summaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/sev-es.c
diff options
context:
space:
mode:
authorTom Lendacky <thomas.lendacky@amd.com>2020-09-07 15:16:12 +0200
committerBorislav Petkov <bp@suse.de>2020-09-10 21:48:50 +0200
commit39336f4ffb2478ad384075cf4ba7ef2e5db2bbd7 (patch)
treea3b7660370d24d993046a07b47364e1a73fa8b1f /arch/x86/kernel/sev-es.c
parent4ca68e023b11e4d5908bf9ee326fab01111d77d5 (diff)
downloadlinux-39336f4ffb2478ad384075cf4ba7ef2e5db2bbd7.tar.bz2
x86/efi: Add GHCB mappings when SEV-ES is active
Calling down to EFI runtime services can result in the firmware performing VMGEXIT calls. The firmware is likely to use the GHCB of the OS (e.g., for setting EFI variables), so each GHCB in the system needs to be identity-mapped in the EFI page tables, as unencrypted, to avoid page faults. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> [ jroedel@suse.de: Moved GHCB mapping loop to sev-es.c ] Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Acked-by: Ard Biesheuvel <ardb@kernel.org> Link: https://lkml.kernel.org/r/20200907131613.12703-72-joro@8bytes.org
Diffstat (limited to 'arch/x86/kernel/sev-es.c')
-rw-r--r--arch/x86/kernel/sev-es.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c
index b6518e96dedb..8cac9f80bfc3 100644
--- a/arch/x86/kernel/sev-es.c
+++ b/arch/x86/kernel/sev-es.c
@@ -491,6 +491,36 @@ int sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
return 0;
}
+/*
+ * This is needed by the OVMF UEFI firmware which will use whatever it finds in
+ * the GHCB MSR as its GHCB to talk to the hypervisor. So make sure the per-cpu
+ * runtime GHCBs used by the kernel are also mapped in the EFI page-table.
+ */
+int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
+{
+ struct sev_es_runtime_data *data;
+ unsigned long address, pflags;
+ int cpu;
+ u64 pfn;
+
+ if (!sev_es_active())
+ return 0;
+
+ pflags = _PAGE_NX | _PAGE_RW;
+
+ for_each_possible_cpu(cpu) {
+ data = per_cpu(runtime_data, cpu);
+
+ address = __pa(&data->ghcb_page);
+ pfn = address >> PAGE_SHIFT;
+
+ if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags))
+ return 1;
+ }
+
+ return 0;
+}
+
static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
{
struct pt_regs *regs = ctxt->regs;