aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-14 11:50:24 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-14 11:50:24 +0000
commit2d3604815210d7b59b78ca630c19ec75bfa51d49 (patch)
tree73147b57177dfd536a676d2729dbe66d587455aa
parent91403dca9a3a558c5f53316a26ba7330fc1531c5 (diff)
downloadxen-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.c19
-rw-r--r--xen/arch/x86/hvm/svm/svm.c20
-rw-r--r--xen/arch/x86/hvm/vlapic.c1
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c13
-rw-r--r--xen/include/asm-x86/hvm/hvm.h19
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);