cirosantilli / linux-kernel-module-cheat

The perfect emulation setup to study and develop the Linux kernel v5.4.3, kernel modules, QEMU, gem5 and x86_64, ARMv7 and ARMv8 userland and baremetal assembly, ANSI C, C++ and POSIX. GDB step debug and KGDB just work. Powered by Buildroot and crosstool-NG. Highly automated. Thoroughly documented. Automated tests. "Tested" in an Ubuntu 24.04 host.
https://cirosantilli.com/linux-kernel-module-cheat
GNU General Public License v3.0
4.21k stars 605 forks source link

virt_to_phys_user to print a physical address for a mmap #146

Open balaji-ch opened 3 years ago

balaji-ch commented 3 years ago

Hi, Thanks a lot for the codes that you are sharing. It is helping me to understand Linux better. 🐧

(All these experiments are on Ubuntu VM) I have used linux-kernel-module-cheat/userland/virt_to_phys_user.c to print a physical address of a variable like this

    int var = 42;
    pid = getpid();//strtoull(argv[1], NULL, 0);
    vaddr = (uintptr_t)&var;//strtoull(argv[2], NULL, 0);

and I get some reasonable values for virtual address, page frame number and physical address as

virtual address , Page frame no, physical address 0x55e451c272a0, 0x3d4a27, 0x3d4a272a0

But when I use it for a mmap I am getting 0 as physical address.

(for this I have compiled the kernel 5.9 with enabling CMA and making CONFIG_STRICT_DEVMEM=n dmesg | cma [ 0.068544] cma: Reserved 64 MiB at 0x000000021bc00000

)

fd = open("/dev/mem", O_RDWR | O_SYNC);
vaddr = mmap(0, 64*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x000000021bc00000);

virtual address , Page frame no, physical address 0x7fd5fffb3000, 0x0, 0x0

Does this program needs some modification for mmap's physical address ? or is there something I am missing ?

cirosantilli commented 3 years ago

Hi Balaji,

So you want to do a mmap and then get its physical address is that right?

But are you trying to the the physical address from:

vaddr = mmap(0, 64*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x000000021bc00000);

by searching for vaddr to /proc/%ju/pagemap?

If so, I'm not sure that can work, since using /dev/mem for mmap makes mmap enter the magic physical address mode which might not have any corresponding virtual address (presumably implemented by giving the /dev/mem file a custom mmap behaviour with file operations: https://cirosantilli.com/linux-kernel-module-cheat/#file-operations )

balaji-ch commented 3 years ago

So, even though it does not have any corresponding virtual address. Writing to vaddr will reflect in the /dev/mem for example vaddr[5000] = 42 will reflect in0x000000021bc00000+5000 ?

cirosantilli commented 3 years ago

So, even though it does not have any corresponding virtual address. Writing to vaddr will reflect in the /dev/mem for example vaddr[5000] = 42 will reflect in0x000000021bc00000+5000 ?

Yes, I think this is what happens when using the /dev/mem magic mmap.

balaji-ch commented 3 years ago

Thank you for your swift replies. AlsoI have one more question, In many examples thatI have seen, the size was always 1 page table. Can we use. 64 MiB for sizes?

cirosantilli commented 3 years ago

You mean the mmap size as in mmap(0, 64*1024*1024? I think any size should be fine. man mmap does not seem to constrain it to even be a multiple of pages.man mmap also mentions MAP_HUGETLB which might be related to what you have in mind.

balaji-ch commented 3 years ago

In many examples that mmap a physical memory I have seen the size was page_size in general.

for instance here https://github.com/Digilent/Petalinux-Arty-Z7-20/blob/master/Arty-Z7-20/project-spec/meta-user/recipes-apps/peekpoke/files/peek.c

ptr=mmap(NULL,page_size,PROT_READ,MAP_SHARED,fd,(addr & ~(page_size-1)));

So, I was wondering if there is a limitation for mmaping physical memory.