]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/ResetVector: Set C-bit when building initial page table
authorBrijesh Singh <brijesh.singh@amd.com>
Thu, 6 Jul 2017 13:21:11 +0000 (09:21 -0400)
committerJordan Justen <jordan.l.justen@intel.com>
Tue, 11 Jul 2017 04:17:27 +0000 (21:17 -0700)
SEV guest VMs have the concept of private and shared memory. Private
memory is encrypted with the guest-specific key, while shared memory
may be encrypted with hypervisor key. Certain types of memory (namely
instruction pages and guest page tables) are always treated as private
memory by the hardware. The C-bit in PTE indicate whether the page is
private or shared. The C-bit position for the PTE can be obtained from
CPUID Fn8000_001F[EBX].

When SEV is active, the BIOS is encrypted by the Qemu launch sequence,
we must set the C-bit when building the page table.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Tom Lendacky <Thomas.Lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
OvmfPkg/ResetVector/Ia32/PageTables64.asm

index 6201cad1f5dc3f1ea0b888b62e612cedd679b74f..db1590aedd42dfb9c6d82c49464ba9dbb2ca1ff4 100644 (file)
@@ -37,12 +37,66 @@ BITS    32
                        PAGE_READ_WRITE + \\r
                        PAGE_PRESENT)\r
 \r
+; Check if Secure Encrypted Virtualization (SEV) feature is enabled\r
+;\r
+; If SEV is enabled then EAX will be at least 32\r
+; If SEV is disabled then EAX will be zero.\r
+;\r
+CheckSevFeature:\r
+    ; Check if we have a valid (0x8000_001F) CPUID leaf\r
+    mov       eax, 0x80000000\r
+    cpuid\r
+\r
+    ; This check should fail on Intel or Non SEV AMD CPUs. In future if\r
+    ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact\r
+    ; same bit definition.\r
+    cmp       eax, 0x8000001f\r
+    jl        NoSev\r
+\r
+    ; Check for memory encryption feature:\r
+    ;  CPUID  Fn8000_001F[EAX] - Bit 1\r
+    ;\r
+    mov       eax,  0x8000001f\r
+    cpuid\r
+    bt        eax, 1\r
+    jnc       NoSev\r
+\r
+    ; Check if memory encryption is enabled\r
+    ;  MSR_0xC0010131 - Bit 0 (SEV enabled)\r
+    mov       ecx, 0xc0010131\r
+    rdmsr\r
+    bt        eax, 0\r
+    jnc       NoSev\r
+\r
+    ; Get pte bit position to enable memory encryption\r
+    ; CPUID Fn8000_001F[EBX] - Bits 5:0\r
+    ;\r
+    mov       eax, ebx\r
+    and       eax, 0x3f\r
+    jmp       SevExit\r
+\r
+NoSev:\r
+    xor       eax, eax\r
+\r
+SevExit:\r
+    OneTimeCallRet CheckSevFeature\r
 \r
 ;\r
-; Modified:  EAX, ECX\r
+; Modified:  EAX, EBX, ECX, EDX\r
 ;\r
 SetCr3ForPageTables64:\r
 \r
+    OneTimeCall   CheckSevFeature\r
+    xor     edx, edx\r
+    test    eax, eax\r
+    jz      SevNotActive\r
+\r
+    ; If SEV is enabled, C-bit is always above 31\r
+    sub     eax, 32\r
+    bts     edx, eax\r
+\r
+SevNotActive:\r
+\r
     ;\r
     ; For OVMF, build some initial page tables at\r
     ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).\r
@@ -64,14 +118,19 @@ clearPageTablesMemoryLoop:
     ; Top level Page Directory Pointers (1 * 512GB entry)\r
     ;\r
     mov     dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR\r
+    mov     dword[PT_ADDR (4)], edx\r
 \r
     ;\r
     ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)\r
     ;\r
     mov     dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR\r
+    mov     dword[PT_ADDR (0x1004)], edx\r
     mov     dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR\r
+    mov     dword[PT_ADDR (0x100C)], edx\r
     mov     dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR\r
+    mov     dword[PT_ADDR (0x1014)], edx\r
     mov     dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR\r
+    mov     dword[PT_ADDR (0x101C)], edx\r
 \r
     ;\r
     ; Page Table Entries (2048 * 2MB entries => 4GB)\r
@@ -83,6 +142,7 @@ pageTableEntriesLoop:
     shl     eax, 21\r
     add     eax, PAGE_2M_PDE_ATTR\r
     mov     [ecx * 8 + PT_ADDR (0x2000 - 8)], eax\r
+    mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx\r
     loop    pageTableEntriesLoop\r
 \r
     ;\r