From: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com>
To: <kvm@vger.kernel.org>, <seanjc@google.com>, <pbonzini@redhat.com>
Cc: <linux-kernel@vger.kernel.org>, <Thomas.Lendacky@amd.com>,
<nikunj@amd.com>, <Santosh.Shukla@amd.com>,
<Vasant.Hegde@amd.com>, <Suravee.Suthikulpanit@amd.com>,
<bp@alien8.de>, <David.Kaplan@amd.com>, <huibo.wang@amd.com>,
<naveen.rao@amd.com>, <pgonda@google.com>,
<linux-kselftest@vger.kernel.org>, <shuah@kernel.org>
Subject: [RFC PATCH 26/31] KVM: selftests: Add test to verify APIC MSR accesses for SAVIC guest
Date: Fri, 28 Feb 2025 15:00:19 +0530 [thread overview]
Message-ID: <20250228093024.114983-27-Neeraj.Upadhyay@amd.com> (raw)
In-Reply-To: <20250228093024.114983-1-Neeraj.Upadhyay@amd.com>
Extend SAVIC test to verify APIC MSR accesses in SAVIC enabled
mode. Verify the behavior of reads and writes using rdmsr/wrmsr
for various APIC registers. In addition, test whether wrmsr
based writes are propagated to guest backing page.
Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com>
---
.../testing/selftests/kvm/include/x86/apic.h | 1 +
.../testing/selftests/kvm/include/x86/savic.h | 3 +
tools/testing/selftests/kvm/lib/x86/savic.c | 7 +-
tools/testing/selftests/kvm/x86/savic_test.c | 192 +++++++++++++++++-
4 files changed, 198 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/x86/apic.h b/tools/testing/selftests/kvm/include/x86/apic.h
index aa3a5d54c404..af555638086f 100644
--- a/tools/testing/selftests/kvm/include/x86/apic.h
+++ b/tools/testing/selftests/kvm/include/x86/apic.h
@@ -33,6 +33,7 @@
#define APIC_SPIV 0xF0
#define APIC_SPIV_FOCUS_DISABLED (1 << 9)
#define APIC_SPIV_APIC_ENABLED (1 << 8)
+#define APIC_ISR 0x100
#define APIC_TMR 0x180
#define APIC_IRR 0x200
#define APIC_ICR 0x300
diff --git a/tools/testing/selftests/kvm/include/x86/savic.h b/tools/testing/selftests/kvm/include/x86/savic.h
index cb432eb527b3..33f19f5e39b3 100644
--- a/tools/testing/selftests/kvm/include/x86/savic.h
+++ b/tools/testing/selftests/kvm/include/x86/savic.h
@@ -6,6 +6,9 @@
#ifndef SELFTEST_KVM_SAVIC_H
#define SELFTEST_KVM_SAVIC_H
+#define APIC_REG_OFF(VEC) (VEC / 32 * 16)
+#define APIC_VEC_POS(VEC) (VEC % 32)
+
struct guest_apic_page;
void guest_apic_pages_init(struct kvm_vm *vm);
diff --git a/tools/testing/selftests/kvm/lib/x86/savic.c b/tools/testing/selftests/kvm/lib/x86/savic.c
index d4c9fcf835ad..c637e486b6e8 100644
--- a/tools/testing/selftests/kvm/lib/x86/savic.c
+++ b/tools/testing/selftests/kvm/lib/x86/savic.c
@@ -9,6 +9,7 @@
#include "kvm_util.h"
#include "sev.h"
#include "ex_regs.h"
+#include "savic.h"
struct apic_page {
u8 apic_regs[PAGE_SIZE];
@@ -45,9 +46,6 @@ enum lapic_lvt_entry {
#define SVM_EXIT_AVIC_UNACCELERATED_ACCESS 0x402
#define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401
-#define REG_OFF(VEC) (VEC / 32 * 16)
-#define VEC_POS(VEC) (VEC % 32)
-
#define SAVIC_NMI_REQ_OFFSET 0x278
/*
@@ -363,7 +361,8 @@ static void send_ipi(int cpu, int vector, bool nmi)
if (nmi)
savic_write_reg(apic_page, SAVIC_NMI_REQ_OFFSET, 1);
else
- savic_write_reg(apic_page, APIC_IRR + REG_OFF(vector), BIT(VEC_POS(vector)));
+ savic_write_reg(apic_page, APIC_IRR + APIC_REG_OFF(vector),
+ BIT(APIC_VEC_POS(vector)));
}
static bool is_cpu_present(int cpu)
diff --git a/tools/testing/selftests/kvm/x86/savic_test.c b/tools/testing/selftests/kvm/x86/savic_test.c
index ca1d7352bc3e..8cba7a81bce2 100644
--- a/tools/testing/selftests/kvm/x86/savic_test.c
+++ b/tools/testing/selftests/kvm/x86/savic_test.c
@@ -29,6 +29,7 @@ enum savic_test_state {
SAVIC_TEST_STATE(X2APIC_ENABLE),
/* APIC regs state on Secure AVIC enablement */
SAVIC_TEST_STATE(SAVIC_EN),
+ SAVIC_TEST_STATE(SAVIC_APIC_MSR_ACCESSES),
};
/* APIC reg values written by host. */
@@ -288,6 +289,193 @@ static void guest_savic_enabled(int id)
savic_write_apic_regs(apage);
}
+static int savic_wrmsr(uint32_t reg, uint64_t val)
+{
+ switch (reg) {
+ case APIC_LVR:
+ case APIC_LDR:
+ case APIC_ISR:
+ case APIC_TMR:
+ case APIC_IRR:
+ case APIC_TMCCT:
+ x2apic_write_reg_fault(reg, val);
+ return -1;
+ default:
+ x2apic_write_reg(reg, val);
+ break;
+ }
+
+ return 0;
+}
+
+static uint64_t savic_rdmsr(uint32_t reg)
+{
+ uint64_t val;
+ uint32_t msr = APIC_BASE_MSR + (reg >> 4);
+
+ switch (reg) {
+ case APIC_EOI:
+ uint8_t fault = rdmsr_safe(msr, &val);
+
+ __GUEST_ASSERT(fault == GP_VECTOR,
+ "Wanted #GP on RDMSR(%x) = %x, got 0x%x\n",
+ msr, GP_VECTOR, fault);
+ return val;
+ default:
+ return x2apic_read_reg(reg);
+ }
+}
+
+static void guest_verify_host_guest_reg(struct guest_apic_page *apage, uint32_t reg,
+ uint64_t val, char *regname)
+{
+ uint64_t hval, gval, gval2;
+
+ if (savic_wrmsr(reg, val) == -1) {
+ savic_write_reg(apage, reg, val);
+ /*
+ * Write using PV interface if wrmsr fails. Skip for
+ * regs which trigger GP
+ */
+ if (reg != APIC_LVR && reg != APIC_TMR && reg != APIC_IRR)
+ savic_hv_write_reg(reg, val);
+ }
+
+ gval = savic_read_reg(apage, reg);
+ gval2 = savic_rdmsr(reg);
+ hval = savic_hv_read_reg(reg);
+ __GUEST_ASSERT(gval == val, "Unexpected Guest %s 0x%lx, expected val:0x%lx\n",
+ regname, gval, val);
+ __GUEST_ASSERT(gval == gval2, "Unexpected Guest %s backing page value : 0x%lx, msr read val:0x%lx\n",
+ regname, gval, gval2);
+
+ switch (reg) {
+ case APIC_LVR:
+ case APIC_LDR:
+ case APIC_ISR:
+ case APIC_TMICT:
+ case APIC_TDCR:
+ case APIC_LVTT:
+ case APIC_LVTTHMR:
+ case APIC_LVTPC:
+ case APIC_LVT0:
+ case APIC_LVT1:
+ case APIC_LVTERR:
+ __GUEST_ASSERT(hval == gval, "Guest 0x%lx host 0x%lx %s mismatch\n",
+ gval, hval, regname);
+ break;
+ case APIC_TASKPRI:
+ case APIC_SPIV:
+ case APIC_ICR:
+ case APIC_TMR:
+ case APIC_IRR:
+ __GUEST_ASSERT(hval != gval, "Guest 0x%lx host 0x%lx reg: %x %s must not match\n",
+ gval, hval, reg, regname);
+ break;
+ default:
+ break;
+ }
+}
+
+static inline uint32_t x2apic_ldr(uint32_t id)
+{
+ return ((id >> 4) << 16) | (1 << (id & 0xf));
+}
+
+static void guest_savic_apic_msr_accesses(int id)
+{
+ struct guest_apic_page *apage = get_guest_apic_page();
+ uint64_t val, hval;
+ uint32_t reg;
+ int vec;
+ int i;
+ uint32_t lvt_regs[] = {
+ APIC_LVTT, APIC_LVTTHMR, APIC_LVTPC,
+ APIC_LVT0, APIC_LVT1, APIC_LVTERR
+ };
+
+ reg = APIC_LVR;
+ val = savic_hv_read_reg(reg);
+ /* APIC_LVR state is in sync between host and guest. */
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_LVR");
+
+ reg = APIC_TASKPRI;
+ val = 0x30;
+ /* Write new TASKPRI to host using PV interface. */
+ savic_hv_write_reg(reg, val);
+ val = 0x40;
+ /* TASKPRI is accelerated and state is not up-to-date in host. */
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_TASKPRI");
+
+ reg = APIC_PROCPRI;
+ val = x2apic_read_reg(reg);
+ /* APIC_PROCPRI is updated with the APIC_TASKPRI update above. */
+ GUEST_ASSERT((val & 0xf0) == (x2apic_read_reg(APIC_TASKPRI) & 0xf0));
+ GUEST_ASSERT((val & 0xf0) == 0x40);
+ vec = 0x20;
+ x2apic_write_reg(APIC_ICR, APIC_DEST_SELF | APIC_INT_ASSERT | vec);
+ /* Interrupt remains pending in APIC_IRR. */
+ val = savic_read_reg(apage, APIC_IRR + APIC_REG_OFF(vec));
+ GUEST_ASSERT((val & BIT_ULL(APIC_VEC_POS(vec))) == BIT_ULL(APIC_VEC_POS(vec)));
+ savic_wrmsr(APIC_TASKPRI, 0x0);
+
+ /* Triggers GP fault */
+ savic_rdmsr(APIC_EOI);
+
+ reg = APIC_LDR;
+ val = x2apic_ldr(savic_rdmsr(APIC_ID));
+ hval = savic_hv_read_reg(APIC_LDR);
+ __GUEST_ASSERT(val == hval, "APIC_LDR mismatch between host %lx and guest %lx",
+ hval, val);
+
+ /* APIC_SPIV state is not visible to host. */
+ reg = APIC_SPIV;
+ val = savic_rdmsr(APIC_SPIV) & ~APIC_SPIV_APIC_ENABLED;
+ savic_hv_write_reg(reg, val);
+ val = savic_rdmsr(APIC_SPIV) | APIC_SPIV_APIC_ENABLED;
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_SPIV");
+
+ reg = APIC_ISR;
+ (void) savic_rdmsr(reg);
+ /* Triggers GP fault */
+ savic_wrmsr(reg, 0x10);
+
+ /* APIC_TMR is not synced to host. */
+ reg = APIC_TMR;
+ val = 0x10000;
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_TMR");
+ vec = 0x20;
+ savic_write_reg(apage, reg + APIC_REG_OFF(vec), BIT_ULL(APIC_VEC_POS(vec)));
+ GUEST_ASSERT(x2apic_read_reg(reg + APIC_REG_OFF(vec)) & BIT_ULL(APIC_VEC_POS(vec)));
+
+ reg = APIC_IRR;
+ val = 0x10000;
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_IRR");
+ savic_write_reg(apage, reg, 0x0);
+
+ reg = APIC_TMICT;
+ val = 0x555;
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_TMICT");
+
+ reg = APIC_TMCCT;
+ savic_rdmsr(reg);
+ savic_wrmsr(reg, 0xf);
+
+ reg = APIC_TDCR;
+ val = 0x1;
+ savic_hv_write_reg(reg, val);
+ val = 0x3;
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_TDCR");
+
+ for (i = 0; i < ARRAY_SIZE(lvt_regs); i++) {
+ reg = lvt_regs[i];
+ val = 0x41;
+ savic_hv_write_reg(reg, val);
+ val = 0x42;
+ guest_verify_host_guest_reg(apage, reg, val, "APIC_LVTx");
+ }
+}
+
static void guest_code(int id)
{
GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SNP_SECURE_AVIC);
@@ -302,6 +490,8 @@ static void guest_code(int id)
SAVIC_GUEST_SYNC(SAVIC_EN, guest_savic_enabled);
+ SAVIC_GUEST_SYNC(SAVIC_APIC_MSR_ACCESSES, guest_savic_apic_msr_accesses);
+
GUEST_DONE();
}
@@ -448,7 +638,7 @@ int main(int argc, char *argv[])
vcpu_args_set(vcpus[0], 1, vcpus[0]->id);
- vm_install_exception_handler(vm, 29, sev_es_vc_handler);
+ vm_install_exception_handler(vm, 29, savic_vc_handler);
vm_sev_launch(vm, snp_default_policy(), NULL);
r = pthread_create(&threads[0], NULL, vcpu_thread, vcpus[0]);
--
2.34.1
next prev parent reply other threads:[~2025-02-28 10:03 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-28 9:29 [RFC PATCH 00/31] AMD: Add Secure AVIC KVM selftests Neeraj Upadhyay
2025-02-28 9:29 ` [RFC PATCH 01/31] Add GHCB with setters and getters Neeraj Upadhyay
2025-02-28 9:29 ` [RFC PATCH 02/31] Add arch specific additional guest pages Neeraj Upadhyay
2025-02-28 9:29 ` [RFC PATCH 03/31] Add vm_vaddr_alloc_pages_shared() Neeraj Upadhyay
2025-02-28 9:29 ` [RFC PATCH 04/31] Add GHCB allocations and helpers Neeraj Upadhyay
2025-02-28 9:29 ` [RFC PATCH 05/31] Add is_sev_enabled() helpers Neeraj Upadhyay
2025-02-28 9:29 ` [RFC PATCH 06/31] Add ability for SEV-ES guests to use ucalls via GHCB Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 07/31] KVM: selftests: Fix ghcb_entry returned in ghcb_alloc() Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 08/31] KVM: selftests: Make GHCB entry page size aligned Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 09/31] KVM: selftests: Add support for #VC in x86 exception handlers Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 10/31] KVM: selftests: Add MSR VC handling support for SEV-ES VMs Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 11/31] KVM: selftests: Skip vm_is_gpa_protected() call for APIC MMIO base Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 12/31] KVM: selftests: Add instruction decoding support Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 13/31] " Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 14/31] KVM: selftests: Add MMIO VC exception handling for SEV-ES guests Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 15/31] KVM: selftests: Add instruction decoding for movabs instructions Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 16/31] KVM: selftests: Add SEV guests support in xapic_state_test Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 17/31] KVM: selftests: Add x2apic mode testing in xapic_ipi_test Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 18/31] KVM: selftests: Add SEV VM support " Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 19/31] KVM: selftests: Add Secure AVIC lib Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 20/31] KVM: selftests: Add unaccelerated APIC msrs #VC handling Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 21/31] KVM: selftests: Add IPI handling support for Secure AVIC Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 22/31] KVM: selftests: Add args param to kvm_arch_vm_post_create() Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 23/31] KVM: selftests: Add SAVIC GPA notification GHCB call Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 24/31] KVM: selftests: Add Secure AVIC mode to xapic_ipi_test Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 25/31] KVM: selftests: Add Secure AVIC APIC regs test Neeraj Upadhyay
2025-02-28 9:30 ` Neeraj Upadhyay [this message]
2025-02-28 9:30 ` [RFC PATCH 27/31] KVM: selftests: Extend savic test with idle halt testing Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 28/31] KVM: selftests: Add IOAPIC tests for Secure AVIC Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 29/31] KVM: selftests: Add cross-vCPU IPI testing for SAVIC guests Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 30/31] KVM: selftests: Add NMI test " Neeraj Upadhyay
2025-02-28 9:30 ` [RFC PATCH 31/31] KVM: selftests: Add MSI injection test for SAVIC 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=20250228093024.114983-27-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=huibo.wang@amd.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=naveen.rao@amd.com \
--cc=nikunj@amd.com \
--cc=pbonzini@redhat.com \
--cc=pgonda@google.com \
--cc=seanjc@google.com \
--cc=shuah@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®