On 17/12/2016 09:16, Paolo Bonzini wrote: > These are designed to test APICv and optimizations of KVM_REQ_EVENT. Results: apicv=1 apicv=0 self_ipi_sti_nop 2404 5230 * self_ipi_sti_hlt 3438 5848 self_ipi_tpr 2401 4852 self_ipi_tpr_sti_nop 2422 6155 ** self_ipi_tpr_sti_hlt 3564 7177 x2apic_self_ipi_sti_nop 967 4511 * x2apic_self_ipi_sti_hlt 2099 5537 x2apic_self_ipi_tpr 1057 4780 x2apic_self_ipi_tpr_sti_nop 1077 6100 ** x2apic_self_ipi_tpr_sti_hlt 2213 7127 With enable_apicv=0, the lines marked (**) are slower than those marked (*), and IIUC that's what the patch is designed to fix. I haven't yet tried applying it and running the test, though. Paolo > 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--) > -- 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