Test cross-vCPU IPI for Secure AVIC guests using xapic_ipi_test.
Add new "SAVIC" apic mode to the test for this.

Signed-off-by: Neeraj Upadhyay <neeraj.upadh...@amd.com>
---
 tools/arch/x86/include/asm/msr-index.h        |  4 +-
 .../selftests/kvm/include/x86/processor.h     |  1 +
 .../selftests/kvm/x86/xapic_ipi_test.c        | 70 ++++++++++++++-----
 3 files changed, 55 insertions(+), 20 deletions(-)

diff --git a/tools/arch/x86/include/asm/msr-index.h 
b/tools/arch/x86/include/asm/msr-index.h
index 3ae84c3b8e6d..93f3ff9991cc 100644
--- a/tools/arch/x86/include/asm/msr-index.h
+++ b/tools/arch/x86/include/asm/msr-index.h
@@ -680,7 +680,9 @@
 #define MSR_AMD64_SNP_VMSA_REG_PROT    BIT_ULL(MSR_AMD64_SNP_VMSA_REG_PROT_BIT)
 #define MSR_AMD64_SNP_SMT_PROT_BIT     17
 #define MSR_AMD64_SNP_SMT_PROT         BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
-#define MSR_AMD64_SNP_RESV_BIT         18
+#define MSR_AMD64_SNP_SECURE_AVIC_BIT  18
+#define MSR_AMD64_SNP_SECURE_AVIC      BIT_ULL(MSR_AMD64_SNP_SECURE_AVIC_BIT)
+#define MSR_AMD64_SNP_RESV_BIT         19
 #define MSR_AMD64_SNP_RESERVED_MASK    GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
 
 #define MSR_AMD64_VIRT_SPEC_CTRL       0xc001011f
diff --git a/tools/testing/selftests/kvm/include/x86/processor.h 
b/tools/testing/selftests/kvm/include/x86/processor.h
index 3f9369644962..f09b18944c47 100644
--- a/tools/testing/selftests/kvm/include/x86/processor.h
+++ b/tools/testing/selftests/kvm/include/x86/processor.h
@@ -201,6 +201,7 @@ struct kvm_x86_cpu_feature {
 #define X86_FEATURE_SEV                        KVM_X86_CPU_FEATURE(0x8000001F, 
0, EAX, 1)
 #define X86_FEATURE_SEV_ES             KVM_X86_CPU_FEATURE(0x8000001F, 0, EAX, 
3)
 #define X86_FEATURE_SNP                        KVM_X86_CPU_FEATURE(0x8000001F, 
0, EAX, 4)
+#define X86_FEATURE_SECURE_AVIC         KVM_X86_CPU_FEATURE(0x8000001F, 0, 
EAX, 26)
 
 /*
  * KVM defined paravirt features.
diff --git a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c 
b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
index 3a54d828dc69..e11c7ded8b8a 100644
--- a/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
+++ b/tools/testing/selftests/kvm/x86/xapic_ipi_test.c
@@ -31,6 +31,7 @@
 #include "test_util.h"
 #include "vmx.h"
 #include "sev.h"
+#include "savic.h"
 
 /* Default running time for the test */
 #define DEFAULT_RUN_SECS 3
@@ -45,30 +46,44 @@
  */
 #define IPI_VECTOR      0xa5
 
+enum apic_mode {
+       XAPIC,
+       X2APIC,
+       SAVIC,
+};
+
 /*
  * Incremented in the IPI handler. Provides evidence to the sender that the IPI
  * arrived at the destination
  */
 static volatile uint64_t *ipis_rcvd;
 
