flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > Changing memory map in LONG MODE |
Author |
|
Feryno 10 Sep 2008, 14:34
it is even possible to change the virtual memory of the running kernel on-the-fly - e.g. you are at virtual memory 80000 and you want to change it to FFFFFFFF00080000 (kernel stays at the same physical memory, you just add new entries into paging tables - at this point the physical memory is mapped twice into 2 different virtual addresses - then make a long jump to new virtual address and at the end remove the old entries from paging tables)
well back to your question you have written that you kernel is running in identity mapped memory of size 8 MB (virtual address = physical address), you know where you have PML4, PDP, PD, several PTs (no one PT if you mapped all 8 MB using 4 large pages of 2 MB) you want to map just one 2 MB page e.g. at physical memory (RAM) 6 GB PA = 6*1024*1024*1024 and you want to map that 2 MB physical memory page into virtual address space 8MB - 10MB VA = 8*1024*1024 it is possible to do it in just 2 instructions in assembler ! assume you know where you have mapped your PD - at virtual address Z which is somewhere inside your 8 MB virtual memory then do it in this way: mov rax,PA + 10000011b ; 10000011b = bit 7 set (PD.PSE=1, that means 2 MB pages and PD is the last level), bit 1 set (writeable), bit 0 set (Present) t = (VA shr 21) and 111111111b ; extract bits 29-21 of virtual address mov [Z + t*8],rax ; if the PA is below 4 GB, then it is possible to do that mapping using just 1 assembler instruction !!!!!!!!!!!!!!!!! ; mov qword [Z + t*8],(PA + 10000011b) after the last instruction, you have 2 extra MB of mapped memory, you can create additional paging tables there e.g. you want to map 1 page of 4 kB from physical memory 7GB and you want it become the virtual address FFFFFFFF05000000h assume your PML4 is at virtual address X somewhere inside your 8 MB kernel and its virtual address = its physical address PA2 = 7*1024*1024*1024 ; address in RAM VA2 = FFFFFFFF05000000h ; returned virtual address 1 empty 2 MB page is mapped at VA=8*1024*1024 and it is in physical memory PA=6*1024*1024*1024 you create 1 new PDP at the first 4 kB memory block at 6GB+0*4kB = PA, 1 new PD at the second 4 kB memory block 6GB+1*4kB = PA+1000h, 1 new PT at the third 4 kB memory block 6GB+2*4kB = PA+2000h and finally put just 1 entry (PTE) into PT mov rax,PA + 11b ; 11b means bit 1 set (writeable), bit 0 set (present) t = (VA2 shr 39) and 111111111b (extract bits 47-39 of virtual address) mov [X + t*8],rax ; write PML4E into PML4 (bits 51-12 of PML4E = the pointer into physical memory base of next level which is PDP table) mov rax,PA+1000h + 11b t = (VA2 shr 30) and 111111111b (extract bits 38-30 of virtual address) mov [VA + t*8],rax ; write PDPE into PDP mov rax,PA+2000h + 11b t = (VA2 shr 21) and 111111111b (extract bits 29-21 of virtual address) mov [VA+1000h + t*8],rax ; write PDE into PD mov rax,PA2 + 11b t = (VA2 shr 12) and 111111111b (extract bits 20-12 of virtual address) mov [VA+2000h + t*8],rax ; put PTE (PT entry) into PT after the last instruction, new virtual address range FFFFFFFF05000000h-FFFFFFFF05000FFFh appears and when you write a byte into virtual address FFFFFFFF05000000h then the byte is written into physical address (RAM) at position PA2 = 7GB |
|||
10 Sep 2008, 14:34 |
|
revolution 10 Sep 2008, 15:36
Feryno wrote: it is even possible to change the virtual memory of the running kernel on-the-fly - e.g. you are at virtual memory 80000 and you want to change it to FFFFFFFF00080000 (kernel stays at the same physical memory, you just add new entries into paging tables - at this point the physical memory is mapped twice into 2 different virtual addresses - then make a long jump to new virtual address and at the end remove the old entries from paging tables) |
|||
10 Sep 2008, 15:36 |
|
Feryno 11 Sep 2008, 12:33
if you want to purge only 1 page, then use:
invlpg [address_of_page] e.g. lea rax,[address_anywhere_inside_of_page] invlpg [rax] if the address is not further than 2GB from RIP, then you can use directly invlpg [address_of_page] which is done by FASM using RIP-relative addressing invlpg [rip+-difference] (difference is limited to be signed dword, so the +- 2 GB limit comes from here) if you want to purge all nonglobal pages, then use: mov rax,cr3 mov cr3,rax if you want (usually very rarely or almost never) to purge all global pages (bit 8. of entries in the last level of translation tables is set and CR4.PGE bit 7. is set), then use: (toggling bit 7. of CR4 - CR4.PGE) mov rax,cr4 mov rcx,rax and al,not (1 shl 7) mov cr4,rax ; this instruction flushes all global and nonglobal pages out of TLB (but note for Intel CPUs, manual says: works on all P4, Xeon, P6 family... and we shouldn't depend on this functionality in all Intel64 processors...) mov cr4,rcx ; this restores cr4 back global pages are sometimes very necessary, e.g. when your kernel switches to a new task with new CR3, the kernel must load new translation tables without losing translation of critical kernel pages (to prevent the code doing task switching from disappearing from the virtual memory translation mechanism after executing mov cr3,reg64). After loading new CR3, all nonglobal pages disappear from the virtual memory translation mechanism, only global pages stays in TLB so your kernel code is able continue its execution if the critical kernel pages doing task switching are global (code, stack, system data) if you want to flush out of TLB only 1 global page, then use invlpg [address] |
|||
11 Sep 2008, 12:33 |
|
Adan 11 Sep 2008, 21:06
Is the argument of invlpg a physycal o virtual address?, could you give an example please?
Supose I want to invalidate a page frame mapped at virtual address 0x2000, how this command would be? Thanks. |
|||
11 Sep 2008, 21:06 |
|
revolution 12 Sep 2008, 01:00
Adan: To save you having to wait for an answer to be posted here you can also check out the excellent Intel and/or AMD programmers manuals (Google them). These comprehensive documents give the details of every instruction available within the CPUs. I thoroughly recommend you download a copy for your future reference.
|
|||
12 Sep 2008, 01:00 |
|
Feryno 12 Sep 2008, 19:37
invlpg uses virtual address, so do this:
mov eax,2000h invlpg [rax] if the mapped page has only 4 kB (in your sample it can't have 2 MB size) the same may be done using mov eax,2FFFh \ invlpg [rax]... it doesn't matter whether you invalidate the first or the last or any byte in the middle of virtual memory page, you also needn't to worry whether the page is 2 MB or 4 kB) mapped addresses are usually stored somewhere (to unmap them later), so in that case you must do: mov rax,qword [stored_virtual_addr] invlpg [rax] note that using invlpg qword [stored_virtual_addr] is wrong and a big mistake !!! btw0 the manual doesn't say it exactly (Intel: The source operand is a memory address... AMD: Invalidate the TLB entry for the page containing a specified memory location...) so this is the reason why I did you direct answer (I hope correct, I didn't know the answer after reading manuals, so I did tests months ago when I needed that to implement in my work and the INVLPG behaved according virtual memory address, not physical). If I had used my brain more before those of experiments, I would had the same result (plus faster as a benefit) because it looks more logical, it is necessary to purge virtual address, not physical...) btw1 instructions using physical address are very rare mov cr3,reg64 \ mov reg64,cr3 \ mov reg64,cr2 mov rax,physical_address \ mov qword [rsp],rax \ vmxon qword [rsp] and similar instructions of virtualization and you also use physical address when constructing virtual memory translation tables this is almost everything usefull with physical address under long mode. There are perhaps another instructions using physical addresses but I can't remember them from my head at this night time here. If somebody knows such instruction, let post it here. btw2 The famous manuals are very huge and split into few separate pdf files - each of size about 1-5 MB http://developer.amd.com/documentation/guides/Pages/default.aspx instructions are here: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf http://www.intel.com/products/processor/manuals/index.htm instructions A-M are here: http://download.intel.com/design/processor/manuals/253666.pdf instructions N-Z are here: http://download.intel.com/design/processor/manuals/253667.pdf btw3 the intel changes manuals very frequently (the last change was after about half a year and the most of changes were just in the virtualization technology) |
|||
12 Sep 2008, 19:37 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.