2013-09-24 20:23:20 +02:00
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
; @file
|
|
|
|
; Sets the CR3 register for 64-bit paging
|
|
|
|
;
|
|
|
|
; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
|
2021-01-07 19:48:11 +01:00
|
|
|
; Copyright (c) 2017 - 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
|
2019-04-04 01:06:33 +02:00
|
|
|
; SPDX-License-Identifier: BSD-2-Clause-Patent
|
2013-09-24 20:23:20 +02:00
|
|
|
;
|
|
|
|
;------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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
|
|
|
|
|
OvmfPkg: Create a GHCB page for use during Sec phase
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198
A GHCB page is needed during the Sec phase, so this new page must be
created. Since the #VC exception handler routines assume that a per-CPU
variable area is immediately after the GHCB, this per-CPU variable area
must also be created. Since the GHCB must be marked as an un-encrypted,
or shared, page, an additional pagetable page is required to break down
the 2MB region where the GHCB page lives into 4K pagetable entries.
Create a new entry in the OVMF memory layout for the new page table
page and for the SEC GHCB and per-CPU variable pages. After breaking down
the 2MB page, update the GHCB page table entry to remove the encryption
mask.
The GHCB page will be used by the SEC #VC exception handler. The #VC
exception handler will fill in the necessary fields of the GHCB and exit
to the hypervisor using the VMGEXIT instruction. The hypervisor then
accesses the GHCB in order to perform the requested function.
Four new fixed PCDs are needed to support the SEC GHCB page:
- PcdOvmfSecGhcbBase UINT32 value that is the base address of the
GHCB used during the SEC phase.
- PcdOvmfSecGhcbSize UINT32 value that is the size, in bytes, of the
GHCB area used during the SEC phase.
- PcdOvmfSecGhcbPageTableBase UINT32 value that is address of a page
table page used to break down the 2MB page into
512 4K pages.
- PcdOvmfSecGhcbPageTableSize UINT32 value that is the size, in bytes,
of the page table page.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2020-08-12 22:21:40 +02:00
|
|
|
%define PAGE_4K_PDE_ATTR (PAGE_ACCESSED + \
|
|
|
|
PAGE_DIRTY + \
|
|
|
|
PAGE_READ_WRITE + \
|
|
|
|
PAGE_PRESENT)
|
|
|
|
|
2013-09-24 20:23:20 +02:00
|
|
|
%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
|
|
|
|
PAGE_ACCESSED + \
|
|
|
|
PAGE_DIRTY + \
|
|
|
|
PAGE_READ_WRITE + \
|
|
|
|
PAGE_PRESENT)
|
|
|
|
|
2013-09-24 20:23:26 +02:00
|
|
|
%define PAGE_PDP_ATTR (PAGE_ACCESSED + \
|
2013-09-24 20:23:20 +02:00
|
|
|
PAGE_READ_WRITE + \
|
|
|
|
PAGE_PRESENT)
|
|
|
|
|
2021-09-28 04:55:59 +02:00
|
|
|
%define TDX_BSP 1
|
|
|
|
%define TDX_AP 2
|
|
|
|
|
2013-09-24 20:23:20 +02:00
|
|
|
;
|
2017-07-06 15:21:11 +02:00
|
|
|
; Modified: EAX, EBX, ECX, EDX
|
2013-09-24 20:23:20 +02:00
|
|
|
;
|
|
|
|
SetCr3ForPageTables64:
|
2021-09-28 04:55:59 +02:00
|
|
|
; Check the TDX features.
|
|
|
|
; If it is TDX APs, then jump to SetCr3 directly.
|
|
|
|
; In TD guest the initialization is done by BSP, including building
|
|
|
|
; the page tables. APs will spin on until byte[TDX_WORK_AREA_PGTBL_READY]
|
|
|
|
; is set.
|
|
|
|
OneTimeCall CheckTdxFeaturesBeforeBuildPagetables
|
|
|
|
cmp eax, TDX_BSP
|
|
|
|
je ClearOvmfPageTables
|
|
|
|
cmp eax, TDX_AP
|
|
|
|
je SetCr3
|
2013-09-24 20:23:20 +02:00
|
|
|
|
2021-08-17 15:46:51 +02:00
|
|
|
; Check whether the SEV is active and populate the SevEsWorkArea
|
2021-01-07 19:48:11 +01:00
|
|
|
OneTimeCall CheckSevFeatures
|
2017-07-06 15:21:11 +02:00
|
|
|
|
2021-08-17 15:46:51 +02:00
|
|
|
; If SEV is enabled, the C-bit position is always above 31.
|
|
|
|
; The mask will be saved in the EDX and applied during the
|
|
|
|
; the page table build below.
|
|
|
|
OneTimeCall GetSevCBitMaskAbove31
|
2017-07-06 15:21:11 +02:00
|
|
|
|
2021-09-28 04:55:59 +02:00
|
|
|
ClearOvmfPageTables:
|
2013-09-24 20:23:20 +02:00
|
|
|
;
|
2016-11-04 14:32:39 +01:00
|
|
|
; For OVMF, build some initial page tables at
|
|
|
|
; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
|
2014-01-21 20:38:34 +01:00
|
|
|
;
|
2016-11-04 14:32:39 +01:00
|
|
|
; This range should match with PcdOvmfSecPageTablesSize which is
|
|
|
|
; declared in the FDF files.
|
2013-09-24 20:23:20 +02:00
|
|
|
;
|
|
|
|
; 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:
|
2016-11-04 14:32:39 +01:00
|
|
|
mov dword[ecx * 4 + PT_ADDR (0) - 4], eax
|
2013-09-24 20:23:20 +02:00
|
|
|
loop clearPageTablesMemoryLoop
|
|
|
|
|
|
|
|
;
|
|
|
|
; Top level Page Directory Pointers (1 * 512GB entry)
|
|
|
|
;
|
2016-11-04 14:32:39 +01:00
|
|
|
mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
|
2017-07-06 15:21:11 +02:00
|
|
|
mov dword[PT_ADDR (4)], edx
|
2013-09-24 20:23:20 +02:00
|
|
|
|
|
|
|
;
|
|
|
|
; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
|
|
|
|
;
|
2016-11-04 14:32:39 +01:00
|
|
|
mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
|
2017-07-06 15:21:11 +02:00
|
|
|
mov dword[PT_ADDR (0x1004)], edx
|
2016-11-04 14:32:39 +01:00
|
|
|
mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
|
2017-07-06 15:21:11 +02:00
|
|
|
mov dword[PT_ADDR (0x100C)], edx
|
2016-11-04 14:32:39 +01:00
|
|
|
mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
|
2017-07-06 15:21:11 +02:00
|
|
|
mov dword[PT_ADDR (0x1014)], edx
|
2016-11-04 14:32:39 +01:00
|
|
|
mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
|
2017-07-06 15:21:11 +02:00
|
|
|
mov dword[PT_ADDR (0x101C)], edx
|
2013-09-24 20:23:20 +02:00
|
|
|
|
|
|
|
;
|
|
|
|
; 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
|
2016-11-04 14:32:39 +01:00
|
|
|
mov [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
|
2017-07-06 15:21:11 +02:00
|
|
|
mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
|
2013-09-24 20:23:20 +02:00
|
|
|
loop pageTableEntriesLoop
|
|
|
|
|
2021-08-17 15:46:51 +02:00
|
|
|
; Clear the C-bit from the GHCB page if the SEV-ES is enabled.
|
|
|
|
OneTimeCall SevClearPageEncMaskForGhcbPage
|
OvmfPkg: Create a GHCB page for use during Sec phase
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198
A GHCB page is needed during the Sec phase, so this new page must be
created. Since the #VC exception handler routines assume that a per-CPU
variable area is immediately after the GHCB, this per-CPU variable area
must also be created. Since the GHCB must be marked as an un-encrypted,
or shared, page, an additional pagetable page is required to break down
the 2MB region where the GHCB page lives into 4K pagetable entries.
Create a new entry in the OVMF memory layout for the new page table
page and for the SEC GHCB and per-CPU variable pages. After breaking down
the 2MB page, update the GHCB page table entry to remove the encryption
mask.
The GHCB page will be used by the SEC #VC exception handler. The #VC
exception handler will fill in the necessary fields of the GHCB and exit
to the hypervisor using the VMGEXIT instruction. The hypervisor then
accesses the GHCB in order to perform the requested function.
Four new fixed PCDs are needed to support the SEC GHCB page:
- PcdOvmfSecGhcbBase UINT32 value that is the base address of the
GHCB used during the SEC phase.
- PcdOvmfSecGhcbSize UINT32 value that is the size, in bytes, of the
GHCB area used during the SEC phase.
- PcdOvmfSecGhcbPageTableBase UINT32 value that is address of a page
table page used to break down the 2MB page into
512 4K pages.
- PcdOvmfSecGhcbPageTableSize UINT32 value that is the size, in bytes,
of the page table page.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2020-08-12 22:21:40 +02:00
|
|
|
|
2021-09-28 04:55:59 +02:00
|
|
|
; TDX will do some PostBuildPages task, such as setting
|
|
|
|
; byte[TDX_WORK_AREA_PGTBL_READY].
|
|
|
|
OneTimeCall TdxPostBuildPageTables
|
|
|
|
|
OvmfPkg: Create a GHCB page for use during Sec phase
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198
A GHCB page is needed during the Sec phase, so this new page must be
created. Since the #VC exception handler routines assume that a per-CPU
variable area is immediately after the GHCB, this per-CPU variable area
must also be created. Since the GHCB must be marked as an un-encrypted,
or shared, page, an additional pagetable page is required to break down
the 2MB region where the GHCB page lives into 4K pagetable entries.
Create a new entry in the OVMF memory layout for the new page table
page and for the SEC GHCB and per-CPU variable pages. After breaking down
the 2MB page, update the GHCB page table entry to remove the encryption
mask.
The GHCB page will be used by the SEC #VC exception handler. The #VC
exception handler will fill in the necessary fields of the GHCB and exit
to the hypervisor using the VMGEXIT instruction. The hypervisor then
accesses the GHCB in order to perform the requested function.
Four new fixed PCDs are needed to support the SEC GHCB page:
- PcdOvmfSecGhcbBase UINT32 value that is the base address of the
GHCB used during the SEC phase.
- PcdOvmfSecGhcbSize UINT32 value that is the size, in bytes, of the
GHCB area used during the SEC phase.
- PcdOvmfSecGhcbPageTableBase UINT32 value that is address of a page
table page used to break down the 2MB page into
512 4K pages.
- PcdOvmfSecGhcbPageTableSize UINT32 value that is the size, in bytes,
of the page table page.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2020-08-12 22:21:40 +02:00
|
|
|
SetCr3:
|
2013-09-24 20:23:20 +02:00
|
|
|
;
|
|
|
|
; Set CR3 now that the paging structures are available
|
|
|
|
;
|
2016-11-04 14:32:39 +01:00
|
|
|
mov eax, PT_ADDR (0)
|
2013-09-24 20:23:20 +02:00
|
|
|
mov cr3, eax
|
|
|
|
|
|
|
|
OneTimeCallRet SetCr3ForPageTables64
|