[PATCH kvm-unit-tests] vmexit: add self-ipi speed tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



These are designed to test APICv and optimizations of KVM_REQ_EVENT.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 lib/x86/apic.c |  21 +++++++++++
 lib/x86/apic.h |   2 +
 x86/vmexit.c   | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+)

diff --git a/lib/x86/apic.c b/lib/x86/apic.c
index a9ed28d..aec968e 100644
--- a/lib/x86/apic.c
+++ b/lib/x86/apic.c
@@ -113,6 +113,27 @@ uint32_t apic_id(void)
     return apic_ops->id();
 }
 
+uint8_t apic_get_tpr(void)
+{
+	unsigned long tpr;
+
+#ifdef __x86_64__
+	asm volatile ("mov %%cr8, %0" : "=r"(tpr));
+#else
+	tpr = apic_read(APIC_TPR) >> 4;
+#endif	
+	return tpr;
+}
+
+void apic_set_tpr(uint8_t tpr)
+{
+#ifdef __x86_64__
+	asm volatile ("mov %0, %%cr8" : : "r"((unsigned long) tpr));
+#else
+	apic_write(APIC_TPR, tpr << 4);
+#endif	
+}
+
 int enable_x2apic(void)
 {
     unsigned a, b, c, d;
diff --git a/lib/x86/apic.h b/lib/x86/apic.h
index dbd6c9b..192268c 100644
--- a/lib/x86/apic.h
+++ b/lib/x86/apic.h
@@ -21,6 +21,8 @@ typedef struct {
 void mask_pic_interrupts(void);
 
 void eoi(void);
+uint8_t apic_get_tpr(void);
+void apic_set_tpr(uint8_t tpr);
 
 void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e);
 void ioapic_write_reg(unsigned reg, uint32_t value);
diff --git a/x86/vmexit.c b/x86/vmexit.c
index 2d99d5f..cf53130 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -6,6 +6,10 @@
 #include "x86/vm.h"
 #include "x86/desc.h"
 #include "x86/acpi.h"
+#include "x86/apic.h"
+#include "x86/isr.h"
+
+#define IPI_TEST_VECTOR	0xb0
 
 struct test {
 	void (*func)(void);
@@ -61,6 +65,107 @@ static void nop(void *junk)
 {
 }
 
+static void self_ipi_isr(isr_regs_t *regs)
+{
+	eoi();
+}
+
+static void x2apic_self_ipi(int vec)
+{
+	wrmsr(0x83f, vec);
+}
+
+static void apic_self_ipi(int vec)
+{
+        apic_icr_write(APIC_INT_ASSERT | APIC_DEST_SELF | APIC_DEST_PHYSICAL |
+		       APIC_DM_FIXED | IPI_TEST_VECTOR, vec);
+}
+
+static void self_ipi_sti_nop(void)
+{
+	irq_disable();
+	apic_self_ipi(IPI_TEST_VECTOR);
+	asm volatile("sti; nop");
+}
+
+static void self_ipi_sti_hlt(void)
+{
+	irq_disable();
+	apic_self_ipi(IPI_TEST_VECTOR);
+	asm volatile("sti; hlt");
+}
+
+static void self_ipi_tpr(void)
+{
+	apic_set_tpr(0x0f);
+	apic_self_ipi(IPI_TEST_VECTOR);
+	apic_set_tpr(0x00);
+	asm volatile("nop");
+}
+
+static void self_ipi_tpr_sti_nop(void)
+{
+	irq_disable();
+	apic_set_tpr(0x0f);
+	apic_self_ipi(IPI_TEST_VECTOR);
+	apic_set_tpr(0x00);
+	asm volatile("sti; nop");
+}
+
+static void self_ipi_tpr_sti_hlt(void)
+{
+	irq_disable();
+	apic_set_tpr(0x0f);
+	apic_self_ipi(IPI_TEST_VECTOR);
+	apic_set_tpr(0x00);
+	asm volatile("sti; hlt");
+}
+
+static int is_x2apic(void)
+{
+    return rdmsr(MSR_IA32_APICBASE) & APIC_EXTD;
+}
+
+static void x2apic_self_ipi_sti_nop(void)
+{
+	irq_disable();
+	x2apic_self_ipi(IPI_TEST_VECTOR);
+	asm volatile("sti; nop");
+}
+
+static void x2apic_self_ipi_sti_hlt(void)
+{
+	irq_disable();
+	x2apic_self_ipi(IPI_TEST_VECTOR);
+	asm volatile("sti; hlt");
+}
+
+static void x2apic_self_ipi_tpr(void)
+{
+	apic_set_tpr(0x0f);
+	x2apic_self_ipi(IPI_TEST_VECTOR);
+	apic_set_tpr(0x00);
+	asm volatile("nop");
+}
+
+static void x2apic_self_ipi_tpr_sti_nop(void)
+{
+	irq_disable();
+	apic_set_tpr(0x0f);
+	x2apic_self_ipi(IPI_TEST_VECTOR);
+	apic_set_tpr(0x00);
+	asm volatile("sti; nop");
+}
+
+static void x2apic_self_ipi_tpr_sti_hlt(void)
+{
+	irq_disable();
+	apic_set_tpr(0x0f);
+	x2apic_self_ipi(IPI_TEST_VECTOR);
+	apic_set_tpr(0x00);
+	asm volatile("sti; hlt");
+}
+
 static void ipi(void)
 {
 	on_cpu(1, nop, 0);
@@ -281,6 +386,16 @@ static struct test tests[] = {
 	{ inl_nop_kernel, "inl_from_kernel", .parallel = 1 },
 	{ outl_elcr_kernel, "outl_to_kernel", .parallel = 1 },
 	{ mov_dr, "mov_dr", .parallel = 1 },
+	{ self_ipi_sti_nop, "self_ipi_sti_nop", .parallel = 1, },
+	{ self_ipi_sti_hlt, "self_ipi_sti_hlt", .parallel = 1, },
+	{ self_ipi_tpr, "self_ipi_tpr", .parallel = 1, },
+	{ self_ipi_tpr_sti_nop, "self_ipi_tpr_sti_nop", .parallel = 1, },
+	{ self_ipi_tpr_sti_hlt, "self_ipi_tpr_sti_hlt", .parallel = 1, },
+	{ x2apic_self_ipi_sti_nop, "x2apic_self_ipi_sti_nop", is_x2apic, .parallel = 1, },
+	{ x2apic_self_ipi_sti_hlt, "x2apic_self_ipi_sti_hlt", is_x2apic, .parallel = 1, },
+	{ x2apic_self_ipi_tpr, "x2apic_self_ipi_tpr", is_x2apic, .parallel = 1, },
+	{ x2apic_self_ipi_tpr_sti_nop, "x2apic_self_ipi_tpr_sti_nop", is_x2apic, .parallel = 1, },
+	{ x2apic_self_ipi_tpr_sti_hlt, "x2apic_self_ipi_tpr_sti_hlt", is_x2apic, .parallel = 1, },
 	{ ipi, "ipi", is_smp, .parallel = 0, },
 	{ ipi_halt, "ipi+halt", is_smp, .parallel = 0, },
 	{ ple_round_robin, "ple-round-robin", .parallel = 1 },
@@ -376,6 +491,7 @@ int main(int ac, char **av)
 
 	smp_init();
 	setup_vm();
+	handle_irq(IPI_TEST_VECTOR, self_ipi_isr);
 	nr_cpus = cpu_count();
 
 	for (i = cpu_count(); i > 0; i--)
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux