[edk2-devel] [PATCH v5 03/35] OvmfPkg: Introduce XenResetVector

Anthony PERARD posted 35 patches 5 years, 3 months ago
[edk2-devel] [PATCH v5 03/35] OvmfPkg: Introduce XenResetVector
Posted by Anthony PERARD 5 years, 3 months ago
Introduce XenResetVector, a copy of OvmfPkg/ResetVector, with one
changes:
  - SEC_DEFAULT_CR0: enable cache (bit 30 or CD set to 0)

Xen copies the OVMF code to RAM, there is no need to disable cache.

This new module will later be modified to add a new entry point, more
detail in a following commit "OvmfPkg/XenResetVector: Add new entry point
for Xen PVH"

Value FILE_GUID of XenResetVector have not changed compare to ResetVector
because it is a special value (gEfiFirmwareVolumeTopFileGuid).

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1689
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---

Notes:
    v4:
    - Update Maintainers.txt
    
    v3:
      - Added gEfiFirmwareVolumeTopFileGuid to the commit message.
      - rebased: SPDX

 OvmfPkg/OvmfXen.dsc                           |   2 +-
 OvmfPkg/OvmfXen.fdf                           |   2 +-
 OvmfPkg/XenResetVector/XenResetVector.inf     |  38 +++++
 Maintainers.txt                               |   1 +
 .../XenResetVector/Ia16/Real16ToFlat32.asm    | 134 ++++++++++++++++
 OvmfPkg/XenResetVector/Ia32/PageTables64.asm  | 149 ++++++++++++++++++
 OvmfPkg/XenResetVector/XenResetVector.nasmb   |  68 ++++++++
 7 files changed, 392 insertions(+), 2 deletions(-)
 create mode 100644 OvmfPkg/XenResetVector/XenResetVector.inf
 create mode 100644 OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm
 create mode 100644 OvmfPkg/XenResetVector/Ia32/PageTables64.asm
 create mode 100644 OvmfPkg/XenResetVector/XenResetVector.nasmb

diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index f224ac32b4..1a0e59f0cc 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -495,7 +495,7 @@ [PcdsDynamicDefault]
 #
 ################################################################################
 [Components]
-  OvmfPkg/ResetVector/ResetVector.inf
+  OvmfPkg/XenResetVector/XenResetVector.inf
 
   #
   # SEC Phase modules
diff --git a/OvmfPkg/OvmfXen.fdf b/OvmfPkg/OvmfXen.fdf
index f59647fd14..6fc8479aae 100644
--- a/OvmfPkg/OvmfXen.fdf
+++ b/OvmfPkg/OvmfXen.fdf
@@ -118,7 +118,7 @@ [FV.SECFV]
 #
 INF  OvmfPkg/Sec/SecMain.inf
 
-INF  RuleOverride=RESET_VECTOR OvmfPkg/ResetVector/ResetVector.inf
+INF  RuleOverride=RESET_VECTOR OvmfPkg/XenResetVector/XenResetVector.inf
 
 ################################################################################
 [FV.PEIFV]
