diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2007-12-14 11:50:24 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2007-12-14 11:50:24 +0000 |
commit | 2d3604815210d7b59b78ca630c19ec75bfa51d49 (patch) | |
tree | 73147b57177dfd536a676d2729dbe66d587455aa | |
parent | 91403dca9a3a558c5f53316a26ba7330fc1531c5 (diff) | |
download | xen-2d3604815210d7b59b78ca630c19ec75bfa51d49.tar.gz xen-2d3604815210d7b59b78ca630c19ec75bfa51d49.tar.bz2 xen-2d3604815210d7b59b78ca630c19ec75bfa51d49.zip |
SVM: Treat the vlapic's tpr as the master copy and sync the vtpr to it
before every vm entry. This fixes HVM save/restore/migrate, as the
vtpr value was only being synced on guest TPR writes before.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
-rw-r--r-- | xen/arch/x86/hvm/hvm.c | 19 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/svm.c | 20 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vlapic.c | 1 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 13 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/hvm.h | 19 |
5 files changed, 29 insertions, 43 deletions
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index b3278cc971..f0575afdab 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1405,6 +1405,25 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx, } } +enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack) +{ + enum hvm_intblk r; + ASSERT(v == current); + + r = hvm_funcs.interrupt_blocked(v, intack); + if ( r != hvm_intblk_none ) + return r; + + if ( intack.source == hvm_intsrc_lapic ) + { + uint32_t tpr = vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xF0; + if ( (tpr >> 4) >= (intack.vector >> 4) ) + return hvm_intblk_tpr; + } + + return r; +} + static long hvm_grant_table_op( unsigned int cmd, XEN_GUEST_HANDLE(void) uop, unsigned int count) { diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index f471474b55..ca935e1458 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -443,10 +443,6 @@ static enum hvm_intblk svm_interrupt_blocked( if ( !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) ) return hvm_intblk_rflags_ie; - if ( (intack.source == hvm_intsrc_lapic) && - ((vmcb->vintr.fields.tpr & 0xf) >= (intack.vector >> 4)) ) - return hvm_intblk_tpr; - return hvm_intblk_none; } @@ -522,13 +518,6 @@ static void svm_flush_guest_tlbs(void) svm_asid_inc_generation(); } -static void svm_update_vtpr(struct vcpu *v, unsigned long value) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - - vmcb->vintr.fields.tpr = value & 0x0f; -} - static void svm_sync_vmcb(struct vcpu *v) { struct arch_svm_struct *arch_svm = &v->arch.hvm_svm; @@ -788,6 +777,10 @@ static void svm_do_resume(struct vcpu *v) svm_asid_init_vcpu(v); } + /* Reflect the vlapic's TPR in the hardware vtpr */ + v->arch.hvm_svm.vmcb->vintr.fields.tpr = + (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4; + hvm_do_resume(v); reset_stack_and_jump(svm_asm_do_resume); } @@ -885,7 +878,6 @@ static struct hvm_function_table svm_function_table = { .update_guest_cr = svm_update_guest_cr, .update_guest_efer = svm_update_guest_efer, .flush_guest_tlbs = svm_flush_guest_tlbs, - .update_vtpr = svm_update_vtpr, .stts = svm_stts, .set_tsc_offset = svm_set_tsc_offset, .inject_exception = svm_inject_exception, @@ -2212,6 +2204,10 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) domain_crash(v->domain); break; } + + /* The exit may have updated the TPR: reflect this in the hardware vtpr */ + vmcb->vintr.fields.tpr = + (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4; } asmlinkage void svm_trace_vmentry(void) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 000cbbfc04..e32ac13b00 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -580,7 +580,6 @@ static void vlapic_write(struct vcpu *v, unsigned long address, { case APIC_TASKPRI: vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff); - hvm_update_vtpr(v, (val >> 4) & 0x0f); break; case APIC_EOI: diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index ff2d8f3cbc..2aeabacdbd 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1011,13 +1011,6 @@ static enum hvm_intblk vmx_interrupt_blocked( if ( !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) ) return hvm_intblk_rflags_ie; - if ( intack.source == hvm_intsrc_lapic ) - { - uint32_t tpr = vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xF0; - if ( (tpr >> 4) >= (intack.vector >> 4) ) - return hvm_intblk_tpr; - } - return hvm_intblk_none; } @@ -1120,11 +1113,6 @@ static void vmx_inject_exception( } } -static void vmx_update_vtpr(struct vcpu *v, unsigned long value) -{ - /* VMX doesn't have a V_TPR field */ -} - static int vmx_event_pending(struct vcpu *v) { ASSERT(v == current); @@ -1148,7 +1136,6 @@ static struct hvm_function_table vmx_function_table = { .update_guest_cr = vmx_update_guest_cr, .update_guest_efer = vmx_update_guest_efer, .flush_guest_tlbs = vmx_flush_guest_tlbs, - .update_vtpr = vmx_update_vtpr, .stts = vmx_stts, .set_tsc_offset = vmx_set_tsc_offset, .inject_exception = vmx_inject_exception, diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 079e3c5da2..6fe80e9f04 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -106,11 +106,6 @@ struct hvm_function_table { void (*flush_guest_tlbs)(void); /* - * Reflect the virtual APIC's value in the guest's V_TPR register - */ - void (*update_vtpr)(struct vcpu *v, unsigned long value); - - /* * Update specifics of the guest state: * 1) TS bit in guest cr0 * 2) TSC offset in guest @@ -161,12 +156,8 @@ u64 hvm_get_guest_tsc(struct vcpu *v); #define hvm_long_mode_enabled(v) (v,0) #endif -static inline enum hvm_intblk -hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack) -{ - ASSERT(v == current); - return hvm_funcs.interrupt_blocked(v, intack); -} +enum hvm_intblk +hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack); static inline int hvm_guest_x86_mode(struct vcpu *v) @@ -184,12 +175,6 @@ hvm_update_host_cr3(struct vcpu *v) hvm_funcs.update_host_cr3(v); } -static inline void -hvm_update_vtpr(struct vcpu *v, unsigned long value) -{ - hvm_funcs.update_vtpr(v, value); -} - static inline void hvm_update_guest_cr(struct vcpu *v, unsigned int cr) { hvm_funcs.update_guest_cr(v, cr); |