└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Translate Virtual Address To Physical Address 2 | 3 | The followings are some ways to translate a virtual address to the corresponding physical address, if exist. 4 | 5 | Step 1. Walk the page tables to get `pte_t *`. 6 | 7 | ```C 8 | // struct mm_struct *mm : The memory descriptor of the current process. 9 | // unsigned long address: The virtual address to be translated. 10 | pgd_t *pgd = pgd_offset(mm, address); 11 | if (!pgd_none(*pgd) && !pgd_bad(*pgd)) { 12 | pud_t *pud = pud_offset(pgd, address); 13 | if (!pud_none(*pud) && !pud_bad(*pud)) { 14 | pmd_t *pmd = pmd_offset(pud, address); 15 | if (!pmd_none(*pmd) && !pmd_bad(*pmd)) { 16 | pte_t *pte = pte_offset_map(pmd, address); 17 | if (!pte_none(*pte)) { 18 | // now you get a pointer pointing to a pte entry! 19 | } 20 | pte_unmap(pte); 21 | } 22 | } 23 | } 24 | ``` 25 | 26 | Step 2. 27 | 28 | - A) Calculate the bits directly. 29 | 30 | ```C 31 | // Assume it is on 32-bit machine with 4 KB pages. 32 | unsigned long phys = pte_val(*pte) & 0xfffff000 + address & 0x00000fff; 33 | ``` 34 | 35 | - B) With the help of a page descriptor. 36 | 37 | ```C 38 | struct page *pg = pte_page(*pte); 39 | unsigned long phys = page_to_phys(pg); 40 | ``` 41 | 42 | ## Userspace: 43 | 44 | `cat /proc//maps` to get virtual address intervals. 45 | 46 | `xxd /proc//pagemap` to get virtual - physical address mappings. 47 | [documention](https://www.mjmwired.net/kernel/Documentation/vm/pagemap.txt) 48 | 49 | 50 | ## Others: 51 | 52 | - `virt_to_page(unsigned long address)` seems to be a faster way to get `struct page*`, but you have to make sure the return value is valid. ([code](https://elixir.free-electrons.com/linux/v3.9/source/arch/x86/include/asm/page.h#L63)) 53 | 54 | - `virt_to_phys(volatile void *address)` is only suitable for addresses directly mapped or mapped by kmalloc. ([code](https://elixir.free-electrons.com/linux/v3.9/source/arch/x86/include/asm/io.h#L111)) 55 | 56 | 57 | ## Reference: 58 | - Understanding the Linux Kernel 3rd (Daniel P. Bovet, Marco Cesati), Sections 2.5, 8.1, 9.2, etc. 59 | - [page_to_phys](https://elixir.free-electrons.com/linux/v3.9/source/arch/x86/include/asm/io.h#L137) from 60 | - How to get the physical address from the logical one in a Linux kernel module? [Stack Overflow](https://stackoverflow.com/questions/6252063/how-to-get-the-physical-address-from-the-logical-one-in-a-linux-kernel-module) 61 | - How to find the physical address of a variable from user-space in Linux? [Stack Overflow](https://stackoverflow.com/questions/2440385/how-to-find-the-physical-address-of-a-variable-from-user-space-in-linux/13949855) 62 | --------------------------------------------------------------------------------