None
None

Reputation: 2433

How to implement MAP_HUGETLB in a character device driver?

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.

Upvotes: 1

Views: 1168

Answers (2)

Arun Kp
Arun Kp

Reputation: 422

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;
}

Upvotes: 1

Marco Bonelli
Marco Bonelli

Reputation: 69276

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:

Upvotes: 1

Related Questions