简而言之,我在内核中有一个物理地址0x250000000
(9,932,111,872 或),它显然与 4kB(页面大小)对齐。当我使用内核__va()
函数获取内核虚拟地址时,我得到了类似的内容0xf570660f
(每次启动时都不同),它没有与 4kB 对齐。
我使用的是 64 位系统,因此没有 HIGHMEM,并且我认为由于线性内存模型,4kB 对齐的物理地址的虚拟地址也应该是 4kB 对齐的。我错过了什么?虚拟地址不应该是吗phys_addr + PAGE_OFFSET
?或者是sparsemem的影响?但也许它也应该是 4kB 对齐的?
以下是更多详细信息:
我的工作环境是在 x86 64 位 QEMU VM 上。我正在尝试在模式下使用 PMEMDEV-DAX
作为普通内存。我可以得到它的物理起始地址(0x250000000
),已经确认是正确的。然后我需要将它转移到内核空间中的虚拟地址,以便我可以根据需要使用它。这是一些代码:
static long nvpc_map_whole_dev(struct dax_device *dax_dev, void **kaddr, pfn_t *pfn)
{
// get the device
struct dev_dax_nvpc *dax_nvpc = (struct dev_dax_nvpc *)dax_get_private(dax_dev);
// get the virtual address and the pfn_t
*kaddr = __va(dax_nvpc->phys_start);
*pfn = phys_to_pfn_t(dax_nvpc->phys_start, PFN_MAP);
pr_info("[NVPC DEBUG]: paddr %#llx kaddr %p pfn %lu\n", dax_nvpc->phys_start, *kaddr, pfn_t_to_pfn(*pfn));
pr_info("[NVPC DEBUG]: kaddr-paddr %#llx\n", __pa(*kaddr));
return PHYS_PFN(dax_nvpc->size);
}
这是我得到的结果:
如图所示, 、paddr
dax_nvpc->phys_start
、 、pfn
都是正确的。但kaddr
(虚拟地址)让我感到困惑。然后,当我将其传输kaddr
回物理地址(下一个输出行)时,结果是正确的。
更重要的是,我可以对内存从kaddr
到进行任何操作kaddr + dax_nvpc->size
,没有页面错误。
谁能告诉我为什么虚拟地址不是 4kB 对齐的?我在某个地方是不是傻瓜?此外,我可以做些什么来确保虚拟地址也与页面对齐吗?