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
andlen
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
How to Send a HTML Email With the Bash Command "Sendmail"
What Happens If You Use the 32-Bit Int 0X80 Linux Abi in 64-Bit Code
Are There Any Standard Exit Status Codes in Linux
Using Openssl to Get the Certificate from a Server
How to Invoke a System Call Via Syscall or Sysenter in Inline Assembly
Command Line Program to Create Website Screenshots (On Linux)
How to Get Terminal'S Character Encoding
How to Set the Gopath Environment Variable on Ubuntu? What File Must I Edit
Print a File, Skipping the First X Lines, in Bash
How to Test If a Variable Is a Number in Bash
How to Make a Program Continue to Run After Log Out from Ssh
What Does the Number in Parentheses Shown After Unix Command Names in Manpages Mean
Have Bash Script Answer Interactive Prompts
How to Generate New Variable Names on the Fly in a Shell Script