[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250923050942.206116-36-Neeraj.Upadhyay@amd.com>
Date: Tue, 23 Sep 2025 10:39:42 +0530
From: Neeraj Upadhyay <Neeraj.Upadhyay@....com>
To: <kvm@...r.kernel.org>, <seanjc@...gle.com>, <pbonzini@...hat.com>
CC: <linux-kernel@...r.kernel.org>, <Thomas.Lendacky@....com>,
<nikunj@....com>, <Santosh.Shukla@....com>, <Vasant.Hegde@....com>,
<Suravee.Suthikulpanit@....com>, <bp@...en8.de>, <David.Kaplan@....com>,
<huibo.wang@....com>, <naveen.rao@....com>, <pgonda@...gle.com>,
<linux-kselftest@...r.kernel.org>, <shuah@...nel.org>, <tiala@...rosoft.com>
Subject: [RFC PATCH v2 35/35] KVM: selftests: Add MSI injection test for SAVIC
Extend the Secure AVIC (SAVIC) selftest to validate the injection of
Message-Signaled Interrupts (MSIs) from the host.
In SAVIC mode, the delivery of external interrupts, including MSIs,
requires explicit cooperation from the guest. For an interrupt to be
successfully injected by the hardware, the guest must first grant
permission by setting the corresponding vector bit in the 'ALLOWED IRR'
region of its private APIC backing page. If the vector is not explicitly
allowed, the hardware will drop the interrupt.
Add a new test case to Secure AVIC selftest that verifies this permission
model for MSIs. Verify that:
1. If the host injects an MSI while the guest has not yet allowed the
vector, the interrupt is correctly dropped and not received.
2. The guest then updates the ALLOWED_IRR to permit the MSI vector. When
the host injects the same MSI again, the interrupt is successfully
delivered and handled.
This two-stage approach provides robust validation of the SAVIC MSI
delivery mechanism, ensuring both the blocking and permissive paths
work as expected.
Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@....com>
---
tools/testing/selftests/kvm/x86/savic_test.c | 49 ++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86/savic_test.c b/tools/testing/selftests/kvm/x86/savic_test.c
index 3efefc1e69f5..1d9861949a28 100644
--- a/tools/testing/selftests/kvm/x86/savic_test.c
+++ b/tools/testing/selftests/kvm/x86/savic_test.c
@@ -22,6 +22,7 @@
#define IOAPIC_NUM_LEVEL_VECTORS 2
#define RTC_GSI 8
#define RTC_GSI_IRQ 0x85
+#define MSI_VECTOR 0x40
#define FIXED_IPI_VEC 0x31
#define FIXED_LOGICAL_IPI_VEC 0x32
#define BROADCAST_ALL_IPI_VEC 0x33
@@ -40,6 +41,7 @@ enum savic_test_state {
SAVIC_TEST_STATE(SAVIC_IDLE_HALT),
SAVIC_TEST_STATE(SAVIC_IOAPIC),
SAVIC_TEST_STATE(SAVIC_IOAPIC2),
+ SAVIC_TEST_STATE(SAVIC_MSI),
SAVIC_TEST_STATE(SAVIC_IPI),
SAVIC_TEST_STATE(SAVIC_NMI),
SAVIC_TEST_STATE(SAVIC_NMI2),
@@ -57,6 +59,7 @@ struct test_data_page {
uint64_t ioapic_lirq1_count;
uint64_t ioapic_lirq2_count;
uint64_t ioapic_rtc_gsi_irq_count;
+ uint64_t msi_irq_count;
uint64_t fixed_phys_ipi_wake_count;
uint64_t fixed_phys_ipi_hlt_count;
uint64_t fixed_logical_ipi_hlt_count;
@@ -807,6 +810,34 @@ static void guest_nmi_handler(struct ex_regs *regs)
sev_es_nmi_complete();
}
+static void savic_msi_not_allowed(int id)
+{
+ struct test_data_page *data = get_test_data();
+
+ savic_allow_vector(MSI_VECTOR);
+
+ __GUEST_ASSERT(READ_ONCE(data->msi_irq_count) == 0,
+ "Invalid MSI IRQ count: %ld, should be 0",
+ READ_ONCE(data->msi_irq_count));
+}
+
+static void savic_msi_allowed(int id)
+{
+ struct test_data_page *data = get_test_data();
+
+ __GUEST_ASSERT(READ_ONCE(data->msi_irq_count) == 1,
+ "Invalid MSI IRQ count: %ld",
+ READ_ONCE(data->msi_irq_count));
+}
+
+static void msi_intr_handler(struct ex_regs *regs)
+{
+ struct test_data_page *data = get_test_data();
+
+ WRITE_ONCE(data->msi_irq_count, data->msi_irq_count + 1);
+ x2apic_write_reg(APIC_EOI, 0x00);
+}
+
static void ipi_guest_code(int id)
{
struct test_data_page *data;
@@ -901,6 +932,9 @@ static void guest_code(int id)
SAVIC_GUEST_SYNC(SAVIC_IOAPIC, savic_ioapic);
SAVIC_GUEST_SYNC(SAVIC_IOAPIC2, savic_ioapic2);
+ SAVIC_GUEST_SYNC(SAVIC_MSI, savic_msi_not_allowed);
+ SAVIC_GUEST_SYNC(SAVIC_MSI, savic_msi_allowed);
+
SAVIC_GUEST_SYNC(SAVIC_IPI, savic_ipi);
/* Disable host NMI injection in control MSR. */
@@ -953,6 +987,17 @@ static void host_send_ioapic_irq(struct kvm_vm *vm, int id)
kvm_irq_line_status(vm, RTC_GSI, 0);
}
+static void host_send_msi(struct kvm_vm *vm)
+{
+ struct kvm_msi msi = {
+ .address_lo = 0,
+ .address_hi = 0,
+ .data = MSI_VECTOR,
+ };
+
+ __vm_ioctl(vm, KVM_SIGNAL_MSI, &msi);
+}
+
static void host_send_nmi(int id)
{
vcpu_nmi(vcpus[id]);
@@ -968,6 +1013,9 @@ static void host_test_savic(struct kvm_vm *vm, int id, enum savic_test_state tes
case SAVIC_IOAPIC2_START:
host_send_ioapic_irq(vm, id);
break;
+ case SAVIC_MSI_START:
+ host_send_msi(vm);
+ break;
case SAVIC_NMI_START:
case SAVIC_NMI2_START:
case SAVIC_NMI3_START:
@@ -1021,6 +1069,7 @@ static void install_exception_handlers(struct kvm_vm *vm)
vm_install_exception_handler(vm, BROADCAST_NOSELF_IPI_VEC,
guest_broadcast_noself_ipi_handler);
vm_install_exception_handler(vm, NMI_VECTOR, guest_nmi_handler);
+ vm_install_exception_handler(vm, MSI_VECTOR, msi_intr_handler);
}
int main(int argc, char *argv[])
--
2.34.1
Powered by blists - more mailing lists