helos1/memory/paging_modeswitch.S

87 lines
3.0 KiB
ArmAsm
Raw Normal View History

2021-10-10 14:39:17 +08:00
format elf64
section '.text' executable
; Details on Control Registers and MSRs can be found here:
; https://wiki.osdev.org/CPU_Registers_x86-64
; x64fastcall void paging_modeswitch_4LevelPaging(void* pml4, int pcid)
;
; This function assumes that the program is now in 64-bit mode (long mode).
; Paging(CR0.PG) in general and long mode (MSR EFER.LME) must already be enabled in this state.
;
; Input: (void* rcx, int rdx)
; Clobbers: rax, flags
public paging_modeswitch_4LevelPaging
paging_modeswitch_4LevelPaging:
; 4 Level paging: CR0.PG (bit 31) = 1 (Protected mode enable)
; CR4.PAE (bit 05) = 1 (PAE enable)
; MSR IA32_EFER.LME (bit 10) = 1 (IA32e 64-bit mode enable)
; CR4.LA57 (bit 12) = 0 (4-level paging instead of 5)
; We only need to set CR4.LA57
; Let's also set CR4.PCIDE(bit 17)=1, enabling process-context identifiers
mov rax, cr0
and rax, 0xFFFFFFFFFFFFEFFF ; unset CR4.LA57
or rax, 0x20000 ; set CR4.PCIDE
mov cr0, rax
and rdx, 0xFFF ; take only the 11:0 bits of the PCID
or rcx, rdx ; construct the full CR3
mov cr3, rcx ; set CR3, invalidate all TLB cache
ret
; x64fastcall void paging_modeswitch_4LevelPagingNX(void* pml4, int pcid)
;
; This function assumes that the program is now in 64-bit mode (long mode).
; Paging(CR0.PG) in general and long mode (MSR EFER.LME) must already be enabled in this state.
;
; This function also sets the IA32_EFER.NXE bit, enabling No-Execute feature.
;
; Input: (void* rcx, int rdx)
; Clobbers: rax, r8, r9, flags
public paging_modeswitch_4LevelPagingNX
paging_modeswitch_4LevelPagingNX:
; 4 Level paging: CR0.PG (bit 31) = 1 (Protected mode enable)
; CR4.PAE (bit 05) = 1 (PAE enable)
; MSR IA32_EFER.LME (bit 10) = 1 (IA32e 64-bit mode enable)
; CR4.LA57 (bit 12) = 0 (4-level paging instead of 5)
; We only need to set CR4.LA57
; Let's also set CR4.PCIDE(bit 17)=1, enabling process-context identifiers
mov rax, cr0
and rax, 0xFFFFFFFFFFFFEFFF ; unset CR4.LA57
or rax, 0x20000 ; set CR4.PCIDE (bit 17)
mov cr0, rax
; save rcx and rdx, RDMSR/WRMSR uses these
mov r8, rcx
mov r9, rdx
mov ecx, 0xC0000080 ; operate on the IA32_EFER MSR
rdmsr ; read the MSR into edx:eax
or eax, (1 shl 11) ; set No-Execute Enable (bit 11)
wrmsr ; write the MSR back
; restore rcx and rdx
mov rcx, r8
mov rdx, r9
and rdx, 0xFFF ; take only the 11:0 bits of the PCID
or rcx, rdx ; construct the full CR3
mov cr3, rcx ; set CR3, invalidate all TLB cache
ret
; x64fastcall void paging_modeswitch_Table(void* pml, int pcid)
;
; This function simply sets CR3 and run INVLPG, flushing the TLB cache.
;
; Input: (void* rcx, int rdx)
; Clobbers: none
public paging_modeswitch_Table
paging_modeswitch_Table:
and rdx, 0xFFF ; take only the 11:0 bits of the PCID
or rcx, rdx ; construct the full CR3
mov cr3, rcx ; set CR3, invalidate all TLB cache
ret