env/vtophys: store unshifted physical address

Rather than storing the page frame number, just store the full physical
address of each 2 MB page.  This simplifies the lookup code and makes
the map generic (values are inserted and retrieved without any
modification) for future uses.

Change-Id: Ib1081513a0682f6b8b908f3401c00d87b00f484c
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2017-02-21 15:11:04 -07:00
parent ee5ca14e21
commit d1638fb677

View File

@ -31,6 +31,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <inttypes.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
@ -66,13 +67,13 @@
/* Max value for a 16-bit ref count. */
#define VTOPHYS_MAX_REF_COUNT (0xFFFF)
/* Physical page frame number of a single 2MB page. */
/* Physical address of a single 2MB page. */
struct map_2mb {
uint64_t pfn_2mb;
uint64_t paddr_2mb;
};
/* Second-level map table indexed by bits [21..29] of the virtual address.
* Each entry contains the 2MB physical page frame number or SPDK_VTOPHYS_ERROR for entries that haven't
* Each entry contains the 2MB physical address or SPDK_VTOPHYS_ERROR for entries that haven't
* been retrieved yet.
*/
struct map_1gb {
@ -158,14 +159,13 @@ vtophys_get_dpdk_paddr(void *vaddr)
}
static uint64_t
vtophys_get_pfn_2mb(uint64_t vfn_2mb)
vtophys_get_paddr(uint64_t vaddr)
{
uintptr_t vaddr, paddr;
uintptr_t paddr;
struct rte_mem_config *mcfg;
struct rte_memseg *seg;
uint32_t seg_idx;
vaddr = vfn_2mb << SHIFT_2MB;
mcfg = rte_eal_get_configuration()->mem_config;
for (seg_idx = 0; seg_idx < RTE_MAX_MEMSEG; seg_idx++) {
@ -178,11 +178,11 @@ vtophys_get_pfn_2mb(uint64_t vfn_2mb)
vaddr < ((uintptr_t)seg->addr + seg->len)) {
paddr = seg->phys_addr;
paddr += (vaddr - (uintptr_t)seg->addr);
return paddr >> SHIFT_2MB;
return paddr;
}
}
fprintf(stderr, "could not find 2MB vfn 0x%jx in DPDK mem config\n", vfn_2mb);
fprintf(stderr, "could not find vaddr 0x%" PRIx64 " in DPDK mem config\n", vaddr);
return SPDK_VTOPHYS_ERROR;
}
@ -205,7 +205,7 @@ _spdk_vtophys_register_one(uint64_t vfn_2mb)
map_2mb = &map_1gb->map[idx_1gb];
ref_count = &map_1gb->ref_count[idx_1gb];
if (map_2mb->pfn_2mb == SPDK_VTOPHYS_ERROR) {
if (map_2mb->paddr_2mb == SPDK_VTOPHYS_ERROR) {
vaddr = (void *)(vfn_2mb << SHIFT_2MB);
paddr = vtophys_get_dpdk_paddr(vaddr);
if (paddr == RTE_BAD_PHYS_ADDR) {
@ -213,7 +213,7 @@ _spdk_vtophys_register_one(uint64_t vfn_2mb)
return;
}
map_2mb->pfn_2mb = paddr >> SHIFT_2MB;
map_2mb->paddr_2mb = paddr & ~MASK_2MB;
*ref_count = 0;
}
@ -243,14 +243,14 @@ _spdk_vtophys_unregister_one(uint64_t vfn_2mb)
map_2mb = &map_1gb->map[idx_1gb];
ref_count = &map_1gb->ref_count[idx_1gb];
if (map_2mb->pfn_2mb == SPDK_VTOPHYS_ERROR || *ref_count == 0) {
if (map_2mb->paddr_2mb == SPDK_VTOPHYS_ERROR || *ref_count == 0) {
fprintf(stderr, "vaddr %p not registered\n", (void *)(vfn_2mb << SHIFT_2MB));
return;
}
(*ref_count)--;
if (*ref_count == 0) {
map_2mb->pfn_2mb = SPDK_VTOPHYS_ERROR;
map_2mb->paddr_2mb = SPDK_VTOPHYS_ERROR;
}
}
@ -310,7 +310,7 @@ uint64_t
spdk_vtophys(void *buf)
{
struct map_2mb *map_2mb;
uint64_t vaddr, vfn_2mb, pfn_2mb;
uint64_t vaddr, vfn_2mb, paddr_2mb;
vaddr = (uint64_t)buf;
if (vaddr & ~MASK_128TB) {
@ -325,14 +325,19 @@ spdk_vtophys(void *buf)
return SPDK_VTOPHYS_ERROR;
}
pfn_2mb = map_2mb->pfn_2mb;
if (pfn_2mb == SPDK_VTOPHYS_ERROR) {
pfn_2mb = vtophys_get_pfn_2mb(vfn_2mb);
if (pfn_2mb == SPDK_VTOPHYS_ERROR) {
paddr_2mb = map_2mb->paddr_2mb;
if (paddr_2mb == SPDK_VTOPHYS_ERROR) {
uint64_t paddr;
paddr = vtophys_get_paddr(vaddr);
if (paddr == SPDK_VTOPHYS_ERROR) {
return SPDK_VTOPHYS_ERROR;
}
map_2mb->pfn_2mb = pfn_2mb;
/* For now, assume all valid addressess are part of 2MB or larger pages. */
paddr_2mb = paddr & ~MASK_2MB;
map_2mb->paddr_2mb = paddr_2mb;
}
return (pfn_2mb << SHIFT_2MB) | ((uint64_t)buf & MASK_2MB);
return paddr_2mb | ((uint64_t)buf & MASK_2MB);
}