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