]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/sev: Let sev_es_efi_map_ghcbs() map the CA pages too
authorGerd Hoffmann <kraxel@redhat.com>
Thu, 26 Jun 2025 11:40:13 +0000 (13:40 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Fri, 27 Jun 2025 12:07:10 +0000 (14:07 +0200)
OVMF EFI firmware needs access to the CA page to do SVSM protocol calls. For
example, when the SVSM implements an EFI variable store, such calls will be
necessary.

So add that to sev_es_efi_map_ghcbs() and also rename the function to reflect
the additional job it is doing now.

  [ bp: Massage. ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/20250626114014.373748-4-kraxel@redhat.com
arch/x86/coco/sev/core.c
arch/x86/include/asm/sev.h
arch/x86/platform/efi/efi_64.c

index 8375ca7fbd8a638077931bdcfd94cfeb161a5b4b..46bd89578ec7e38f409b364ae93ad64a3d908d0f 100644 (file)
@@ -1045,11 +1045,13 @@ int __init sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
  * 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.
+ *
+ * When running under SVSM the CA page is needed too, so map it as well.
  */
-int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
+int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd)
 {
+       unsigned long address, pflags, pflags_enc;
        struct sev_es_runtime_data *data;
-       unsigned long address, pflags;
        int cpu;
        u64 pfn;
 
@@ -1057,6 +1059,7 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
                return 0;
 
        pflags = _PAGE_NX | _PAGE_RW;
+       pflags_enc = cc_mkenc(pflags);
 
        for_each_possible_cpu(cpu) {
                data = per_cpu(runtime_data, cpu);
@@ -1066,6 +1069,16 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
 
                if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags))
                        return 1;
+
+               if (snp_vmpl) {
+                       address = per_cpu(svsm_caa_pa, cpu);
+                       if (!address)
+                               return 1;
+
+                       pfn = address >> PAGE_SHIFT;
+                       if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags_enc))
+                               return 1;
+               }
        }
 
        return 0;
index fbb616fcbfb8d50c6fbd641bc0916a48aeec9e9a..a81769a32eaa4e4a89ee3e42d9afca0e6730e004 100644 (file)
@@ -446,7 +446,7 @@ static __always_inline void sev_es_nmi_complete(void)
            cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
                __sev_es_nmi_complete();
 }
-extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
+extern int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd);
 extern void sev_enable(struct boot_params *bp);
 
 /*
@@ -554,7 +554,7 @@ static inline void sev_es_ist_enter(struct pt_regs *regs) { }
 static inline void sev_es_ist_exit(void) { }
 static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
 static inline void sev_es_nmi_complete(void) { }
-static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
+static inline int sev_es_efi_map_ghcbs_cas(pgd_t *pgd) { return 0; }
 static inline void sev_enable(struct boot_params *bp) { }
 static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
 static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
index e7e8f77f77f8d638ec697e8d4cfa3f9285bb00a4..b4409df2105a660b439aebd8b15dccc474ab552a 100644 (file)
@@ -216,8 +216,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
         * When SEV-ES is active, the GHCB as set by the kernel will be used
         * by firmware. Create a 1:1 unencrypted mapping for each GHCB.
         */
-       if (sev_es_efi_map_ghcbs(pgd)) {
-               pr_err("Failed to create 1:1 mapping for the GHCBs!\n");
+       if (sev_es_efi_map_ghcbs_cas(pgd)) {
+               pr_err("Failed to create 1:1 mapping for the GHCBs and CAs!\n");
                return 1;
        }