mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation
       [not found] <20250626114014.373748-1-kraxel@redhat.com>
@ 2025-06-26 11:40 ` Gerd Hoffmann
  2025-06-27  8:33   ` Gupta, Pankaj
  2025-06-27 12:30   ` [tip: x86/sev] x86/sev/vc: Fix EFI " tip-bot2 for Gerd Hoffmann
  2025-06-26 11:40 ` [PATCH v4 2/3] x86/sev: fix error handling in sev_es_efi_map_ghcbs_caas() Gerd Hoffmann
  2025-06-26 11:40 ` [PATCH v4 3/3] x86/sev: Let sev_es_efi_map_ghcbs() map the caa pages too Gerd Hoffmann
  2 siblings, 2 replies; 7+ messages in thread
From: Gerd Hoffmann @ 2025-06-26 11:40 UTC (permalink / raw)
  To: linux-coco, kvm
  Cc: Gerd Hoffmann, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

In case efi_mm is active go use the userspace instruction decoder which
supports fetching instructions from active_mm.  This is needed to make
instruction emulation work for EFI runtime code, so it can use cpuid
and rdmsr.

EFI runtime code uses the cpuid instruction to gather information about
the environment it is running in, such as SEV being enabled or not, and
choose (if needed) the SEV code path for ioport access.

EFI runtime code uses the rdmsr instruction to get the location of the
CAA page (see SVSM spec, section 4.2 - "Post Boot").

The big picture behind this is that the kernel needs to be able to
properly handle #VC exceptions that come from EFI runtime services.
Since EFI runtime services have a special page table mapping for the EFI
virtual address space, the efi_mm context must be used when decoding
instructions during #VC handling.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 arch/x86/coco/sev/vc-handle.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/x86/coco/sev/vc-handle.c b/arch/x86/coco/sev/vc-handle.c
index 0989d98da130..faf1fce89ed4 100644
--- a/arch/x86/coco/sev/vc-handle.c
+++ b/arch/x86/coco/sev/vc-handle.c
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 #include <linux/psp-sev.h>
+#include <linux/efi.h>
 #include <uapi/linux/sev-guest.h>
 
 #include <asm/init.h>
@@ -178,9 +179,15 @@ static enum es_result __vc_decode_kern_insn(struct es_em_ctxt *ctxt)
 		return ES_OK;
 }
 
+/*
+ * User instruction decoding is also required for the EFI runtime. Even though
+ * the EFI runtime is running in kernel mode, it uses special EFI virtual
+ * address mappings that require the use of efi_mm to properly address and
+ * decode.
+ */
 static enum es_result vc_decode_insn(struct es_em_ctxt *ctxt)
 {
-	if (user_mode(ctxt->regs))
+	if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm))
 		return __vc_decode_user_insn(ctxt);
 	else
 		return __vc_decode_kern_insn(ctxt);
-- 
2.50.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 2/3] x86/sev: fix error handling in sev_es_efi_map_ghcbs_caas()
       [not found] <20250626114014.373748-1-kraxel@redhat.com>
  2025-06-26 11:40 ` [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation Gerd Hoffmann
@ 2025-06-26 11:40 ` Gerd Hoffmann
  2025-06-27 12:01   ` Borislav Petkov
  2025-06-26 11:40 ` [PATCH v4 3/3] x86/sev: Let sev_es_efi_map_ghcbs() map the caa pages too Gerd Hoffmann
  2 siblings, 1 reply; 7+ messages in thread
From: Gerd Hoffmann @ 2025-06-26 11:40 UTC (permalink / raw)
  To: linux-coco, kvm
  Cc: Gerd Hoffmann, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

Pass up error codes from kernel_map_pages_in_pgd() instead of
returning '1' on failure.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 arch/x86/coco/sev/core.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index b6db4e0b936b..3de8c3d2b55d 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -1050,6 +1050,7 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
 {
 	struct sev_es_runtime_data *data;
 	unsigned long address, pflags;
+	int retval;
 	int cpu;
 	u64 pfn;
 
@@ -1064,8 +1065,9 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
 		address = __pa(&data->ghcb_page);
 		pfn = address >> PAGE_SHIFT;
 
-		if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags))
-			return 1;
+		retval = kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags);
+		if (retval != 0)
+			return retval;
 	}
 
 	return 0;
-- 
2.50.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 3/3] x86/sev: Let sev_es_efi_map_ghcbs() map the caa pages too
       [not found] <20250626114014.373748-1-kraxel@redhat.com>
  2025-06-26 11:40 ` [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation Gerd Hoffmann
  2025-06-26 11:40 ` [PATCH v4 2/3] x86/sev: fix error handling in sev_es_efi_map_ghcbs_caas() Gerd Hoffmann
@ 2025-06-26 11:40 ` Gerd Hoffmann
  2025-06-27 12:30   ` [tip: x86/sev] x86/sev: Let sev_es_efi_map_ghcbs() map the CA " tip-bot2 for Gerd Hoffmann
  2 siblings, 1 reply; 7+ messages in thread
From: Gerd Hoffmann @ 2025-06-26 11:40 UTC (permalink / raw)
  To: linux-coco, kvm
  Cc: Gerd Hoffmann, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, Ard Biesheuvel,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	open list:EXTENSIBLE FIRMWARE INTERFACE (EFI)

OVMF EFI firmware needs access to the CAA 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.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 arch/x86/include/asm/sev.h     |  4 ++--
 arch/x86/coco/sev/core.c       | 17 +++++++++++++++--
 arch/x86/platform/efi/efi_64.c |  4 ++--
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 58e028d42e41..6e0ef192f23b 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -445,7 +445,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_caas(pgd_t *pgd);
 extern void sev_enable(struct boot_params *bp);
 
 /*
@@ -556,7 +556,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_caas(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; }
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 3de8c3d2b55d..26b96e19f5e1 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -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 CCA 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_caas(pgd_t *pgd)
 {
 	struct sev_es_runtime_data *data;
-	unsigned long address, pflags;
+	unsigned long address, pflags, pflags_enc;
 	int retval;
 	int cpu;
 	u64 pfn;
@@ -1058,6 +1060,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);
@@ -1068,6 +1071,16 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
 		retval = kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags);
 		if (retval != 0)
 			return retval;
+
+		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;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index e7e8f77f77f8..97e8032db45d 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -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_caas(pgd)) {
+		pr_err("Failed to create 1:1 mapping for the GHCBs and CAAs!\n");
 		return 1;
 	}
 
-- 
2.50.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation
  2025-06-26 11:40 ` [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation Gerd Hoffmann
@ 2025-06-27  8:33   ` Gupta, Pankaj
  2025-06-27 12:30   ` [tip: x86/sev] x86/sev/vc: Fix EFI " tip-bot2 for Gerd Hoffmann
  1 sibling, 0 replies; 7+ messages in thread
From: Gupta, Pankaj @ 2025-06-27  8:33 UTC (permalink / raw)
  To: Gerd Hoffmann, linux-coco, kvm
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)


> In case efi_mm is active go use the userspace instruction decoder which
> supports fetching instructions from active_mm.  This is needed to make
> instruction emulation work for EFI runtime code, so it can use cpuid
> and rdmsr.
> 
> EFI runtime code uses the cpuid instruction to gather information about
> the environment it is running in, such as SEV being enabled or not, and
> choose (if needed) the SEV code path for ioport access.
> 
> EFI runtime code uses the rdmsr instruction to get the location of the
> CAA page (see SVSM spec, section 4.2 - "Post Boot").
> 
> The big picture behind this is that the kernel needs to be able to
> properly handle #VC exceptions that come from EFI runtime services.
> Since EFI runtime services have a special page table mapping for the EFI
> virtual address space, the efi_mm context must be used when decoding
> instructions during #VC handling.
> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

Reviewed-by: Pankaj Gupta <pankaj.gupta@amd.com>

> ---
>   arch/x86/coco/sev/vc-handle.c | 9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/coco/sev/vc-handle.c b/arch/x86/coco/sev/vc-handle.c
> index 0989d98da130..faf1fce89ed4 100644
> --- a/arch/x86/coco/sev/vc-handle.c
> +++ b/arch/x86/coco/sev/vc-handle.c
> @@ -17,6 +17,7 @@
>   #include <linux/mm.h>
>   #include <linux/io.h>
>   #include <linux/psp-sev.h>
> +#include <linux/efi.h>
>   #include <uapi/linux/sev-guest.h>
>   
>   #include <asm/init.h>
> @@ -178,9 +179,15 @@ static enum es_result __vc_decode_kern_insn(struct es_em_ctxt *ctxt)
>   		return ES_OK;
>   }
>   
> +/*
> + * User instruction decoding is also required for the EFI runtime. Even though
> + * the EFI runtime is running in kernel mode, it uses special EFI virtual
> + * address mappings that require the use of efi_mm to properly address and
> + * decode.
> + */
>   static enum es_result vc_decode_insn(struct es_em_ctxt *ctxt)
>   {
> -	if (user_mode(ctxt->regs))
> +	if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm))
>   		return __vc_decode_user_insn(ctxt);
>   	else
>   		return __vc_decode_kern_insn(ctxt);


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 2/3] x86/sev: fix error handling in sev_es_efi_map_ghcbs_caas()
  2025-06-26 11:40 ` [PATCH v4 2/3] x86/sev: fix error handling in sev_es_efi_map_ghcbs_caas() Gerd Hoffmann
@ 2025-06-27 12:01   ` Borislav Petkov
  0 siblings, 0 replies; 7+ messages in thread
