summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/PlatformPei/AmdSev.c
Commit message (Collapse)AuthorAgeFilesLines
* OvmfPkg/VmgExitLib: Support nested #VCsTom Lendacky2021-01-071-6/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3108 In order to be able to issue messages or make interface calls that cause another #VC (e.g. GetLocalApicBaseAddress () issues RDMSR), add support for nested #VCs. In order to support nested #VCs, GHCB backup pages are required. If a #VC is received while currently processing a #VC, a backup of the current GHCB content is made. This allows the #VC handler to continue processing the new #VC. Upon completion of the new #VC, the GHCB is restored from the backup page. The #VC recursion level is tracked in the per-vCPU variable area. Support is added to handle up to one nested #VC (or two #VCs total). If a second nested #VC is encountered, an ASSERT will be issued and the vCPU will enter CpuDeadLoop (). For SEC, the GHCB backup pages are reserved in the OvmfPkgX64.fdf memory layout, with two new fixed PCDs to provide the address and size of the backup area. For PEI/DXE, the GHCB backup pages are allocated as boot services pages using the memory allocation library. Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Brijesh Singh <brijesh.singh@amd.com> Acked-by: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Message-Id: <ac2e8203fc41a351b43f60d68bdad6b57c4fb106.1610045305.git.thomas.lendacky@amd.com>
* OvmfPkg: Obtain SEV encryption mask with the new MemEncryptSevLib APITom Lendacky2021-01-071-10/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3108 The early assembler code performs validation for some of the SEV-related information, specifically the encryption bit position. The new MemEncryptSevGetEncryptionMask() interface provides access to this validated value. To ensure that we always use a validated encryption mask for an SEV-ES guest, update all locations that use CPUID to calculate the encryption mask to use the new interface. Also, clean up some call areas where extra masking was being performed and where a function call was being used instead of the local variable that was just set using the function. Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Rebecca Cran <rebecca@bsdio.com> Cc: Peter Grehan <grehan@freebsd.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Anthony Perard <anthony.perard@citrix.com> Cc: Julien Grall <julien@xen.org> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Message-Id: <9de678c0d66443c6cc33e004a4cac0a0223c2ebc.1610045305.git.thomas.lendacky@amd.com>
* OvmfPkg: Move the GHCB allocations into reserved memoryTom Lendacky2020-08-171-1/+3
| | | | | | | | | | | | | | | | | | | | | BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 After having transitioned from UEFI to the OS, the OS will need to boot the APs. For an SEV-ES guest, the APs will have been parked by UEFI using GHCB pages allocated by UEFI. The hypervisor will write to the GHCB SW_EXITINFO2 field of the GHCB when the AP is booted. As a result, the GHCB pages must be marked reserved so that the OS does not attempt to use them and experience memory corruption because of the hypervisor write. Change the GHCB allocation from the default boot services memory to reserved memory. 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>
* OvmfPkg/PlatformPei: Move early GDT into ram when SEV-ES is enabledTom Lendacky2020-08-171-0/+18
| | | | | | | | | | | | | | | | | | | BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 The SEV support will clear the C-bit from non-RAM areas. The early GDT lives in a non-RAM area, so when an exception occurs (like a #VC) the GDT will be read as un-encrypted even though it is encrypted. This will result in a failure to be able to handle the exception. Move the GDT into RAM so it can be accessed without error when running as an SEV-ES guest. 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>
* OvmfPkg: Create GHCB pages for use during Pei and Dxe phaseTom Lendacky2020-08-171-1/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 Allocate memory for the GHCB pages and the per-CPU variable pages during SEV initialization for use during Pei and Dxe phases. The GHCB page(s) must be shared pages, so clear the encryption mask from the current page table entries. Upon successful allocation, set the GHCB PCDs (PcdGhcbBase and PcdGhcbSize). The per-CPU variable page needs to be unique per AP. Using the page after the GHCB ensures that it is unique per AP. Only the GHCB page is marked as shared, keeping the per-CPU variable page encyrpted. The same logic is used in DXE using CreateIdentityMappingPageTables() before switching to the DXE pagetables. The GHCB pages (one per vCPU) will be used by the PEI and DXE #VC exception handlers. 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 associated with the vCPU in order to perform the requested function. 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>
* OvmfPkg: Add support to perform SEV-ES initializationTom Lendacky2020-08-171-0/+26
| | | | | | | | | | | | | | | BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 When SEV-ES is enabled, then SEV is also enabled. Add support to the SEV initialization function to also check for SEV-ES being enabled, and if enabled, set the SEV-ES enabled PCD (PcdSevEsIsEnabled). 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>
* OvmfPkg/SEV: don't manage the lifecycle of the SMRAM at the default SMBASELaszlo Ersek2020-02-051-5/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When OVMF runs in a SEV guest, the initial SMM Save State Map is (1) allocated as EfiBootServicesData type memory in OvmfPkg/PlatformPei, function AmdSevInitialize(), for preventing unintended information sharing with the hypervisor; (2) decrypted in AmdSevDxe; (3) re-encrypted in OvmfPkg/Library/SmmCpuFeaturesLib, function SmmCpuFeaturesSmmRelocationComplete(), which is called by PiSmmCpuDxeSmm right after initial SMBASE relocation; (4) released to DXE at the same location. The SMRAM at the default SMBASE is a superset of the initial Save State Map. The reserved memory allocation in InitializeRamRegions(), from the previous patch, must override the allocating and freeing in (1) and (4), respectively. (Note: the decrypting and re-encrypting in (2) and (3) are unaffected.) In AmdSevInitialize(), only assert the containment of the initial Save State Map, in the larger area already allocated by InitializeRamRegions(). In SmmCpuFeaturesSmmRelocationComplete(), preserve the allocation of the initial Save State Map into OS runtime, as part of the allocation done by InitializeRamRegions(). Only assert containment. These changes only affect the normal boot path (the UEFI memory map is untouched during S3 resume). Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1512 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Message-Id: <20200129214412.2361-9-lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
* OvmfPkg: Replace BSD License with BSD+Patent LicenseMichael D Kinney2019-04-091-7/+1
| | | | | | | | | | | | | | | | | | | | https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
* OvmfPkg/PlatformPei: SEV: allocate pages of initial SMRAM save state mapLaszlo Ersek2018-03-061-0/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the next two patches, we'll temporarily decrypt the pages containing the initial SMRAM save state map, for SMBASE relocation. (Unlike the separate, relocated SMRAM save state map of each VCPU, the original, shared map behaves similarly to a "common buffer" between guest and host.) The decryption will occur near the beginning of the DXE phase, in AmdSevDxe, and the re-encryption will occur in PiSmmCpuDxeSmm, via OVMF's SmmCpuFeaturesLib instance. There is a non-trivial time gap between these two points, and the DXE phase might use the pages overlapping the initial SMRAM save state map for arbitrary purposes meanwhile. In order to prevent any information leak towards the hypervisor, make sure the DXE phase puts nothing in those pages until re-encryption is done. Creating a memalloc HOB for the area in question is safe: - the temporary SEC/PEI RAM (stack and heap) is based at PcdOvmfSecPeiTempRamBase, which is above 8MB, - the permanent PEI RAM (installed in PlatformPei's PublishPeiMemory() function) never starts below PcdOvmfDxeMemFvBase, which is also above 8MB. The allocated pages can be released to the DXE phase after SMBASE relocation and re-encryption are complete. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
* OvmfPkg/PlatformPei: sort #includes in "AmdSev.c"Laszlo Ersek2018-03-061-4/+3
| | | | | | | | | | | | No functional changes. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
* OvmfPkg/PlatformPei: sync AmdSevInitialize() definition with declarationLaszlo Ersek2018-02-081-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | "Platform.h" declares the AmdSevInitialize() function without EFIAPI, but the definition in "AmdSev.c" includes EFIAPI. GCC toolchains without LTO do not catch this error because "AmdSev.c" does not include "Platform.h"; i.e. the declaration used by callers such as "Platform.c" is not actually matched against the function definition at build time. With LTO enabled, the mismatch is found -- however, as a warning only, due to commit f8d0b9662993 ("BaseTools GCC5: disable warnings-as-errors for now", 2016-08-03). Include the header in the C file (which turns the issue into a hard build error on all GCC toolchains), plus sync the declaration from the header file to the C file. There's been no functional breakage because AmdSevInitialize() takes no parameters. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Fixes: 13b5d743c87a22dfcd94e8475d943dee5712b62d Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
* OvmfPkg/PlatformPei: DENY_EXECUTE_ON_SECURITY_VIOLATION when SEV is activeBrijesh Singh2017-10-171-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | The following commit: 1fea9ddb4e3f OvmfPkg: execute option ROM images regardless of Secure Boot sets the OptionRomImageVerificationPolicy to ALWAYS_EXECUTE the expansion ROMs attached to the emulated PCI devices. A expansion ROM constitute another channel through which a cloud provider (i.e hypervisor) can inject a code in guest boot flow to compromise it. When SEV is enabled, the bios code has been verified by the guest owner via the SEV guest launch sequence before its executed. When secure boot, is enabled, lets make sure that we do not allow guest bios to execute a code which is not signed by the guest owner. Fixes: https://bugzilla.tianocore.org/show_bug.cgi?id=728 Cc: Chao Zhang <chao.b.zhang@intel.com> 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.1 Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
* OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabledBrijesh Singh2017-07-101-0/+62
Secure Encrypted Virtualization (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. For data memory, SEV guest VMs can choose which pages they would like to be private. The choice is done using the standard CPU page tables using the C-bit. When building the initial page table we mark all the memory as private. The patch sets the memory encryption PCD. The PCD is consumed by the following edk2 modules, which manipulate page tables: - PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei. CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the end of the PEI phase, when it builds the initial page tables for the DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its entry point function, only when DxeIplPeim branches to the S3 resume path at the end of the PEI phase, and calls S3Resume2Pei's EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function. Therefore it is safe to set the PCD for these modules in PlatformPei. - DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm. They are all dispatched after the PEI phase, so setting the PCD for them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for real" in the PEI phase during S3 resume, but it caches the PCD into a static variable when its entry point is originally invoked in DXE.) Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Laszlo Ersek <lersek@redhat.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>