[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM][VMX] Enable VMX TPR shadow feature.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 2b99c99f96e67572d33dc1117a6f402ab90d2d3d # Parent c33272c2571c7bab7056d8228490700d1df405f9 [HVM][VMX] Enable VMX TPR shadow feature. x64 Windows uses CR8 to access TPR very frequently. This patch enables TPR shadow and allows mov-from/to-CR8 to access it directly; tests indicates it can boost greatly the performance of x64 Windows 2003. Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx> Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx> Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx> --- xen/arch/x86/hvm/vlapic.c | 19 +++++++++++++------ xen/arch/x86/hvm/vmx/io.c | 25 +++++++++++++++++++++++++ xen/arch/x86/hvm/vmx/vmcs.c | 23 +++++++++++++++-------- xen/arch/x86/hvm/vmx/vmx.c | 5 +++++ xen/include/asm-x86/hvm/vlapic.h | 25 ++++++++++++++++++++++++- 5 files changed, 82 insertions(+), 15 deletions(-) diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Mon Oct 30 09:45:17 2006 +0000 +++ b/xen/arch/x86/hvm/vlapic.c Mon Oct 30 10:42:27 2006 +0000 @@ -217,8 +217,7 @@ static int vlapic_accept_irq(struct vcpu if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) ) break; - if ( vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR) && - trig_mode) + if ( vlapic_test_and_set_irr(vector, vlapic) && trig_mode ) { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "level trig mode repeatedly for vector %d\n", vector); @@ -482,6 +481,11 @@ static void vlapic_read_aligned(struct v *result = 0; switch ( offset ) { + case APIC_PROCPRI: + vlapic_update_ppr(vlapic); + *result = vlapic_get_reg(vlapic, offset); + break; + case APIC_ARBPRI: printk("access local APIC ARBPRI register which is for P6\n"); break; @@ -616,6 +620,7 @@ static void vlapic_write(struct vcpu *v, case APIC_TASKPRI: vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff); vlapic_update_ppr(vlapic); + vlapic->flush_tpr_threshold = 1; break; case APIC_EOI: @@ -814,7 +819,7 @@ void vlapic_timer_fn(void *data) vlapic->timer_last_update = now; - if ( vlapic_test_and_set_vector(timer_vector, vlapic->regs + APIC_IRR) ) + if ( vlapic_test_and_set_irr(timer_vector, vlapic) ) vlapic->intr_pending_count[timer_vector]++; if ( vlapic_lvtt_period(vlapic) ) @@ -891,7 +896,7 @@ int cpu_get_apic_interrupt(struct vcpu * HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "Sending an illegal vector 0x%x.", highest_irr); - vlapic_set_vector(err_vector, vlapic->regs + APIC_IRR); + vlapic_set_irr(err_vector, vlapic); highest_irr = err_vector; } @@ -942,7 +947,7 @@ void vlapic_post_injection(struct vcpu * case APIC_DM_FIXED: case APIC_DM_LOWEST: vlapic_set_vector(vector, vlapic->regs + APIC_ISR); - vlapic_clear_vector(vector, vlapic->regs + APIC_IRR); + vlapic_clear_irr(vector, vlapic); vlapic_update_ppr(vlapic); if ( vector == vlapic_lvt_vector(vlapic, APIC_LVTT) ) @@ -950,7 +955,7 @@ void vlapic_post_injection(struct vcpu * if ( vlapic->intr_pending_count[vector] > 0 ) { vlapic->intr_pending_count[vector]--; - vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR); + vlapic_set_irr(vector, vlapic); } } break; @@ -1000,6 +1005,8 @@ static int vlapic_reset(struct vlapic *v vlapic_set_reg(vlapic, APIC_SPIV, 0xff); vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + + vlapic->flush_tpr_threshold = 0; if ( v->vcpu_id == 0 ) vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP; diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vmx/io.c --- a/xen/arch/x86/hvm/vmx/io.c Mon Oct 30 09:45:17 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/io.c Mon Oct 30 10:42:27 2006 +0000 @@ -68,6 +68,27 @@ static inline int is_interruptibility_st return interruptibility; } +#ifdef __x86_64__ +static void update_tpr_threshold(struct vlapic *vlapic) +{ + int highest_irr, tpr; + + /* Clear the work-to-do flag /then/ do the work. */ + vlapic->flush_tpr_threshold = 0; + mb(); + + highest_irr = vlapic_find_highest_irr(vlapic); + tpr = vlapic_get_reg(vlapic, APIC_TASKPRI) & 0xF0; + + if ( highest_irr == -1 ) + __vmwrite(TPR_THRESHOLD, 0); + else + __vmwrite(TPR_THRESHOLD, + (highest_irr > tpr) ? (tpr >> 4) : (highest_irr >> 4)); +} +#else +#define update_tpr_threshold(v) ((void)0) +#endif asmlinkage void vmx_intr_assist(void) { @@ -75,6 +96,7 @@ asmlinkage void vmx_intr_assist(void) int highest_vector; unsigned long eflags; struct vcpu *v = current; + struct vlapic *vlapic = VLAPIC(v); struct hvm_domain *plat=&v->domain->arch.hvm_domain; struct periodic_time *pt = &plat->pl_time.periodic_tm; struct hvm_virpic *pic= &plat->vpic; @@ -97,6 +119,9 @@ asmlinkage void vmx_intr_assist(void) if ( callback_irq != 0 ) pic_set_xen_irq(pic, callback_irq, local_events_need_delivery()); } + + if ( vlapic && vlapic_enabled(vlapic) && vlapic->flush_tpr_threshold ) + update_tpr_threshold(vlapic); has_ext_irq = cpu_has_pending_irq(v); diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Mon Oct 30 09:45:17 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Mon Oct 30 10:42:27 2006 +0000 @@ -346,8 +346,21 @@ static void vmx_do_launch(struct vcpu *v hvm_stts(v); - if(hvm_apic_support(v->domain)) - vlapic_init(v); + if( hvm_apic_support(v->domain) && (vlapic_init(v) == 0) ) + { +#ifdef __x86_64__ + u32 *cpu_exec_control = &v->arch.hvm_vcpu.u.vmx.exec_control; + u64 vapic_page_addr = + page_to_maddr(v->arch.hvm_vcpu.vlapic->regs_page); + + *cpu_exec_control |= CPU_BASED_TPR_SHADOW; + *cpu_exec_control &= ~CPU_BASED_CR8_STORE_EXITING; + *cpu_exec_control &= ~CPU_BASED_CR8_LOAD_EXITING; + error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, *cpu_exec_control); + error |= __vmwrite(VIRTUAL_APIC_PAGE_ADDR, vapic_page_addr); + error |= __vmwrite(TPR_THRESHOLD, 0); +#endif + } vmx_set_host_env(v); init_timer(&v->arch.hvm_vcpu.hlt_timer, hlt_timer_fn, v, v->processor); @@ -514,12 +527,6 @@ static inline int construct_vmcs_host(vo error |= __vmwrite(HOST_CR4, crn); error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler); -#ifdef __x86_64__ - /* TBD: support cr8 for 64-bit guest */ - __vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0); - __vmwrite(TPR_THRESHOLD, 0); - __vmwrite(SECONDARY_VM_EXEC_CONTROL, 0); -#endif return error; } diff -r c33272c2571c -r 2b99c99f96e6 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Oct 30 09:45:17 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Oct 30 10:42:27 2006 +0000 @@ -2409,6 +2409,11 @@ asmlinkage void vmx_vmexit_handler(struc vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE); break; + case EXIT_REASON_TPR_BELOW_THRESHOLD: + vlapic_update_ppr(VLAPIC(v)); + VLAPIC(v)->flush_tpr_threshold = 1; + break; + default: domain_crash_synchronous(); /* should not happen */ } diff -r c33272c2571c -r 2b99c99f96e6 xen/include/asm-x86/hvm/vlapic.h --- a/xen/include/asm-x86/hvm/vlapic.h Mon Oct 30 09:45:17 2006 +0000 +++ b/xen/include/asm-x86/hvm/vlapic.h Mon Oct 30 10:42:27 2006 +0000 @@ -107,6 +107,7 @@ struct vlapic { uint32_t timer_divide_count; struct timer vlapic_timer; int intr_pending_count[MAX_VECTOR]; + int flush_tpr_threshold; s_time_t timer_last_update; direct_intr_info_t direct_intr; uint32_t err_status; @@ -117,12 +118,30 @@ struct vlapic { void *regs; }; +static inline int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic) +{ + vlapic->flush_tpr_threshold = 1; + return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR); +} + +static inline void vlapic_set_irr(int vector, struct vlapic *vlapic) +{ + vlapic->flush_tpr_threshold = 1; + vlapic_set_vector(vector, vlapic->regs + APIC_IRR); +} + +static inline void vlapic_clear_irr(int vector, struct vlapic *vlapic) +{ + vlapic->flush_tpr_threshold = 1; + vlapic_clear_vector(vector, vlapic->regs + APIC_IRR); +} + static inline int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig) { int ret; - ret = vlapic_test_and_set_vector(vec, vlapic->regs + APIC_IRR); + ret = vlapic_test_and_set_irr(vec, vlapic); if ( trig ) vlapic_set_vector(vec, vlapic->regs + APIC_TMR); @@ -144,12 +163,16 @@ static inline void vlapic_set_reg(struct void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode); +extern int vlapic_find_highest_irr(struct vlapic *vlapic); + int cpu_has_apic_interrupt(struct vcpu* v); int cpu_get_apic_interrupt(struct vcpu* v, int *mode); extern int vlapic_init(struct vcpu *vc); extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value); + +extern uint32_t vlapic_update_ppr(struct vlapic *vlapic); int vlapic_accept_pic_intr(struct vcpu *v); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |