Instantly Entry Your Bodily Reminiscence (dev/mem)
“/dev/mem” is a personality machine file, picture of the principle reminiscence of system. It permits to instantly entry any phys tackle.
2.1 Requisites
To make use of /dev/mem, your kernel should be configured with “CONFIG_STRICT_DEVMEM=n”, or it stop entry from even privileged person.
- “CONFIG_STRICT_DEVMEM=y”, the default kernel configuration basically, disallows to entry RAM space through /dev/mem or solely permits first 1MB measurement of RAM
FYI: “CONFIG_IO_STRICT_DEVMEM=y”, disallows to entry register through dev/mem
2.2 Let’s code
To begin with, open dev/mem machine file and map the phys tackle we’re fascinated with. Be aware that the phys tackle ought to be page-aligned. Relying on request, learn or write worth to the mapped tackle. To keep away from a code sequence optimization from compiler, use unstable
if you learn or write.
int mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
void *map_base = mmap(NULL,
PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
mem_fd,
phys_addr); // phys_addr ought to be page-aligned.
void *virt_addr = (char *)map_base + offset_in_page;
if (is_read) {
read_result = *(unstable uint64_t*)virt_addr;
} else { // write
*(unstable uint64_t*)virt_addr = write_value;
}
Great tool: busybox.
For those who instantly use RAM, the reminiscence may be cached by the CPU which probably incurs cache coherence drawback.
- Whenever you write, the precise worth couldn’t be written to the reminiscence but however CPU cache.
- We don’t know when will probably be flushed.
State of affairs: I applied kernel module that allocates pages by alloc_pages (low-level web page request mechanism). When user-space utility requested, the module allocates the web page and passes its phys tackle to the user-space. The applying begins to put in writing one thing into the allotted web page by utilizing /dev/mem.
Commentary: When writing some values through /dev/mem, it appears the phys reminiscence is corrupted after the write is completed as follows.
Guess: It appears that evidently phys reminiscence the place we attempt to write was cached earlier than. Then we write it instantly utilizing dev/mem which bypasses the CPU cache and later, the cache is flushed which corrupts the information we wrote. This can be affected by different cores as effectively when the machine has a number of cores.
Troubleshooting:
i) flip off all the opposite cores aside from the principle core (cpu0) which appears work (no knowledge corruption; no flush from different cores)
echo 0 | sudo tee /sys/gadgets/system/cpu/cpu1/on-line
ii) map the allotted phys reminiscence as DMA reminiscence, which prevents cached entry.
struct web page *p = alloc_pages(gfp, pool->order);
dma_addr_t dma_addr = dma_map_page(dev, p, 0, (PAGE_SIZE << pool->order), DMA_BIDIRECTIONAL);
Be aware: Relying on the reminiscence area the phys tackle you attempt to entry, the mapping is completed with both “pgprot_noncached” or “pgprot_writecombined”. For example, MMIO area is mapped as noncached
whereas regular reminiscence area as writecombined.
It additionally depends upon the your kernel arch, so look into how it’s applied in your kernel supply code, “driver/char/ mem.c”.