persistent memory /dev/dax0.0 mmap in C program

356 views Asked by At

I am trying to mmap Intel's DCPMM and access it using load/store. Currently the persistent memory is used in "devdax" mode and ndctl list shows

[
  {
    "dev":"namespace1.0",
    "mode":"devdax",
    "map":"mem",
    "size":135289372672,
    "uuid":"138d5bcb-8c86-401a-9e70-ee2d60a94cc6",
    "chardev":"dax1.0",
    "align":2097152
  },
  {
    "dev":"namespace3.0",
    "mode":"devdax",
    "map":"mem",
    "size":135289372672,
    "uuid":"f1ac242e-0899-4550-9f00-1506e587322a",
    "chardev":"dax3.0",
    "align":2097152
  },
  {
    "dev":"namespace0.0",
    "mode":"devdax",
    "map":"mem",
    "size":135289372672,
    "uuid":"50640c4d-8a97-4227-a9c8-950dce3b1491",
    "chardev":"dax0.0",
    "align":2097152
  },
  {
    "dev":"namespace2.0",
    "mode":"devdax",
    "map":"mem",
    "size":135289372672,
    "uuid":"eb19f89a-1c06-4b53-ba5a-37c1832a3e92",
    "chardev":"dax2.0",
    "align":2097152
  }
]

I can also see /dev/dax0.0 /dev/dax1.0 /dev/dax2.0 and /dev/dax3.0 But when I am trying to mmap /dev/dax0.0 as mentioned in section 7.6.1. (https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_storage_devices/using-nvdimm-persistent-memory-storage_managing-storage-devices), I am getting "mmap: : Invalid argument" error. This is the program I used for mmap

#define NUM_ENTR (1<<12)

int main(int argc, char* argv[]){
    int fd = open("/dev/dax0.0",O_RDWR);
    printf("fd:%d\n",fd);
    if(fd < 0){
        perror("open:");
        exit(0);
    }
    char * ptr = (char *)mmap(NULL, NUM_ENTR*sizeof(char), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if( ptr == MAP_FAILED){
        perror("mmap: ");
        exit(0);
    }
    close(fd);
    return 0;
}

I looked for documents to mmap the /dev/dax0.0 and use the persistent memory for load/store. Can anyone help me with using persistent memory through mmap

1

There are 1 answers

0
Arun Kp On

I am posting it for the benefit of others (I spend around 4 to 5 hours, so others can save these hours).

After referring to qemu help document says. The following code worked, it seems the mmap needs to be aligned based on the "/dev/dax0.0" alignment requirement, 2M in my case

#define NUM_ENTR (1<<21)

int main(int argc, char* argv[]){
    int fd = open("/dev/dax0.0",O_RDWR);
    printf("fd:%d\n",fd);
    if(fd < 0){
        perror("open:");
        exit(0);
    }
    char * ptr_temp = (char *)mmap(NULL, 2*NUM_ENTR, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    munmap(ptr_temp,2*NUM_ENTR);
    unsigned long addr = (unsigned long)(ptr_temp+NUM_ENTR)&0xffffffffffe00000;
    printf("ptr temp:%p, %lx\n",ptr_temp,addr);
    char * ptr = (char *)mmap((void*)addr, NUM_ENTR*sizeof(char), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if( ptr == MAP_FAILED){
        perror("mmap: ");
        exit(0);
    }
    for(int i=0;i<10;i++){
        ptr[i] = 'A';
    }
    for(int i=0;i<10;i++){
        printf("%c\n",ptr[i]);
    }

    close(fd);
    return 0;
}