How to Access Physical Addresses from User Space in Linux

How to access physical addresses from user space in Linux?

You can map a device file to a user process memory using mmap(2) system call. Usually, device files are mappings of physical memory to the file system.
Otherwise, you have to write a kernel module which creates such a file or provides a way to map the needed memory to a user process.

Another way is remapping parts of /dev/mem to a user memory.

Edit:
Example of mmaping /dev/mem (this program must have access to /dev/mem, e.g. have root rights):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
return 0;
}

off_t offset = strtoul(argv[1], NULL, 0);
size_t len = strtoul(argv[2], NULL, 0);

// Truncate offset to a multiple of the page size, or mmap will fail.
size_t pagesize = sysconf(_SC_PAGE_SIZE);
off_t page_base = (offset / pagesize) * pagesize;
off_t page_offset = offset - page_base;

int fd = open("/dev/mem", O_SYNC);
unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
if (mem == MAP_FAILED) {
perror("Can't map memory");
return -1;
}

size_t i;
for (i = 0; i < len; ++i)
printf("%02x ", (int)mem[page_offset + i]);

return 0;
}

Accessing physical address space using mmap in Linux: passing the correct arguments to mmap

mmap does not take in physical addresses - all these addresses are virtual. The first argument is a hint telling the virtual address where the mapping should be placed.

You do not need the virtual and physical addresses to be identical in order to be able to write at some physical address. Instead you'd just need to translate physical addresses to virtual addresses. What you need to do, however, is to use MAP_SHARED so that any changes you make into memory will be conveyed to /dev/mem and you won't have a private copy.


If you really want to do an identity mapping, then there is a special flag (or two) to mmap that you have to use for this to really work, which you should | with either MAP_PRIVATE or MAP_SHARED.

MAP_FIXED

Don't interpret addr as a hint: place the mapping at exactly that address. addr must be suitably aligned: for most architectures a multiple of the page size is sufficient; however, some architectures may impose additional restrictions. If the memory region specified by addr and
len overlaps pages of any existing mapping(s), then the overlapped part of the existing mapping(s) will be discarded. If the specified address cannot be used, mmap() will fail.

Software that aspires to be portable should use the MAP_FIXED flag with care, keeping in mind that the exact layout of a process's memory mappings is allowed to change significantly between kernel versions, C library versions, and operating system releases. Carefully read the discussion of this flag in NOTES!

This is for example what ld.so uses to load the program at the predefined address

There is a safer version of the flag: MAP_FIXED_NOREPLACE in later Linux kernels, which does not evict the previous mapping if it exists, but returns an error.

How to find the physical address of a variable from user-space in Linux?

First, why would you want to do this? The purpose of modern VM systems is to remove the application programmer from the complexity of physocal memory layout. Gving them each their own uniform address space to make their life easyer.

If you did want to do this you would almost certanly need to use a kernel module. Get the virtual address of the variable in the normal way, use this to index into the processes page tables and read the value you find(the physical address of the frame). Then add the page offset to get the complete physical address. Note you wont be able to use this address while paging is enabled.

(If your lucky you may be able to get the frame address of a VM region from the /proc file system and thus wouldnt require to write a kernel module.)

How can I convert virtual address from user space to physical address?(in linux device driver)

First using virt_to_phys() is only supposed to be used with kernel lowmem(directly maped RAM region) region so you cant get physical address of a user space it's even not allowed even with kernel space regions like vmalloc. only allowed with lowmem region since it's at fixed offset of PAGE_OFFSET.

If I'm correct you try to write directly to physical memory and hope your result will be seen in user space app. If this is what you want there is no way to do that(at least an easy way).


The hack would be like: you will want to view the page tables of the app and record where will be this address be located in physical ram. on x86 page tables address is stored in CR3 register. The next problem is that the CPU is already set in protected mode with PG flag set in CR0 (ie; using paging) which make the MMU read the address as virtual and do the conversion itself to physical(you can't interfere). So to access physical memory you must switch to real mode with paging disabled(which must be if you are will be using real mode). This will probably means that you will have to call BIOS routines to do the hard work for you.

How to access physical memory in linux from userspace?

If you absolutely have to, use the functions mmap and mprotect from the header <unistd.h>
Open /dev/mem



Related Topics



Leave a reply



Submit