-static bool x2apic;
+static int apic_mode;
 
 static void apic_enable(void)
 {
-       if (x2apic)
-               x2apic_enable();
-       else
+       switch (apic_mode) {
+       case XAPIC:
                xapic_enable();
+               break;
+       case X2APIC:
+               x2apic_enable();
+               break;
+       case SAVIC:
+               x2apic_enable();
+               savic_enable();
+               break;
+       }
 }
 
 static uint32_t apic_read_reg(unsigned int reg)
 {
-       return x2apic ? x2apic_read_reg(reg) : xapic_read_reg(reg);
+       return apic_mode != XAPIC ? x2apic_read_reg(reg) : xapic_read_reg(reg);
 }
 
 static void apic_write_reg(unsigned int reg, uint64_t val)
 {
-       if (x2apic)
+       if (apic_mode != XAPIC)
                x2apic_write_reg(reg, val);
        else
                xapic_write_reg(reg, (uint32_t)val);
@@ -144,7 +159,7 @@ static void halter_guest_code(struct test_data_page *data)
 static void guest_ipi_handler(struct ex_regs *regs)
 {
        (*ipis_rcvd)++;
-       apic_write_reg(APIC_EOI, 77);
+       apic_write_reg(APIC_EOI, 0);
 }
 
 static void sender_guest_code(struct test_data_page *data)
@@ -184,7 +199,7 @@ static void sender_guest_code(struct test_data_page *data)
                 * First IPI can be sent unconditionally because halter vCPU
                 * starts earlier.
                 */
-               if (!x2apic) {
+               if (apic_mode == XAPIC) {
                        apic_write_reg(APIC_ICR2, icr2_val);
                        apic_write_reg(APIC_ICR, icr_val);
                } else {
@@ -385,10 +400,10 @@ void do_migrations(struct test_data_page *data, int 
run_secs, int delay_usecs,
 }
 
 void get_cmdline_args(int argc, char *argv[], int *run_secs,
-                     bool *migrate, int *delay_usecs, bool *x2apic, int 
*vm_type)
+                     bool *migrate, int *delay_usecs, int *apic_mode, int 
*vm_type)
 {
        for (;;) {
-               int opt = getopt(argc, argv, "s:d:v:me:t:");
+               int opt = getopt(argc, argv, "s:d:v:me:t:g");
 
                if (opt == -1)
                        break;
@@ -403,7 +418,7 @@ void get_cmdline_args(int argc, char *argv[], int *run_secs,
                        *delay_usecs = parse_size(optarg);
                        break;
                case 'e':
-                       *x2apic = parse_size(optarg) == 1;
+                       *apic_mode = parse_size(optarg);
                        break;
                case 't':
                        *vm_type = parse_size(optarg);
@@ -431,7 +446,7 @@ void get_cmdline_args(int argc, char *argv[], int *run_secs,
                                    " Default is no migrations.\n"
                                    "-d <delay microseconds> - delay between 
migrate_pages() calls."
                                    " Default is %d microseconds.\n"
-                                   "-e <apic mode> - APIC mode 0 - xapic , 1 - 
x2apic"
+                                   "-e <apic mode> - APIC mode 0 - xapic , 1 - 
x2apic, 3 - Secure AVIC"
                                    " Default is xAPIC.\n"
                                    "-t <vm type>. Default is %d.\n"
                                    "Supported values:\n"
@@ -483,10 +498,17 @@ int main(int argc, char *argv[])
        bool is_sev;
 
        get_cmdline_args(argc, argv, &run_secs, &migrate, &delay_usecs,
-                        &x2apic, &vm_type);
+                        &apic_mode, &vm_type);
+       if (apic_mode == SAVIC) {
+               vm_type = KVM_X86_SNP_VM;
+               TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SNP));
+               TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_IDLE_HLT));
+               TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SECURE_AVIC));
+       }
+
        is_sev = is_sev_vm_type(vm_type);
 
-       if (x2apic)
+       if (apic_mode != XAPIC)
                migrate = 0;
 
        if (run_secs <= 0)
@@ -494,18 +516,28 @@ int main(int argc, char *argv[])
        if (delay_usecs <= 0)
                delay_usecs = DEFAULT_DELAY_USECS;
 
-       if (is_sev)
+       if (apic_mode == SAVIC) {
+               struct kvm_sev_init args = { .vmsa_features = 
BIT_ULL(SVM_FEAT_SECURE_AVIC) |
+                                               
BIT_ULL(SVM_FEAT_ALLOWED_SEV_FEATURES_VALID)
+                                          };
+
+               vm = _vm_sev_create_with_one_vcpu(vm_type, halter_guest_code,
+                               &params[0].vcpu, &args);
+       } else if (is_sev) {
                vm = vm_sev_create_with_one_vcpu(vm_type, halter_guest_code,
                                &params[0].vcpu);
-       else
+       } else {
                vm = vm_create_with_one_vcpu(&params[0].vcpu, 
halter_guest_code);
+       }
 
        vm_install_exception_handler(vm, IPI_VECTOR, guest_ipi_handler);
-       if (is_sev_es_vm(vm))
+       if (apic_mode == SAVIC)
+               vm_install_exception_handler(vm, 29, savic_vc_handler);
+       else if (is_sev_es_vm(vm))
                vm_install_exception_handler(vm, 29, sev_es_vc_handler);
 
-       sync_global_to_guest(vm, x2apic);
-       if (!x2apic)
+       sync_global_to_guest(vm, apic_mode);
+       if (apic_mode == XAPIC)
                virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
 
        params[1].vcpu = vm_vcpu_add(vm, 1, sender_guest_code);
-- 
2.34.1


Reply via email to