From: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com>
To: <linux-kernel@vger.kernel.org>
Cc: <bp@alien8.de>, <tglx@linutronix.de>, <mingo@redhat.com>,
<dave.hansen@linux.intel.com>, <Thomas.Lendacky@amd.com>,
<nikunj@amd.com>, <Santosh.Shukla@amd.com>,
<Vasant.Hegde@amd.com>, <Suravee.Suthikulpanit@amd.com>,
<David.Kaplan@amd.com>, <x86@kernel.org>, <hpa@zytor.com>,
<peterz@infradead.org>, <seanjc@google.com>,
<pbonzini@redhat.com>, <kvm@vger.kernel.org>,
<kirill.shutemov@linux.intel.com>, <huibo.wang@amd.com>,
<naveen.rao@amd.com>, <francescolavra.fl@gmail.com>
Subject: [PATCH v4 04/18] x86/apic: Populate .read()/.write() callbacks of Secure AVIC driver
Date: Thu, 17 Apr 2025 14:46:54 +0530 [thread overview]
Message-ID: <20250417091708.215826-5-Neeraj.Upadhyay@amd.com> (raw)
In-Reply-To: <20250417091708.215826-1-Neeraj.Upadhyay@amd.com>
Add read() and write() APIC callback functions to read and write x2APIC
registers directly from the guest APIC backing page of a vCPU.
The x2APIC registers are mapped at an offset within the guest APIC
backing page which is same as their x2APIC MMIO offset. Secure AVIC
adds new registers such as ALLOWED_IRRs (which are at 4-byte offset
within the IRR register offset range) and NMI_REQ to the APIC register
space.
When Secure AVIC is enabled, guest's rdmsr/wrmsr of APIC registers
result in VC exception (for non-accelerated register accesses) with
error code VMEXIT_AVIC_NOACCEL. The VC exception handler can read/write
the x2APIC register in the guest APIC backing page to complete the
rdmsr/wrmsr. Since doing this would increase the latency of accessing
x2APIC registers, instead of doing rdmsr/wrmsr based reg accesses
and handling reads/writes in VC exception, directly read/write APIC
registers from/to the guest APIC backing page of the vCPU in read()
and write() callbacks of the Secure AVIC APIC driver.
Co-developed-by: Kishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: Kishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com>
---
Changes since v3:
- Removed "x2apic_" from savic's apic cbs func names.
arch/x86/include/asm/apicdef.h | 2 +
arch/x86/kernel/apic/x2apic_savic.c | 116 +++++++++++++++++++++++++++-
2 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 094106b6a538..be39a543fbe5 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -135,6 +135,8 @@
#define APIC_TDR_DIV_128 0xA
#define APIC_EFEAT 0x400
#define APIC_ECTRL 0x410
+#define APIC_SEOI 0x420
+#define APIC_IER 0x480
#define APIC_EILVTn(n) (0x500 + 0x10 * n)
#define APIC_EILVT_NR_AMD_K8 1 /* # of extended interrupts */
#define APIC_EILVT_NR_AMD_10H 4
diff --git a/arch/x86/kernel/apic/x2apic_savic.c b/arch/x86/kernel/apic/x2apic_savic.c
index 0a2cb1c03d08..4761afc7527d 100644
--- a/arch/x86/kernel/apic/x2apic_savic.c
+++ b/arch/x86/kernel/apic/x2apic_savic.c
@@ -9,6 +9,7 @@
#include <linux/cc_platform.h>
#include <linux/percpu-defs.h>
+#include <linux/align.h>
#include <asm/apic.h>
#include <asm/sev.h>
@@ -32,6 +33,117 @@ static int savic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return x2apic_enabled() && cc_platform_has(CC_ATTR_SNP_SECURE_AVIC);
}
+static __always_inline u32 get_reg(unsigned int offset)
+{
+ return READ_ONCE(this_cpu_ptr(apic_page)->regs[offset >> 2]);
+}
+
+static __always_inline void set_reg(unsigned int offset, u32 val)
+{
+ WRITE_ONCE(this_cpu_ptr(apic_page)->regs[offset >> 2], val);
+}
+
+#define SAVIC_ALLOWED_IRR 0x204
+
+static u32 savic_read(u32 reg)
+{
+ /*
+ * When Secure AVIC is enabled, rdmsr/wrmsr of APIC registers
+ * result in VC exception (for non-accelerated register accesses)
+ * with VMEXIT_AVIC_NOACCEL error code. The VC exception handler
+ * can read/write the x2APIC register in the guest APIC backing page.
+ * Since doing this would increase the latency of accessing x2APIC
+ * registers, instead of doing rdmsr/wrmsr based accesses and
+ * handling apic register reads/writes in VC exception, the read()
+ * and write() callbacks directly read/write APIC register from/to
+ * the vCPU APIC backing page.
+ */
+ switch (reg) {
+ case APIC_LVTT:
+ case APIC_TMICT:
+ case APIC_TMCCT:
+ case APIC_TDCR:
+ case APIC_ID:
+ case APIC_LVR:
+ case APIC_TASKPRI:
+ case APIC_ARBPRI:
+ case APIC_PROCPRI:
+ case APIC_LDR:
+ case APIC_SPIV:
+ case APIC_ESR:
+ case APIC_ICR:
+ case APIC_LVTTHMR:
+ case APIC_LVTPC:
+ case APIC_LVT0:
+ case APIC_LVT1:
+ case APIC_LVTERR:
+ case APIC_EFEAT:
+ case APIC_ECTRL:
+ case APIC_SEOI:
+ case APIC_IER:
+ case APIC_EILVTn(0) ... APIC_EILVTn(3):
+ return get_reg(reg);
+ case APIC_ISR ... APIC_ISR + 0x70:
+ case APIC_TMR ... APIC_TMR + 0x70:
+ if (WARN_ONCE(!IS_ALIGNED(reg, 16),
+ "APIC reg read offset 0x%x not aligned at 16 bytes", reg))
+ return 0;
+ return get_reg(reg);
+ /* IRR and ALLOWED_IRR offset range */
+ case APIC_IRR ... APIC_IRR + 0x74:
+ /*
+ * Either aligned at 16 bytes for valid IRR reg offset or a
+ * valid Secure AVIC ALLOWED_IRR offset.
+ */
+ if (WARN_ONCE(!(IS_ALIGNED(reg, 16) ||
+ IS_ALIGNED(reg - SAVIC_ALLOWED_IRR, 16)),
+ "Misaligned IRR/ALLOWED_IRR APIC reg read offset 0x%x", reg))
+ return 0;
+ return get_reg(reg);
+ default:
+ pr_err("Permission denied: read of Secure AVIC reg offset 0x%x\n", reg);
+ return 0;
+ }
+}
+
+#define SAVIC_NMI_REQ 0x278
+
+static void savic_write(u32 reg, u32 data)
+{
+ switch (reg) {
+ case APIC_LVTT:
+ case APIC_LVT0:
+ case APIC_LVT1:
+ case APIC_TMICT:
+ case APIC_TDCR:
+ case APIC_SELF_IPI:
+ case APIC_TASKPRI:
+ case APIC_EOI:
+ case APIC_SPIV:
+ case SAVIC_NMI_REQ:
+ case APIC_ESR:
+ case APIC_ICR:
+ case APIC_LVTTHMR:
+ case APIC_LVTPC:
+ case APIC_LVTERR:
+ case APIC_ECTRL:
+ case APIC_SEOI:
+ case APIC_IER:
+ case APIC_EILVTn(0) ... APIC_EILVTn(3):
+ set_reg(reg, data);
+ break;
+ /* ALLOWED_IRR offsets are writable */
+ case SAVIC_ALLOWED_IRR ... SAVIC_ALLOWED_IRR + 0x70:
+ if (IS_ALIGNED(reg - SAVIC_ALLOWED_IRR, 16)) {
+ set_reg(reg, data);
+ break;
+ }
+ fallthrough;
+ default:
+ pr_err("Permission denied: write to Secure AVIC reg offset 0x%x\n", reg);
+ }
+}
+
static void savic_setup(void)
{
void *backing_page;
@@ -95,8 +207,8 @@ static struct apic apic_x2apic_savic __ro_after_init = {
.nmi_to_offline_cpu = true,
- .read = native_apic_msr_read,
- .write = native_apic_msr_write,
+ .read = savic_read,
+ .write = savic_write,
.eoi = native_apic_msr_eoi,
.icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write,
--
2.34.1
next prev parent reply other threads:[~2025-04-17 9:19 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-17 9:16 [PATCH v4 00/18] AMD: Add Secure AVIC Guest Support Neeraj Upadhyay
2025-04-17 9:16 ` [PATCH v4 01/18] KVM: x86: Move find_highest_vector() to a common header Neeraj Upadhyay
2025-04-17 9:16 ` [PATCH v4 02/18] x86/apic: Add new driver for Secure AVIC Neeraj Upadhyay
2025-04-17 9:16 ` [PATCH v4 03/18] x86/apic: Initialize Secure AVIC APIC backing page Neeraj Upadhyay
2025-04-17 9:16 ` Neeraj Upadhyay [this message]
2025-04-17 9:16 ` [PATCH v4 05/18] x86/apic: Initialize APIC ID for Secure AVIC Neeraj Upadhyay
2025-04-17 9:16 ` [PATCH v4 06/18] x86/apic: Add update_vector callback " Neeraj Upadhyay
2025-04-17 10:50 ` Thomas Gleixner
2025-04-17 12:00 ` Neeraj Upadhyay
2025-04-17 16:51 ` Thomas Gleixner
2025-04-17 10:52 ` Thomas Gleixner
2025-04-17 12:12 ` Neeraj Upadhyay
2025-04-17 16:52 ` Thomas Gleixner
2025-04-17 9:16 ` [PATCH v4 07/18] x86/apic: Add support to send IPI " Neeraj Upadhyay
2025-04-17 9:16 ` [PATCH v4 08/18] x86/apic: Support LAPIC timer " Neeraj Upadhyay
2025-04-17 9:16 ` [PATCH v4 09/18] x86/sev: Initialize VGIF for secondary VCPUs " Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 10/18] x86/apic: Add support to send NMI IPI " Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 11/18] x86/apic: Allow NMI to be injected from hypervisor " Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 12/18] x86/sev: Enable NMI support " Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 13/18] x86/apic: Read and write LVT* APIC registers from HV for SAVIC guests Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 14/18] x86/apic: Handle EOI writes " Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 15/18] x86/apic: Add kexec support for Secure AVIC Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 16/18] x86/apic: Enable Secure AVIC in Control MSR Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 17/18] x86/sev: Prevent SECURE_AVIC_CONTROL MSR interception for Secure AVIC guests Neeraj Upadhyay
2025-04-17 9:17 ` [PATCH v4 18/18] x86/sev: Indicate SEV-SNP guest supports Secure AVIC Neeraj Upadhyay
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=20250417091708.215826-5-Neeraj.Upadhyay@amd.com \
--to=neeraj.upadhyay@amd.com \
--cc=David.Kaplan@amd.com \
--cc=Santosh.Shukla@amd.com \
--cc=Suravee.Suthikulpanit@amd.com \
--cc=Thomas.Lendacky@amd.com \
--cc=Vasant.Hegde@amd.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=francescolavra.fl@gmail.com \
--cc=hpa@zytor.com \
--cc=huibo.wang@amd.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=naveen.rao@amd.com \
--cc=nikunj@amd.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--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 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®