| ;------------------------------------------------------------------------------ | |
| ; @file | |
| ; | |
| ; Switch from 5-level paging mode to 4-level paging mode. | |
| ; | |
| ; This assumes everything (code, stack, page tables) is in 32-bit | |
| ; address space. Which is true for PEI phase even in X64 builds | |
| ; because low memory is used for early firmware setup. | |
| ; | |
| ; This also assumes the standard ResetVector GDT is active. | |
| ; | |
| ; SPDX-License-Identifier: BSD-2-Clause-Patent | |
| ;------------------------------------------------------------------------------ | |
| SECTION .text | |
| BITS 64 | |
| global ASM_PFX(Switch4Level) | |
| ASM_PFX(Switch4Level): | |
| ; save regs | |
| push rax | |
| push rbx | |
| push rcx | |
| push rdx | |
| ; cs:ip for long mode | |
| lea rax, [rel Switch4Level64] | |
| mov rbx, 0x3800000000 ; LINEAR_CODE64_SEL << 32 | |
| or rax, rbx | |
| push rax | |
| ; cs:ip for 32-bit mode | |
| lea rax, [rel Switch4Level32] | |
| mov rbx, 0x1000000000 ; LINEAR_CODE_SEL << 32 | |
| or rax, rbx | |
| push rax | |
| ; enter 32-bit mode | |
| retf | |
| Switch4Level64: | |
| ; restore regs | |
| pop rdx | |
| pop rcx | |
| pop rbx | |
| pop rax | |
| ret | |
| BITS 32 | |
| Switch4Level32: | |
| ; disable paging | |
| mov eax, cr0 | |
| btc eax, 31 ; clear PG | |
| mov cr0, eax | |
| ; disable 5-level paging | |
| mov eax, cr4 | |
| btc eax, 12 ; clear la57 | |
| mov cr4, eax | |
| ; fixup cr3 (dereference 5th level) | |
| mov eax, cr3 | |
| mov eax, [ eax ] | |
| and eax, 0xfffff000 | |
| mov cr3, eax | |
| ; enable paging | |
| mov eax, cr0 | |
| bts eax, 31 ; set PG | |
| mov cr0, eax | |
| ; back to long mode | |
| retf |