1

I have a character driver exposing a character device file under /dev. I'd like to use the huge pages when I map some menory.

MAP_HUGETLB seems to be only available when grouped with MAP_ANONYMOUS or with transparent huge-page but am not interested in it.

mmap(...,MAP_HUGETLB|MAP_ANONYMOUS,..., -1, 0);

How can we implement the huge-pages feature for a character device? Is it already done somewhere?

I didn't find an example the kernel's tree.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Alexis
  • 2,136
  • 2
  • 19
  • 47

2 Answers2

1

This isn't possible. You can only mmap files with MAP_HUGETLB if they reside in a hugetlbfs filesystem. Since /proc is a procfs filesystem, you have no way of mapping those files through huge pages.

You can also see this from the checks performed in mmap by the kernel:

    /* ... */

    if (!(flags & MAP_ANONYMOUS)) { // <== File-backed mapping?
        audit_mmap_fd(fd, flags);
        file = fget(fd);
        if (!file)
            return -EBADF;
        if (is_file_hugepages(file)) { // <== Check that FS is hugetlbfs
            len = ALIGN(len, huge_page_size(hstate_file(file)));
        } else if (unlikely(flags & MAP_HUGETLB)) { // <== If not, MAP_HUGETLB isn't allowed
            retval = -EINVAL;
            goto out_fput;
        }
    } else if (flags & MAP_HUGETLB) { // <== Anonymous MAP_HUGETLB mapping?

    /* ... */

See also:

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • Thanks for the details and the mmap's code! That confirms what I thought, it complicates things, it's a pity. – Alexis Dec 17 '21 at 00:20
  • One more question since you have experience in that, do you confirm, `mmap with MAP_HUGETLB` and `hugetlbfs` are similar? Give the same result? – Alexis Dec 17 '21 at 00:23
  • @Alexis what is similar to what exactly? – Marco Bonelli Dec 17 '21 at 00:25
  • I updated the comment. – Alexis Dec 17 '21 at 00:27
  • 1
    @Alexis not sure I understand your question. Do you want to know if `mmap(MAP_ANONYMOUS|MAP_HUGETLB)` is equivalent to `mmap(MAP_SHARED|MAP_HUGETLB)` with a `fd` which referso to an open file which is inside a `hugetlbfs`? In terms of TLB/page table it's the same situation, but in terms of observable effects those are different things of course (one is file backed and one is not). – Marco Bonelli Dec 17 '21 at 00:31
  • I need to read more about `hugetlbfs`, at first glance I thought it was an API to avoid calling `mmap(MAP_HUGETLB)`. **libhugetlbfs**'s `get_huge_pages()` https://linux.die.net/man/7/libhugetlbfs Forget my question :) thank you again! – Alexis Dec 17 '21 at 00:37
1

This code worked for me, I am aligning an address to 2MB and passing it as hint address for second mmap with MAP_HUGETLB flag. I checked "HugePages_Total" in /proc/meminfo before doing this

#include<stdio.h>
#include<stdlib.h>
#include <sys/mman.h>
#define EIGHTMB 8388608
#define TWOMB 2097152

int main(int argc, char* argv[]){
    int sum = 0;
    char * ptr = (char*)mmap(NULL, EIGHTMB+TWOMB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
     if (ptr == MAP_FAILED){
         printf("error\n");
         exit(0);
     }
    unsigned long align_ptr = (((unsigned long)ptr+TWOMB)>>21)<<21;
    printf("ptr:%p,%lx\n",ptr,align_ptr);
    munmap(ptr, EIGHTMB+TWOMB);
    ptr = (char*)mmap((void*)align_ptr, EIGHTMB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB,-1,0);
    if (ptr == MAP_FAILED){
         printf("error\n");
         exit(0);
     }
    printf("ptr:%p\n",ptr);
    ptr[0] = 'A';
    ptr[4096] = 'B';
    munmap(ptr, EIGHTMB);
    return 0;
}
Arun Kp
  • 392
  • 2
  • 13