All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tom Lendacky <thomas.lendacky@amd.com>
To: Melody Wang <huibo.wang@amd.com>, x86@kernel.org
Cc: LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 4/7] x86/sev: Route unsupported APIC register accesses to the hypervisor APIC emulation
Date: Fri, 31 Jul 2026 13:37:53 -0500	[thread overview]
Message-ID: <77738e02-3939-4e11-a736-b67b2f21d73e@amd.com> (raw)
In-Reply-To: <081659b1aaa293d9bfda3554790526a9a4040a90.1785375271.git.huibo.wang@amd.com>

On 7/29/26 20:48, Melody Wang wrote:
> The SVSM APIC emulation supports only a subset of the X2APIC MSRs.
> Therefore, route the unsupported ones to the hypervisor's X2APIC
> emulation.

Explain a bit more why this is needed? How will the hypervisor use this,
maybe give an example.

> 
> Signed-off-by: Melody Wang <huibo.wang@amd.com>
> ---
>  arch/x86/coco/sev/core.c            | 12 ++++++------
>  arch/x86/include/asm/sev-common.h   |  1 +
>  arch/x86/include/asm/sev.h          |  8 ++++----
>  arch/x86/kernel/apic/svsm_apic.c    | 11 +++++++----
>  arch/x86/kernel/apic/x2apic_savic.c |  8 ++++----

You could do the function rename as a separate pre-patch and then this
patch would be purley SVSM support. Up to you.

>  5 files changed, 22 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index 197119807230..b293a36c3594 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -972,7 +972,7 @@ int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd)
>  	return 0;
>  }
>  
> -u64 savic_ghcb_msr_read(u32 reg)
> +u64 hvs_ghcb_msr_read(u32 reg)

Not sure that hvs is really that descriptive.

sev_apic_ghcb_msr_read ?

>  {
>  	u64 msr = APIC_BASE_MSR + (reg >> 4);
>  	struct pt_regs regs = { .cx = msr };
> @@ -988,9 +988,9 @@ u64 savic_ghcb_msr_read(u32 reg)
>  
>  	res = __vc_handle_msr(ghcb, &ctxt, false);
>  	if (res != ES_OK) {
> -		pr_err("Secure AVIC MSR (0x%llx) read returned error (%d)\n", msr, res);
> +		pr_err("Hypervisor MSR (0x%llx) read returned error (%d)\n", msr, res);

Same here with Hypervisor... maybe "APIC MSR via GHCB..." ?

>  		/* MSR read failures are treated as fatal errors */
> -		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SAVIC_FAIL);
> +		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_APIC_MSR_FAIL);

Alteratively you could pass in the code to use so that it is unique for
Secure AVIC and Alternate Injection.

