# HG changeset patch # User kaf24@localhost.localdomain # Date Fri Oct 27 18:00:03 2006 +0100 # Node ID a1939d76c0e8e27bdac5233df7bd78c004ea8deb # parent: 66fe61db9e69e03e12d0c4086683bebfb4a67780 [HVM] Fix SMP timer issues: * Sync AP TSCs with BP at startup * Only halt BP TSC when descheduled * Correctly handle IPIs on timer vector Signed-off-by: Xiaowei Yang Index: xen-3.0.3-testing/xen/arch/x86/hvm/hvm.c =================================================================== --- xen-3.0.3-testing.orig/xen/arch/x86/hvm/hvm.c +++ xen-3.0.3-testing/xen/arch/x86/hvm/hvm.c @@ -226,7 +226,7 @@ void hvm_do_resume(struct vcpu *v) hvm_stts(v); /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( pt->enabled && pt->first_injected ) { + if ( pt->enabled && v->vcpu_id == pt->bind_vcpu && pt->first_injected ) { if ( v->arch.hvm_vcpu.guest_time ) { hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time); v->arch.hvm_vcpu.guest_time = 0; Index: xen-3.0.3-testing/xen/arch/x86/hvm/intercept.c =================================================================== --- xen-3.0.3-testing.orig/xen/arch/x86/hvm/intercept.c +++ xen-3.0.3-testing/xen/arch/x86/hvm/intercept.c @@ -339,6 +339,7 @@ struct periodic_time * create_periodic_t stop_timer (&pt->timer); pt->enabled = 0; } + pt->bind_vcpu = 0; /* timer interrupt delivered to BSP by default */ pt->pending_intr_nr = 0; pt->first_injected = 0; if (period < 900000) { /* < 0.9 ms */ Index: xen-3.0.3-testing/xen/arch/x86/hvm/io.c =================================================================== --- xen-3.0.3-testing.orig/xen/arch/x86/hvm/io.c +++ xen-3.0.3-testing/xen/arch/x86/hvm/io.c @@ -680,7 +680,7 @@ void hvm_interrupt_post(struct vcpu *v, struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - if ( is_pit_irq(v, vector, type) ) { + if ( is_pit_irq(v, vector, type) && (v->vcpu_id == pt->bind_vcpu) ) { if ( !pt->first_injected ) { pt->pending_intr_nr = 0; pt->last_plt_gtime = hvm_get_guest_time(v); Index: xen-3.0.3-testing/xen/arch/x86/hvm/svm/svm.c =================================================================== --- xen-3.0.3-testing.orig/xen/arch/x86/hvm/svm/svm.c +++ xen-3.0.3-testing/xen/arch/x86/hvm/svm/svm.c @@ -763,7 +763,8 @@ static void svm_freeze_time(struct vcpu { struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm; - if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) { + if ( pt->enabled && pt->first_injected && v->vcpu_id == pt->bind_vcpu + && !v->arch.hvm_vcpu.guest_time ) { v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); stop_timer(&(pt->timer)); } Index: xen-3.0.3-testing/xen/arch/x86/hvm/vmx/vmcs.c =================================================================== --- xen-3.0.3-testing.orig/xen/arch/x86/hvm/vmx/vmcs.c +++ xen-3.0.3-testing/xen/arch/x86/hvm/vmx/vmcs.c @@ -314,14 +314,20 @@ static void vmx_set_host_env(struct vcpu error |= __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom()); } +/* Update CR3, CR0, CR4, GDT, LDT, TR */ static void vmx_do_launch(struct vcpu *v) { -/* Update CR3, CR0, CR4, GDT, LDT, TR */ unsigned int error = 0; unsigned long cr0, cr4; - if (v->vcpu_id == 0) + if ( v->vcpu_id == 0 ) hvm_setup_platform(v->domain); + else { + /* Sync AP's TSC with BSP's */ + v->arch.hvm_vcpu.cache_tsc_offset = + v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset; + hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); + } __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : ); @@ -360,9 +366,6 @@ static void vmx_do_launch(struct vcpu *v __vmwrite(HOST_CR3, v->arch.cr3); v->arch.schedule_tail = arch_vmx_do_resume; - - /* init guest tsc to start from 0 */ - hvm_set_guest_time(v, 0); } /* Index: xen-3.0.3-testing/xen/arch/x86/hvm/vmx/vmx.c =================================================================== --- xen-3.0.3-testing.orig/xen/arch/x86/hvm/vmx/vmx.c +++ xen-3.0.3-testing/xen/arch/x86/hvm/vmx/vmx.c @@ -456,7 +456,8 @@ static void vmx_freeze_time(struct vcpu { struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm; - if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) { + if ( pt->enabled && pt->first_injected && v->vcpu_id == pt->bind_vcpu + && !v->arch.hvm_vcpu.guest_time ) { v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); stop_timer(&(pt->timer)); } @@ -1927,6 +1928,13 @@ static inline void vmx_do_msr_write(stru switch (regs->ecx) { case MSR_IA32_TIME_STAMP_COUNTER: + { + struct periodic_time *pt = + &(v->domain->arch.hvm_domain.pl_time.periodic_tm); + if ( pt->enabled && pt->first_injected + && v->vcpu_id == pt->bind_vcpu ) + pt->first_injected = 0; + } hvm_set_guest_time(v, msr_content); break; case MSR_IA32_SYSENTER_CS: Index: xen-3.0.3-testing/xen/include/asm-x86/hvm/vpit.h =================================================================== --- xen-3.0.3-testing.orig/xen/include/asm-x86/hvm/vpit.h +++ xen-3.0.3-testing/xen/include/asm-x86/hvm/vpit.h @@ -58,6 +58,7 @@ struct periodic_time { char one_shot; /* one shot time */ char irq; char first_injected; /* flag to prevent shadow window */ + u32 bind_vcpu; /* vcpu timer interrupt delivers to */ u32 pending_intr_nr; /* the couner for pending timer interrupts */ u32 period; /* frequency in ns */ u64 period_cycles; /* frequency in cpu cycles */