1;------------------------------------------------------------------------------ 2; @file 3; Sets the CR3 register for 64-bit paging 4; 5; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR> 6; Copyright (c) 2019, Citrix Systems, Inc. 7; SPDX-License-Identifier: BSD-2-Clause-Patent 8; 9;------------------------------------------------------------------------------ 10 11BITS 32 12 13%define PAGE_PRESENT 0x01 14%define PAGE_READ_WRITE 0x02 15%define PAGE_USER_SUPERVISOR 0x04 16%define PAGE_WRITE_THROUGH 0x08 17%define PAGE_CACHE_DISABLE 0x010 18%define PAGE_ACCESSED 0x020 19%define PAGE_DIRTY 0x040 20%define PAGE_PAT 0x080 21%define PAGE_GLOBAL 0x0100 22%define PAGE_2M_MBO 0x080 23%define PAGE_2M_PAT 0x01000 24 25%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \ 26 PAGE_ACCESSED + \ 27 PAGE_DIRTY + \ 28 PAGE_READ_WRITE + \ 29 PAGE_PRESENT) 30 31%define PAGE_PDP_ATTR (PAGE_ACCESSED + \ 32 PAGE_READ_WRITE + \ 33 PAGE_PRESENT) 34 35; Check if Secure Encrypted Virtualization (SEV) feature is enabled 36; 37; If SEV is enabled then EAX will be at least 32 38; If SEV is disabled then EAX will be zero. 39; 40CheckSevFeature: 41 ; Check if we have a valid (0x8000_001F) CPUID leaf 42 mov eax, 0x80000000 43 cpuid 44 45 ; This check should fail on Intel or Non SEV AMD CPUs. In future if 46 ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact 47 ; same bit definition. 48 cmp eax, 0x8000001f 49 jl NoSev 50 51 ; Check for memory encryption feature: 52 ; CPUID Fn8000_001F[EAX] - Bit 1 53 ; 54 mov eax, 0x8000001f 55 cpuid 56 bt eax, 1 57 jnc NoSev 58 59 ; Check if memory encryption is enabled 60 ; MSR_0xC0010131 - Bit 0 (SEV enabled) 61 mov ecx, 0xc0010131 62 rdmsr 63 bt eax, 0 64 jnc NoSev 65 66 ; Get pte bit position to enable memory encryption 67 ; CPUID Fn8000_001F[EBX] - Bits 5:0 68 ; 69 mov eax, ebx 70 and eax, 0x3f 71 jmp SevExit 72 73NoSev: 74 xor eax, eax 75 76SevExit: 77 OneTimeCallRet CheckSevFeature 78 79; 80; Modified: EAX, EBX, ECX, EDX 81; 82SetCr3ForPageTables64: 83 84 OneTimeCall CheckSevFeature 85 xor edx, edx 86 test eax, eax 87 jz SevNotActive 88 89 ; If SEV is enabled, C-bit is always above 31 90 sub eax, 32 91 bts edx, eax 92 93SevNotActive: 94 95 ; 96 ; For OVMF, build some initial page tables at 97 ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000). 98 ; 99 ; This range should match with PcdOvmfSecPageTablesSize which is 100 ; declared in the FDF files. 101 ; 102 ; At the end of PEI, the pages tables will be rebuilt into a 103 ; more permanent location by DxeIpl. 104 ; 105 106 mov ecx, 6 * 0x1000 / 4 107 xor eax, eax 108clearPageTablesMemoryLoop: 109 mov dword[ecx * 4 + PT_ADDR (0) - 4], eax 110 loop clearPageTablesMemoryLoop 111 112 ; 113 ; Top level Page Directory Pointers (1 * 512GB entry) 114 ; 115 mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR 116 mov dword[PT_ADDR (4)], edx 117 118 ; 119 ; Next level Page Directory Pointers (4 * 1GB entries => 4GB) 120 ; 121 mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR 122 mov dword[PT_ADDR (0x1004)], edx 123 mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR 124 mov dword[PT_ADDR (0x100C)], edx 125 mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR 126 mov dword[PT_ADDR (0x1014)], edx 127 mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR 128 mov dword[PT_ADDR (0x101C)], edx 129 130 ; 131 ; Page Table Entries (2048 * 2MB entries => 4GB) 132 ; 133 mov ecx, 0x800 134pageTableEntriesLoop: 135 mov eax, ecx 136 dec eax 137 shl eax, 21 138 add eax, PAGE_2M_PDE_ATTR 139 mov [ecx * 8 + PT_ADDR (0x2000 - 8)], eax 140 mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx 141 loop pageTableEntriesLoop 142 143 ; 144 ; Set CR3 now that the paging structures are available 145 ; 146 mov eax, PT_ADDR (0) 147 mov cr3, eax 148 149 OneTimeCallRet SetCr3ForPageTables64 150