C 内核驱动程序中对hugepages的顺序访问

C 内核驱动程序中对hugepages的顺序访问,c,memory,linux-kernel,huge-pages,C,Memory,Linux Kernel,Huge Pages,我在一个使用hugepages支持的缓冲区的驱动程序中工作,我发现hugepages的顺序性存在一些问题 在用户空间中,程序使用mmapsyscall分配一个由hugepages支持的大缓冲区。然后通过ioctl调用将缓冲区传送给驾驶员。驱动程序使用get\u user\u pages函数获取该缓冲区的内存地址 当缓冲区大小为1GB(1HugePage)时,这一点非常有效get\u user\u pages返回很多页面(ground\u PAGE\u SIZE/PAGE\u SIZE),但它们都

我在一个使用hugepages支持的缓冲区的驱动程序中工作,我发现hugepages的顺序性存在一些问题

在用户空间中,程序使用
mmap
syscall分配一个由hugepages支持的大缓冲区。然后通过
ioctl
调用将缓冲区传送给驾驶员。驱动程序使用
get\u user\u pages
函数获取该缓冲区的内存地址

当缓冲区大小为1GB(1HugePage)时,这一点非常有效
get\u user\u pages
返回很多页面(
ground\u PAGE\u SIZE/PAGE\u SIZE
),但它们都是连续的,所以没有问题。我只是用
page\u address
抓取第一页的地址,然后处理它。当另一个程序在char设备上执行
mmap
调用时,驱动程序还可以使用
remap\u pfn\u range
将该缓冲区映射回用户空间

然而,当缓冲区由多个hugepage支持时,事情就变得复杂了。内核似乎可以返回一个由非顺序hugepages支持的缓冲区。也就是说,如果hugepage池的布局是这样的

+------+------+------+------+
| HP 1 | HP 2 | HP 3 | HP 4 |
+------+------+------+------+
,对hugepage备份缓冲区的请求可以通过保留HP1和HP4,或者HP3和HP2来实现。这意味着,在最后一种情况下,当我获取带有
get_user_pages
的页面时,第0页的地址实际上是第262.144页(下一个hugepage的页眉)地址之后的1GB

有没有办法对这些页面的访问进行排序?我尝试对地址进行重新排序,以找到较低的地址,这样我就可以使用整个缓冲区(例如,如果内核给我一个由HP3支持的缓冲区,我将HP2用作HP2的基地址),但这似乎会扰乱用户空间中的数据(重新排序的缓冲区中的偏移量0可能是用户空间缓冲区中的偏移量1GB)

TL;DR:给定>1个无序的hugepages,有没有办法在Linux内核驱动程序中按顺序访问它们


顺便说一句,我正在使用3.8.0-29-generic内核的Linux机器上工作。

使用CL建议的函数,我能够重新映射内存,以便可以顺序地访问它,而不受映射的hugepages数的影响。我将代码留在这里(不包括错误控制),以防它对任何人都有帮助

struct page** pages;
int retval;
unsigned long npages;
unsigned long buffer_start = (unsigned long) huge->addr; // Address from user-space map.
void* remapped;

npages =  1 + ((bufsize- 1) / PAGE_SIZE); 

pages = vmalloc(npages * sizeof(struct page *));

down_read(&current->mm->mmap_sem);
retval = get_user_pages(current, current->mm, buffer_start, npages,
                     1 /* Write enable */, 0 /* Force */, pages, NULL);
up_read(&current->mm->mmap_sem);    

nid = page_to_nid(pages[0]); // Remap on the same NUMA node.

remapped = vm_map_ram(pages, npages, nid, PAGE_KERNEL);

// Do work on remapped.

缓冲区是按用户空间分配的吗?不,这不是必需的,但我没有在内核驱动程序中找到一个明确的方法来完成。而且,这种方法让我们可以更容易地选择不同的hugepage大小。为什么你首先关心pysical地址?你在做DMA吗?好的,你关心什么ut是页面的内核虚拟地址。除非重新映射页面,否则无法保证页面是连续的,但是
vm\u map\u ram
似乎无法处理大型页面。我认为它总是会创建4KB的页面表条目。如果它有效,请创建一个答案。