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

3

20

I want to find the physical address of a variable defined in a user-space process? Is there any way to do it using root privileges?

Extraditable answered 13/3, 2010 at 23:1 Comment(2)
Probably with /dev/mem?Accessory
Some related information in #5748992Nissensohn
U
-4

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.)

Ultan answered 13/3, 2010 at 23:16 Comment(5)
...and unless you lock the page into memory, that physical address could change at any time.Colossians
You don't need to write a kernel module: as the other examples explain, this is already exposed through /proc/$pid/pagemap.Melanism
It can be interesting in NUMA architectures to know the physical address of variablesDime
"why would you want to do this?" is not an answerKarat
It is a necessary function for heterogeneous systems where some components (eg CPU) use virtual addressing and other components (eg. PCIE attached accelerators) may use physical addressing. They need to be able to communicate addresses between each other somehow...Pneuma
J
24
#include "stdio.h"
#include "unistd.h"
#include "inttypes.h"

uintptr_t vtop(uintptr_t vaddr) {
    FILE *pagemap;
    intptr_t paddr = 0;
    int offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t);
    uint64_t e;

    // https://www.kernel.org/doc/Documentation/vm/pagemap.txt
    if ((pagemap = fopen("/proc/self/pagemap", "r"))) {
        if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) {
            if (fread(&e, sizeof(uint64_t), 1, pagemap)) {
                if (e & (1ULL << 63)) { // page present ?
                    paddr = e & ((1ULL << 54) - 1); // pfn mask
                    paddr = paddr * sysconf(_SC_PAGESIZE);
                    // add offset within page
                    paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1));
                }   
            }   
        }   
        fclose(pagemap);
    }   

    return paddr;
}   
Juxtapose answered 11/3, 2015 at 13:6 Comment(0)
S
21

As partially answered before, normal programs should not need to worry about physical addresses as they run in a virtual address space with all its conveniences. Furthermore, not every virtual address has a physical address, the may belong to mapped files or swapped pages. However, sometimes it may be interesting to see this mapping, even in userland.

For this purpose, the Linux kernel exposes its mapping to userland through a set of files in the /proc. The documentation can be found here. Short summary:

  1. /proc/$pid/maps provides a list of mappings of virtual addresses together with additional information, such as the corresponding file for mapped files.
  2. /proc/$pid/pagemap provides more information about each mapped page, including the physical address if it exists.

This website provides a C program that dumps the mappings of all running processes using this interface and an explanation of what it does.

Statesmanship answered 19/12, 2012 at 10:5 Comment(1)
Minimal example with tests: #17021714Polygamist
U
-4

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.)

Ultan answered 13/3, 2010 at 23:16 Comment(5)
...and unless you lock the page into memory, that physical address could change at any time.Colossians
You don't need to write a kernel module: as the other examples explain, this is already exposed through /proc/$pid/pagemap.Melanism
It can be interesting in NUMA architectures to know the physical address of variablesDime
"why would you want to do this?" is not an answerKarat
It is a necessary function for heterogeneous systems where some components (eg CPU) use virtual addressing and other components (eg. PCIE attached accelerators) may use physical addressing. They need to be able to communicate addresses between each other somehow...Pneuma

© 2022 - 2024 — McMap. All rights reserved.