>  	}
>  
>  	__sev_put_ghcb(&state);
> @@ -998,7 +998,7 @@ u64 savic_ghcb_msr_read(u32 reg)
>  	return regs.ax | regs.dx << 32;
>  }
>  
> -void savic_ghcb_msr_write(u32 reg, u64 value)
> +void hvs_ghcb_msr_write(u32 reg, u64 value)
>  {
>  	u64 msr = APIC_BASE_MSR + (reg >> 4);
>  	struct pt_regs regs = {
> @@ -1018,9 +1018,9 @@ void savic_ghcb_msr_write(u32 reg, u64 value)
>  
>  	res = __vc_handle_msr(ghcb, &ctxt, true);
>  	if (res != ES_OK) {
> -		pr_err("Secure AVIC MSR (0x%llx) write returned error (%d)\n", msr, res);
> +		pr_err("Hypervisor MSR (0x%llx) write returned error (%d)\n", msr, res);
>  		/* MSR writes should never fail. Any failure is fatal error for SNP guest */
> -		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SAVIC_FAIL);
> +		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_APIC_MSR_FAIL);
>  	}
>  
>  	__sev_put_ghcb(&state);
> diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
> index 01a6e4dbe423..a41c52a16e31 100644
> --- a/arch/x86/include/asm/sev-common.h
> +++ b/arch/x86/include/asm/sev-common.h
> @@ -209,6 +209,7 @@ struct snp_psc_desc {
>  #define GHCB_TERM_SECURE_TSC		10	/* Secure TSC initialization failed */
>  #define GHCB_TERM_SVSM_CA_REMAP_FAIL	11	/* SVSM is present but CA could not be remapped */
>  #define GHCB_TERM_SAVIC_FAIL		12	/* Secure AVIC-specific failure */
> +#define GHCB_TERM_APIC_MSR_FAIL		13	/* APIC MSR failure */
>  
>  #define GHCB_RESP_CODE(v)		((v) & GHCB_MSR_INFO_MASK)
>  
> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
> index f8a5b5cf939a..491a891a7694 100644
> --- a/arch/x86/include/asm/sev.h
> +++ b/arch/x86/include/asm/sev.h
> @@ -549,8 +549,8 @@ void __init snp_secure_tsc_prepare(void);
>  void __init snp_secure_tsc_init(void);
>  enum es_result savic_register_gpa(u64 gpa);
>  enum es_result savic_unregister_gpa(u64 *gpa);
> -u64 savic_ghcb_msr_read(u32 reg);
> -void savic_ghcb_msr_write(u32 reg, u64 value);
> +u64 hvs_ghcb_msr_read(u32 reg);
> +void hvs_ghcb_msr_write(u32 reg, u64 value);
>  
>  static __always_inline void vc_ghcb_invalidate(struct ghcb *ghcb)
>  {
> @@ -659,8 +659,8 @@ static inline void __init snp_secure_tsc_init(void) { }
>  static inline void sev_evict_cache(void *va, int npages) {}
>  static inline enum es_result savic_register_gpa(u64 gpa) { return ES_UNSUPPORTED; }
>  static inline enum es_result savic_unregister_gpa(u64 *gpa) { return ES_UNSUPPORTED; }
> -static inline void savic_ghcb_msr_write(u32 reg, u64 value) { }
> -static inline u64 savic_ghcb_msr_read(u32 reg) { return 0; }
> +static inline void hvs_ghcb_msr_write(u32 reg, u64 value) { }
> +static inline u64 hvs_ghcb_msr_read(u32 reg) { return 0; }
>  
>  #endif	/* CONFIG_AMD_MEM_ENCRYPT */
>  
> diff --git a/arch/x86/kernel/apic/svsm_apic.c b/arch/x86/kernel/apic/svsm_apic.c
> index 7040a1ca8b55..a4e7ba7e9985 100644
> --- a/arch/x86/kernel/apic/svsm_apic.c
> +++ b/arch/x86/kernel/apic/svsm_apic.c
> @@ -68,7 +68,8 @@ static void svsm_apic_msr_write(u32 reg, u32 v)
>  		}
>  		break;
>  	default:
> -		pr_err("SVSM_APIC_WRITE_REGISTER 0x%x not supported\n", reg);
> +		pr_debug("SVSM_APIC_WRITE_REGISTER to HV (0x%x, val:0x%x)\n", reg, v);

Not sure what makes this different from the SVSM calls that don't have a
pr_debug(), so you can probably remove the pr_debug().

> +		hvs_ghcb_msr_write(reg, v);
>  		break;
>  	}
>  }
> @@ -77,6 +78,7 @@ static u32 svsm_apic_msr_read(u32 reg)
>  {
>  	u32 msr = APIC_BASE_MSR + (reg >> 4);
>  	struct svsm_call call = {};
> +	u64 val;
>  	int ret;
>  
>  	switch (reg) {
> @@ -93,17 +95,18 @@ static u32 svsm_apic_msr_read(u32 reg)
>  		call.rcx = msr;
>  
>  		ret = svsm_do_call(&call);
> +		val = call.rdx_out;
>  		if (ret) {
>  			pr_err("SVSM_APIC_READ_REGISTER: 0x%x, error: %d\n", reg, ret);
>  			sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
>  		}
>  		break;
>  	default:
> -		pr_err("SVSM_APIC_READ_REGISTER: 0x%x not supported\n", reg);
> -		return 0;
> +		val = hvs_ghcb_msr_read(reg);
> +		pr_debug("SVSM_APIC_READ_REGISTER from HV 0x%x, val: 0x%llx\n", reg, val);

Ditto.

Thanks,
Tom

>  	}
>  
> -	return call.rdx_out;
> +	return val;
>  }
>  
>  static inline void svsm_apic_msr_eoi(void)
> diff --git a/arch/x86/kernel/apic/x2apic_savic.c b/arch/x86/kernel/apic/x2apic_savic.c
> index 4bc6d7e018a5..71040f77dfaf 100644
> --- a/arch/x86/kernel/apic/x2apic_savic.c
> +++ b/arch/x86/kernel/apic/x2apic_savic.c
> @@ -72,7 +72,7 @@ static u32 savic_read(u32 reg)
>  	case APIC_LVT0:
>  	case APIC_LVT1:
>  	case APIC_LVTERR:
> -		return savic_ghcb_msr_read(reg);
> +		return hvs_ghcb_msr_read(reg);
>  	case APIC_ID:
>  	case APIC_LVR:
>  	case APIC_TASKPRI:
> @@ -193,7 +193,7 @@ static void savic_icr_write(u32 icr_low, u32 icr_high)
>  
>  	icr_data = ((u64)icr_high) << 32 | icr_low;
>  	if (dsh != APIC_DEST_SELF)
> -		savic_ghcb_msr_write(APIC_ICR, icr_data);
> +		hvs_ghcb_msr_write(APIC_ICR, icr_data);
>  	apic_set_reg64(this_cpu_ptr(savic_page), APIC_ICR, icr_data);
>  }
>  
> @@ -210,7 +210,7 @@ static void savic_write(u32 reg, u32 data)
>  	case APIC_LVTTHMR:
>  	case APIC_LVTPC:
>  	case APIC_LVTERR:
> -		savic_ghcb_msr_write(reg, data);
> +		hvs_ghcb_msr_write(reg, data);
>  		break;
>  	case APIC_TASKPRI:
>  	case APIC_EOI:
> @@ -316,7 +316,7 @@ static void savic_eoi(void)
>  		 * interrupts. Return to the guest from GHCB protocol event takes
>  		 * care of re-evaluating interrupt state.
>  		 */
> -		savic_ghcb_msr_write(APIC_EOI, 0);
> +		hvs_ghcb_msr_write(APIC_EOI, 0);
>  	} else {
>  		/*
>  		 * Hardware clears APIC_ISR and re-evaluates the interrupt state


  reply	other threads:[~2026-07-31 18:38 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-30  1:48 [PATCH 0/7] Alternate Injection: Secure Interrupt Delivery for SEV-SNP Guests - Guest Support Melody Wang
2026-07-30  1:48 ` [PATCH 1/7] x86/sev: Add support for Alternate Injection Melody Wang
2026-07-31 15:27   ` Tom Lendacky
2026-07-30  1:48 ` [PATCH 2/7] x86/apic: Add an SVSM APIC driver Melody Wang
2026-07-31 17:39   ` Tom Lendacky
2026-07-30  1:48 ` [PATCH 3/7] x86/sev: Allow the guest to configure interrupt vectors for the hypervisor Melody Wang
2026-07-31 17:52   ` Tom Lendacky
2026-07-30  1:48 ` [PATCH 4/7] x86/sev: Route unsupported APIC register accesses to the hypervisor APIC emulation Melody Wang
2026-07-31 18:37   ` Tom Lendacky [this message]
2026-07-30  1:48 ` [PATCH 5/7] x86/sev: Add a function to contain all SEV-specific setup operations Melody Wang
2026-07-31 19:15   ` Tom Lendacky
2026-07-30  1:48 ` [PATCH 6/7] x86/sev: Register the guest with the SVSM APIC protocol Melody Wang
2026-07-31 19:18   ` Tom Lendacky
2026-07-30  1:48 ` [PATCH 7/7] x86/sev: Indicate that Alternate Injection is supported in the guest Melody Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=77738e02-3939-4e11-a736-b67b2f21d73e@amd.com \
    --to=thomas.lendacky@amd.com \
    --cc=huibo.wang@amd.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.