diff --git a/OvmfPkg/XenResetVector/XenResetVector.inf b/OvmfPkg/XenResetVector/XenResetVector.inf
new file mode 100644
index 0000000000..097fc9b5b4
--- /dev/null
+++ b/OvmfPkg/XenResetVector/XenResetVector.inf
@@ -0,0 +1,38 @@
+## @file
+#  Reset Vector
+#
+#  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2019, Citrix Systems, Inc.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = XenResetVector
+  FILE_GUID                      = 1BA0062E-C779-4582-8566-336AE8F78F09
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.1
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  XenResetVector.nasmb
+
+[Packages]
+  OvmfPkg/OvmfPkg.dec
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[BuildOptions]
+   *_*_IA32_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/
+   *_*_X64_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
diff --git a/Maintainers.txt b/Maintainers.txt
index 98f6d828eb..34bdb275b4 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -380,6 +380,7 @@ F: OvmfPkg/SmbiosPlatformDxe/*Xen.c
 F: OvmfPkg/XenBusDxe/
 F: OvmfPkg/XenIoPciDxe/
 F: OvmfPkg/XenPvBlkDxe/
+F: OvmfPkg/XenResetVector/
 R: Anthony Perard <anthony.perard@citrix.com>
 R: Julien Grall <julien.grall@arm.com>
 
diff --git a/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm b/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm
new file mode 100644
index 0000000000..5c329bfaea
--- /dev/null
+++ b/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm
@@ -0,0 +1,134 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 16 bit real mode into 32 bit flat protected mode
+;
+; Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019, Citrix Systems, Inc.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+%define SEC_DEFAULT_CR0  0x00000023
+%define SEC_DEFAULT_CR4  0x640
+
+BITS    16
+
+;
+; Modified:  EAX, EBX
+;
+; @param[out]     DS       Selector allowing flat access to all addresses
+; @param[out]     ES       Selector allowing flat access to all addresses
+; @param[out]     FS       Selector allowing flat access to all addresses
+; @param[out]     GS       Selector allowing flat access to all addresses
+; @param[out]     SS       Selector allowing flat access to all addresses
+;
+TransitionFromReal16To32BitFlat:
+
+    debugShowPostCode POSTCODE_16BIT_MODE
+
+    cli
+
+    mov     bx, 0xf000
+    mov     ds, bx
+
+    mov     bx, ADDR16_OF(gdtr)
+
+o32 lgdt    [cs:bx]
+
+    mov     eax, SEC_DEFAULT_CR0
+    mov     cr0, eax
+
+    jmp     LINEAR_CODE_SEL:dword ADDR_OF(jumpTo32BitAndLandHere)
+BITS    32
+jumpTo32BitAndLandHere:
+
+    mov     eax, SEC_DEFAULT_CR4
+    mov     cr4, eax
+
+    debugShowPostCode POSTCODE_32BIT_MODE
+
+    mov     ax, LINEAR_SEL
+    mov     ds, ax
+    mov     es, ax
+    mov     fs, ax
+    mov     gs, ax
+    mov     ss, ax
+
+    OneTimeCallRet TransitionFromReal16To32BitFlat
+
+ALIGN   2
+
+gdtr:
+    dw      GDT_END - GDT_BASE - 1   ; GDT limit
+    dd      ADDR_OF(GDT_BASE)
+
+ALIGN   16
+
+;
+; Macros for GDT entries
+;
+
+%define  PRESENT_FLAG(p) (p << 7)
+%define  DPL(dpl) (dpl << 5)
+%define  SYSTEM_FLAG(s) (s << 4)
+%define  DESC_TYPE(t) (t)
+
+; Type: data, expand-up, writable, accessed
+%define  DATA32_TYPE 3
+
+; Type: execute, readable, expand-up, accessed
+%define  CODE32_TYPE 0xb
+
+; Type: execute, readable, expand-up, accessed
+%define  CODE64_TYPE 0xb
+
+%define  GRANULARITY_FLAG(g) (g << 7)
+%define  DEFAULT_SIZE32(d) (d << 6)
+%define  CODE64_FLAG(l) (l << 5)
+%define  UPPER_LIMIT(l) (l)
+
+;
+; The Global Descriptor Table (GDT)
+;
+
+GDT_BASE:
+; null descriptor
+NULL_SEL            equ $-GDT_BASE
+    DW      0            ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      0            ; sys flag, dpl, type
+    DB      0            ; limit 19:16, flags
+    DB      0            ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL          equ $-GDT_BASE
+    DW      0xffff       ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+    DB      0            ; base 31:24
+
+; linear code segment descriptor
+LINEAR_CODE_SEL     equ $-GDT_BASE
+    DW      0xffff       ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+    DB      0            ; base 31:24
+
+%ifdef ARCH_X64
+; linear code (64-bit) segment descriptor
+LINEAR_CODE64_SEL   equ $-GDT_BASE
+    DW      0xffff       ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)
+    DB      0            ; base 31:24
+%endif
+
+GDT_END:
+
diff --git a/OvmfPkg/XenResetVector/Ia32/PageTables64.asm b/OvmfPkg/XenResetVector/Ia32/PageTables64.asm
new file mode 100644
index 0000000000..9f1c0e2259
--- /dev/null
+++ b/OvmfPkg/XenResetVector/Ia32/PageTables64.asm
@@ -0,0 +1,149 @@
+;------------------------------------------------------------------------------
+; @file
+; Sets the CR3 register for 64-bit paging
+;
+; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019, Citrix Systems, Inc.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    32
+
+%define PAGE_PRESENT            0x01
+%define PAGE_READ_WRITE         0x02
+%define PAGE_USER_SUPERVISOR    0x04
+%define PAGE_WRITE_THROUGH      0x08
+%define PAGE_CACHE_DISABLE     0x010
+%define PAGE_ACCESSED          0x020
+%define PAGE_DIRTY             0x040
+%define PAGE_PAT               0x080
+%define PAGE_GLOBAL           0x0100
+%define PAGE_2M_MBO            0x080
+%define PAGE_2M_PAT          0x01000
+
+%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
+                          PAGE_ACCESSED + \
+                          PAGE_DIRTY + \
+                          PAGE_READ_WRITE + \
+                          PAGE_PRESENT)
+
+%define PAGE_PDP_ATTR (PAGE_ACCESSED + \
+                       PAGE_READ_WRITE + \
+                       PAGE_PRESENT)
+
+; Check if Secure Encrypted Virtualization (SEV) feature is enabled
+;
+; If SEV is enabled then EAX will be at least 32
+; If SEV is disabled then EAX will be zero.
+;
+CheckSevFeature:
+    ; Check if we have a valid (0x8000_001F) CPUID leaf
+    mov       eax, 0x80000000
+    cpuid
+
+    ; This check should fail on Intel or Non SEV AMD CPUs. In future if
+    ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
+    ; same bit definition.
+    cmp       eax, 0x8000001f
+    jl        NoSev
+
+    ; Check for memory encryption feature:
+    ;  CPUID  Fn8000_001F[EAX] - Bit 1
+    ;
+    mov       eax,  0x8000001f
+    cpuid
+    bt        eax, 1
+    jnc       NoSev
+
+    ; Check if memory encryption is enabled
+    ;  MSR_0xC0010131 - Bit 0 (SEV enabled)
+    mov       ecx, 0xc0010131
+    rdmsr
+    bt        eax, 0
+    jnc       NoSev
+
+    ; Get pte bit position to enable memory encryption
+    ; CPUID Fn8000_001F[EBX] - Bits 5:0
+    ;
+    mov       eax, ebx
+    and       eax, 0x3f
+    jmp       SevExit
+
+NoSev:
+    xor       eax, eax
+
+SevExit:
+    OneTimeCallRet CheckSevFeature
+
+;
+; Modified:  EAX, EBX, ECX, EDX
+;
+SetCr3ForPageTables64:
+
+    OneTimeCall   CheckSevFeature
+    xor     edx, edx
+    test    eax, eax
+    jz      SevNotActive
+
+    ; If SEV is enabled, C-bit is always above 31
+    sub     eax, 32
+    bts     edx, eax
+
+SevNotActive:
+
+    ;
+    ; For OVMF, build some initial page tables at
+    ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
+    ;
+    ; This range should match with PcdOvmfSecPageTablesSize which is
+    ; declared in the FDF files.
+    ;
+    ; At the end of PEI, the pages tables will be rebuilt into a
+    ; more permanent location by DxeIpl.
+    ;
+
+    mov     ecx, 6 * 0x1000 / 4
+    xor     eax, eax
+clearPageTablesMemoryLoop:
+    mov     dword[ecx * 4 + PT_ADDR (0) - 4], eax
+    loop    clearPageTablesMemoryLoop
+
+    ;
+    ; Top level Page Directory Pointers (1 * 512GB entry)
+    ;
+    mov     dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (4)], edx
+
+    ;
+    ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
+    ;
+    mov     dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x1004)], edx
+    mov     dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x100C)], edx
+    mov     dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x1014)], edx
+    mov     dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x101C)], edx
+
+    ;
+    ; Page Table Entries (2048 * 2MB entries => 4GB)
+    ;
+    mov     ecx, 0x800
+pageTableEntriesLoop:
+    mov     eax, ecx
+    dec     eax
+    shl     eax, 21
+    add     eax, PAGE_2M_PDE_ATTR
+    mov     [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
+    mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
+    loop    pageTableEntriesLoop
+
+    ;
+    ; Set CR3 now that the paging structures are available
+    ;
+    mov     eax, PT_ADDR (0)
+    mov     cr3, eax
+
+    OneTimeCallRet SetCr3ForPageTables64
diff --git a/OvmfPkg/XenResetVector/XenResetVector.nasmb b/OvmfPkg/XenResetVector/XenResetVector.nasmb
new file mode 100644
index 0000000000..89a4b08bc3
--- /dev/null
+++ b/OvmfPkg/XenResetVector/XenResetVector.nasmb
@@ -0,0 +1,68 @@
+;------------------------------------------------------------------------------
+; @file
+; This file includes all other code files to assemble the reset vector code
+;
+; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019, Citrix Systems, Inc.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+;
+; If neither ARCH_IA32 nor ARCH_X64 are defined, then try to include
+; Base.h to use the C pre-processor to determine the architecture.
+;
+%ifndef ARCH_IA32
+  %ifndef ARCH_X64
+    #include <Base.h>
+    #if defined (MDE_CPU_IA32)
+      %define ARCH_IA32
+    #elif defined (MDE_CPU_X64)
+      %define ARCH_X64
+    #endif
+  %endif
+%endif
+
+%ifdef ARCH_IA32
+  %ifdef ARCH_X64
+    %error "Only one of ARCH_IA32 or ARCH_X64 can be defined."
+  %endif
+%elifdef ARCH_X64
+%else
+  %error "Either ARCH_IA32 or ARCH_X64 must be defined."
+%endif
+
+%include "CommonMacros.inc"
+
+%include "PostCodes.inc"
+
+%ifdef DEBUG_PORT80
+  %include "Port80Debug.asm"
+%elifdef DEBUG_SERIAL
+  %include "SerialDebug.asm"
+%else
+  %include "DebugDisabled.asm"
+%endif
+
+%include "Ia32/SearchForBfvBase.asm"
+%include "Ia32/SearchForSecEntry.asm"
+
+%ifdef ARCH_X64
+  #include <AutoGen.h>
+
+  %if (FixedPcdGet32 (PcdOvmfSecPageTablesSize) != 0x6000)
+    %error "This implementation inherently depends on PcdOvmfSecPageTablesSize"
+  %endif
+
+  %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
+%include "Ia32/Flat32ToFlat64.asm"
+%include "Ia32/PageTables64.asm"
+%endif
+
+%include "Ia16/Real16ToFlat32.asm"
+%include "Ia16/Init16.asm"
+
+%include "Main.asm"
+
+%include "Ia16/ResetVectorVtf0.asm"
+
-- 
Anthony PERARD


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#45527): https://edk2.groups.io/g/devel/message/45527
Mute This Topic: https://groups.io/mt/32851498/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-