On a ARM based system running Linux, I have a device that's memory mapped to a physical address. From a user space program where all addresses are virtual, how can I read content from this address?
Linux. Open a terminal and use the ifconfig command. The MAC address will be listed next to HWaddr. If your Linux OS does not have the ifconfig command, you may also use the ip addr command.
Whilst a user-space program is not allowed to access kernel memory, it is possible for the kernel to access user memory. However, the kernel must never execute user-space memory and it must also never access user-space memory without explicit expectation to do so.
Even the kernel has no direct access to physical memory in the way your are thinking. Basically the kind of memory you seem to imagine (linear memory with flat addressing) is something that is constructed by the kernel (from physical memory banks) and exported, it doesn't "exist".
busybox devmem
busybox devmem is a tiny CLI utility that mmaps /dev/mem.
You can get it in Ubuntu with: sudo apt-get install busybox
Usage: read 4 bytes from the physical address 0x12345678:
sudo busybox devmem 0x12345678 Write 0x9abcdef0 to that address:
sudo busybox devmem 0x12345678 w 0x9abcdef0 Source: https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85
mmap MAP_SHARED
When mmapping /dev/mem, you likely want to use:
open("/dev/mem", O_RDWR | O_SYNC); mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...) MAP_SHARED makes writes go to physical memory immediately, which makes it easier to observe, and makes more sense for hardware register writes.
CONFIG_STRICT_DEVMEM and nopat
To use /dev/mem to view and modify regular RAM on kernel v4.9, you must fist:
CONFIG_STRICT_DEVMEM (set by default on Ubuntu 17.04)nopat kernel command line option for x86IO ports still work without those.
See also: mmap of /dev/mem fails with invalid argument for virt_to_phys address, but address is page aligned
Cache flushing
If you try to write to RAM instead of a register, the memory may be cached by the CPU: How to flush the CPU cache for a region of address space in Linux? and I don't see a very portable / easy way to flush it or mark the region as uncacheable:
So maybe /dev/mem can't be used reliably to pass memory buffers to devices?
This can't be observed in QEMU unfortunately, since QEMU does not simulate caches.
How to test it out
Now for the fun part. Here are a few cool setups:
volatile variable on an userland process/proc/<pid>/maps + /proc/<pid>/pagemap devmem, and watch the userland process reactkmalloc virt_to_phys and pass it back to userlanddevmem devmem to write to the registerprintfs come out of the virtual device in responseBonus: determine the physical address for a virtual address
Is there any API for determining the physical address from virtual address in Linux?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With