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);
