How to get physical address of ARM64 Linux page table? - linux-kernel

How can I get the physical address of page table itself?
I tried to use __pa(), virt_to_phys() but it seems to translate to another virtual address.
For example, the address of the page table of the first page is:
0xffffffbf00000000 --> 0x0000003f78800000.
The system has only 5G physical memory.
So, the address must be another virtual address.
How can I get its actual physical address?

Related

QEMU-KVM: Is Guest Physical Address(GBA) same as QEMU-KVM's Virtual Address on the host?

For example, if a process on the guest has data allocated on 0x8000(as in Guest Virtual Memory), and that has been mapped into 0x4000 in Guest Physical Memory Address Space, is the data located on 0x4000 in the virtual memory address space of host-side QEMU-KVM's (sub)process(per VM)? In other words, if I write new code within QEMU's source(so I can use the QEMU-KVM's page table), compile, and run it, then can I access to the data of guest process directly just with the guest's physical memory address matching to the guest virtual memory address?
No, the page table mapping used for the user-space QEMU process is unrelated to either the page tables used by the guest itself for guest virtual -> guest physical address mapping, or to the page tables used by the KVM kernel code for guest physical address -> host physical address mapping for RAM.
When you're writing code in QEMU that needs to access guest memory, you should do so using the APIs that QEMU provides for that, which deal with converting the guest address to a host virtual address for RAM and also with handling the case when that guest address has an emulated device rather than RAM. The QEMU developer internals docs have a section on APIs for loads and stores, and the functions are also documented in doc comments in the header files.
Usually the best advice is "find some existing code in QEMU which is doing something basically the same as what you're trying to do, and follow that as an example".
I'm assuming your question is about x86 platform.
QEMU+KVM use extended page table (EPT) to map host virtual addresses (HVA) to guest physical addresses (GPA). To find HVA corresponding to GPA, you should traverse EPT of your guest.
When you need to read a virtual address from your guest, you can use GDB functions in QEMU source. This snippet will read 4 bytes at virtualAddress in the current executing process in your guest:
uint8_t instr[4];
if( cpu_memory_rw_debug( cpu, virtualAddress, (uint8_t *)instr, sizeof( instr ), 0 ) )
{
printf( "Failed to read instr!\n" );
return;
}
cpu is an CPUState* of a cpu of your guest.
When you want to read an address of a concrete process in your guest, you should set env->cr[3] to CR3 value of this process (env is an CPUX86State*). Dont forget to restore the original value after you finish reading. And of course read memory only when your guest is not executing, otherwise there can be races.

What happens when you lose the virtual address of the page directory?

I'm writing a memory manager for my kernel (32 bit x86)
In the course of this... I'm facing a bit of a dilemma....
Description of virtual memory map:
Identity map of first 4 Mb
Virtual address 0xC0000000 mapped to physical address 0x100000 (Also a 4 Mb map)
My page directory is at physical address 0x9c000.
My page table 1 is at physical address 0x9d000.
My page table 2 is at physical addres 0x9e000.
(I need only two page tables here :) ... These correspond to the identity map and higher memory map respectively)
Bless the identity mapping.... I can safely access my page directory and page tables as if paging wasn't even enabled. This makes it really easy for me to modify page tables,etc.
Now comes the issue: I may remove this identity mapping... If so, I can already imagine problems creeping up..
Eg. I have physical addresses that I want to access... But I can only access virtual ones. In order to map the virtual address to the required physical address, I need to access the page directory. But I have the physical address of the page directory... *I realize that I'm back where I started.
So, I'm guessing there's a need for some permanent mapping (or some sort of identity mapping for tables and the directory) so that I can forget about all this and get on with my life.
But if I map something permanently, I feel that I'm reducing the flexibilty of the program(kernel) in some sort of way.
What's the way one deals with this issue?
What happens when you lose the virtual address of the page directory? You can always get the physical address from cr3, but you have no idea where it's mapped, how to access it, and whatnot. In this case, I don't think one can even change the page directory location using cr3 because you'd be loading a physical address into it, but all that you can view are virtual addresses... It seems like a really scary situation here
Am I missing something?
Don't lose your virtual Page directory address! You need at least a small portion of the page directory at a know physical and a known virtual address (they do not need identity mapped).

Setting up memory pagination

Next, the loader creates a basic page table. This page table maps the 64 MB at the base of virtual memory (starting at virtual address
0) directly to the identical physical addresses. It also maps the same
physical memory starting at virtual address LOADER_PHYS_BASE, which
defaults to 0xc0000000 (3 GB). The Pintos kernel only wants the latter
mapping, but there's a chicken-and-egg problem if we don't include the
former: our current virtual address is roughly 0x20000, the location
where the loader put us, and we can't jump to 0xc0020000 until we turn
on the page table, but if we turn on the page table without jumping
there, then we've just pulled the rug out from under ourselves.
A citation comes from: https://web.stanford.edu/~ouster/cgi-bin/cs140-winter16/pintos/pintos_6.html
I think that I don't understand exactly what does it is written above.
My issues:
Let's assume that kernel was loaded at 0x20000 physical address by bootloader. From what I understand two different virtual address are mapped to the same place- to the kernel. The first, direct mapping: ~0x20000 -> ~0x20000. And the second ~0xc0000000 -> ~0x20000. But, why there is need to use two mappings?
I cannot see why the page table ( and page directory) must be mapped by identity.
Please explain.

Mapping a page with a specific address

I'm trying to map a virtual memory page using VirtualAlloc, but it's an specific address outside 8TB Windows 7 64 bits allowed range, i've read at Windows Internals book this address range is used
for "page table self mapping structures", anyway,is there any way i could map a memory page with the 0x7ffffffff000 address?

Is there any kernel function to convert a physical page to its virtual address?

I get one huge page by struct page *page=alloc_pages(), and I want to verify if it is a 2MB page. Is there any kernel function that I can use to convert this page to its virtual address?
For the pages allocated with alloc_page() or the like, you can use page_address() to obtain their virtual addresses (see <linux/mm.h>).

Resources