From c93b418730a5f2b1f3f955b83f3c7fa746f25c5f Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Tue, 13 Nov 2018 17:43:46 +0100 Subject: [PATCH] memory: fix contiguous memory calculation for unaligned buffers We assumed spdk_mem_map_translate() translates only 2MB-aligned addresses, but that's not true. Both vtophys and NVMf can use it with any user-provided address and that breaks our contiguous memory length calculations. Right now each buffer appeared to have the first n * 2MB of memory always contiguous. This is a bugfix for NVMf which does check the mapping length internally. It will also become handy when adding the similar functionality to spdk_vtophys(). Change-Id: I3bc8e0b2b8d203cb90320a79264effb7ea7037a7 Signed-off-by: Darek Stojaczyk Reviewed-on: https://review.gerrithub.io/433076 (master) Reviewed-on: https://review.gerrithub.io/435691 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- lib/env_dpdk/env_internal.h | 1 + lib/env_dpdk/memory.c | 6 ++++-- test/env/memory/memory_ut.c | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/env_dpdk/env_internal.h b/lib/env_dpdk/env_internal.h index d95084ead..66f4a7a78 100644 --- a/lib/env_dpdk/env_internal.h +++ b/lib/env_dpdk/env_internal.h @@ -68,6 +68,7 @@ extern struct rte_pci_bus rte_pci_bus; #define SHIFT_4KB 12 /* (1 << 12) == 4KB */ #define MASK_4KB ((1ULL << SHIFT_4KB) - 1) +#define VALUE_4KB (1 << SHIFT_4KB) struct spdk_pci_enum_ctx { struct rte_pci_driver driver; diff --git a/lib/env_dpdk/memory.c b/lib/env_dpdk/memory.c index eaeccb903..9ab730a7a 100644 --- a/lib/env_dpdk/memory.c +++ b/lib/env_dpdk/memory.c @@ -57,6 +57,8 @@ #define MAP_256TB_IDX(vfn_2mb) ((vfn_2mb) >> (SHIFT_1GB - SHIFT_2MB)) #define MAP_1GB_IDX(vfn_2mb) ((vfn_2mb) & ((1ULL << (SHIFT_1GB - SHIFT_2MB)) - 1)) +#define _2MB_OFFSET(ptr) (((uintptr_t)(ptr)) & (VALUE_2MB - 1)) + /* Page is registered */ #define REG_MAP_REGISTERED (1ULL << 62) @@ -612,9 +614,9 @@ spdk_mem_map_translate(const struct spdk_mem_map *map, uint64_t vaddr, uint64_t return map->default_translation; } - cur_size = VALUE_2MB; + cur_size = VALUE_2MB - _2MB_OFFSET(vaddr); if (size != NULL) { - *size = VALUE_2MB; + *size = cur_size; } map_2mb = &map_1gb->map[idx_1gb]; diff --git a/test/env/memory/memory_ut.c b/test/env/memory/memory_ut.c index 39a89a102..b7fbbf71d 100644 --- a/test/env/memory/memory_ut.c +++ b/test/env/memory/memory_ut.c @@ -257,6 +257,12 @@ test_mem_map_translation(void) CU_ASSERT(addr == 0); CU_ASSERT(mapping_length == VALUE_2MB * 3) + /* Translate an unaligned address */ + mapping_length = VALUE_2MB * 3; + addr = spdk_mem_map_translate(map, VALUE_4KB, &mapping_length); + CU_ASSERT(addr == 0); + CU_ASSERT(mapping_length == VALUE_2MB * 3 - VALUE_4KB); + /* Clear translation for the middle page of the larger region. */ rc = spdk_mem_map_clear_translation(map, VALUE_2MB, VALUE_2MB); CU_ASSERT(rc == 0);