From: Borislav Petkov @ 2025-06-27 12:01 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: linux-coco, kvm, Thomas Gleixner, Ingo Molnar, Dave Hansen,
	maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)

On Thu, Jun 26, 2025 at 01:40:12PM +0200, Gerd Hoffmann wrote:
> -		if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags))
> -			return 1;
> +		retval = kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags);
> +		if (retval != 0)
> +			return retval;

Yeah, I'd understand if it made any sense to propagate the error upwards but
this function is called exactly once by efi_setup_page_tables() and all it
needs to return is success/failure which the caller uses on the spot.

So no point in doing any of that nonsense. I'll zap it from the set.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tip: x86/sev] x86/sev: Let sev_es_efi_map_ghcbs() map the CA pages too
  2025-06-26 11:40 ` [PATCH v4 3/3] x86/sev: Let sev_es_efi_map_ghcbs() map the caa pages too Gerd Hoffmann
@ 2025-06-27 12:30   ` tip-bot2 for Gerd Hoffmann
  0 siblings, 0 replies; 7+ messages in thread
From: tip-bot2 for Gerd Hoffmann @ 2025-06-27 12:30 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Gerd Hoffmann, Borislav Petkov (AMD), x86, linux-kernel

The following commit has been merged into the x86/sev branch of tip:

Commit-ID:     a7549636f67f973474ebe1ad262acc2aa4d1327d
Gitweb:        https://git.kernel.org/tip/a7549636f67f973474ebe1ad262acc2aa4d1327d
Author:        Gerd Hoffmann <kraxel@redhat.com>
AuthorDate:    Thu, 26 Jun 2025 13:40:13 +02:00
Committer:     Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Fri, 27 Jun 2025 14:07:10 +02:00

x86/sev: Let sev_es_efi_map_ghcbs() map the CA pages too

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       | 17 +++++++++++++++--
 arch/x86/include/asm/sev.h     |  4 ++--
 arch/x86/platform/efi/efi_64.c |  4 ++--
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 8375ca7..46bd895 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -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;
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index fbb616f..a81769a 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -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; }
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index e7e8f77..b4409df 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -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;
 	}
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tip: x86/sev] x86/sev/vc: Fix EFI runtime instruction emulation
  2025-06-26 11:40 ` [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation Gerd Hoffmann
  2025-06-27  8:33   ` Gupta, Pankaj
@ 2025-06-27 12:30   ` tip-bot2 for Gerd Hoffmann
  1 sibling, 0 replies; 7+ messages in thread
From: tip-bot2 for Gerd Hoffmann @ 2025-06-27 12:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Gerd Hoffmann, Borislav Petkov (AMD), Pankaj Gupta, x86, linux-kernel

The following commit has been merged into the x86/sev branch of tip:

Commit-ID:     7b22e0432981c2fa230f1b493082b7e67112c4aa
Gitweb:        https://git.kernel.org/tip/7b22e0432981c2fa230f1b493082b7e67112c4aa
Author:        Gerd Hoffmann <kraxel@redhat.com>
AuthorDate:    Thu, 26 Jun 2025 13:40:11 +02:00
Committer:     Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Fri, 27 Jun 2025 13:53:12 +02:00

x86/sev/vc: Fix EFI runtime instruction emulation

In case efi_mm is active go use the userspace instruction decoder which
supports fetching instructions from active_mm.  This is needed to make
instruction emulation work for EFI runtime code, so it can use CPUID and
RDMSR.

EFI runtime code uses the CPUID instruction to gather information about
the environment it is running in, such as SEV being enabled or not, and
choose (if needed) the SEV code path for ioport access.

EFI runtime code uses the RDMSR instruction to get the location of the
CAA page (see SVSM spec, section 4.2 - "Post Boot").

The big picture behind this is that the kernel needs to be able to
properly handle #VC exceptions that come from EFI runtime services.
Since EFI runtime services have a special page table mapping for the EFI
virtual address space, the efi_mm context must be used when decoding
instructions during #VC handling.

  [ bp: Massage. ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Pankaj Gupta <pankaj.gupta@amd.com>
Link: https://lore.kernel.org/20250626114014.373748-2-kraxel@redhat.com
---
 arch/x86/coco/sev/vc-handle.c |  9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/x86/coco/sev/vc-handle.c b/arch/x86/coco/sev/vc-handle.c
index 0989d98..faf1fce 100644
--- a/arch/x86/coco/sev/vc-handle.c
+++ b/arch/x86/coco/sev/vc-handle.c
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 #include <linux/psp-sev.h>
+#include <linux/efi.h>
 #include <uapi/linux/sev-guest.h>
 
 #include <asm/init.h>
@@ -178,9 +179,15 @@ static enum es_result __vc_decode_kern_insn(struct es_em_ctxt *ctxt)
 		return ES_OK;
 }
 
+/*
+ * User instruction decoding is also required for the EFI runtime. Even though
+ * the EFI runtime is running in kernel mode, it uses special EFI virtual
+ * address mappings that require the use of efi_mm to properly address and
+ * decode.
+ */
 static enum es_result vc_decode_insn(struct es_em_ctxt *ctxt)
 {
-	if (user_mode(ctxt->regs))
+	if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm))
 		return __vc_decode_user_insn(ctxt);
 	else
 		return __vc_decode_kern_insn(ctxt);

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-06-27 12:30 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20250626114014.373748-1-kraxel@redhat.com>
2025-06-26 11:40 ` [PATCH v4 1/3] x86/sev/vc: fix efi runtime instruction emulation Gerd Hoffmann
2025-06-27  8:33   ` Gupta, Pankaj
2025-06-27 12:30   ` [tip: x86/sev] x86/sev/vc: Fix EFI " tip-bot2 for Gerd Hoffmann
2025-06-26 11:40 ` [PATCH v4 2/3] x86/sev: fix error handling in sev_es_efi_map_ghcbs_caas() Gerd Hoffmann
2025-06-27 12:01   ` Borislav Petkov
2025-06-26 11:40 ` [PATCH v4 3/3] x86/sev: Let sev_es_efi_map_ghcbs() map the caa pages too Gerd Hoffmann
2025-06-27 12:30   ` [tip: x86/sev] x86/sev: Let sev_es_efi_map_ghcbs() map the CA " tip-bot2 for Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®