# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1172148584 0
# Node ID 3f7e8c763b55b0a805928adcd43d7e2ea321b3e4
# Parent 0a970a431bbcbf91162698580f6cbd7578fe8114
hvm: Do not take shadow-emulation path if we are trying to inject an
event into the HVM guest.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/svm/svm.c | 8 ++++++++
xen/arch/x86/hvm/vmx/vmx.c | 14 ++++++++++++++
xen/arch/x86/mm/shadow/multi.c | 29 +++++++++++++++++++++++------
xen/include/asm-x86/hvm/hvm.h | 7 +++++++
4 files changed, 52 insertions(+), 6 deletions(-)
diff -r 0a970a431bbc -r 3f7e8c763b55 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Thu Feb 22 12:21:29 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c Thu Feb 22 12:49:44 2007 +0000
@@ -982,6 +982,12 @@ static void svm_hvm_inject_exception(
v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2;
}
+static int svm_injection_pending(struct vcpu *v)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ return (vmcb->vintr.fields.irq || vmcb->exitintinfo.fields.v);
+}
+
int start_svm(void)
{
u32 eax, ecx, edx;
@@ -1057,6 +1063,8 @@ int start_svm(void)
hvm_funcs.init_ap_context = svm_init_ap_context;
hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
+
+ hvm_funcs.injection_pending = svm_injection_pending;
hvm_enable();
diff -r 0a970a431bbc -r 3f7e8c763b55 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 22 12:21:29 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 22 12:49:44 2007 +0000
@@ -990,6 +990,18 @@ static void vmx_update_vtpr(struct vcpu
/* VMX doesn't have a V_TPR field */
}
+static int vmx_injection_pending(struct vcpu *v)
+{
+ unsigned int idtv_info_field;
+
+ ASSERT(v == current);
+
+ idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD);
+
+ return (v->arch.hvm_vmx.vector_injected ||
+ (idtv_info_field & INTR_INFO_VALID_MASK));
+}
+
/* Setup HVM interfaces */
static void vmx_setup_hvm_funcs(void)
{
@@ -1025,6 +1037,8 @@ static void vmx_setup_hvm_funcs(void)
hvm_funcs.init_ap_context = vmx_init_ap_context;
hvm_funcs.init_hypercall_page = vmx_init_hypercall_page;
+
+ hvm_funcs.injection_pending = vmx_injection_pending;
}
int start_vmx(void)
diff -r 0a970a431bbc -r 3f7e8c763b55 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Thu Feb 22 12:21:29 2007 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c Thu Feb 22 12:49:44 2007 +0000
@@ -2901,18 +2901,35 @@ static int sh_page_fault(struct vcpu *v,
goto not_a_shadow_fault;
if ( is_hvm_domain(d) )
+ {
+ /*
+ * If we are in the middle of injecting an exception or interrupt then
+ * we should not emulate: it is not the instruction at %eip that caused
+ * the fault. Furthermore it is almost certainly the case the handler
+ * stack is currently considered to be a page table, so we should
+ * unshadow the faulting page before exiting.
+ */
+ if ( hvm_injection_pending(v) )
+ {
+ gdprintk(XENLOG_DEBUG, "write to pagetable during event "
+ "injection: cr2=%#lx, mfn=%#lx\n",
+ va, mfn_x(gmfn));
+ sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
+ goto done;
+ }
+
hvm_store_cpu_guest_regs(v, regs, NULL);
+ }
+
SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n",
(unsigned long)regs->eip, (unsigned long)regs->esp);
- /* Check whether this looks like a stack operation. */
+ /*
+ * Check whether this looks like a stack operation.
+ * If so, forcibly unshadow and return.
+ */
if ( (va & PAGE_MASK) == (regs->esp & PAGE_MASK) )
{
- /* Forcibly unshadow and return. It's important to do this before
- * we emulate: if the faulting stack operation was the guest handling
- * an interrupt, then
- * (a) the instruction at %eip is irrelevant; and
- * (b) we might inject some other fault and mask the real one */
gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: "
"%%esp=%#lx, cr2=%#lx, mfn=%#lx\n",
(unsigned long)regs->esp, va, mfn_x(gmfn));
diff -r 0a970a431bbc -r 3f7e8c763b55 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h Thu Feb 22 12:21:29 2007 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h Thu Feb 22 12:49:44 2007 +0000
@@ -134,6 +134,8 @@ struct hvm_function_table {
int vcpuid, int trampoline_vector);
void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
+
+ int (*injection_pending)(struct vcpu *v);
};
extern struct hvm_function_table hvm_funcs;
@@ -262,4 +264,9 @@ hvm_inject_exception(unsigned int trapnr
int hvm_bringup_ap(int vcpuid, int trampoline_vector);
+static inline int hvm_injection_pending(struct vcpu *v)
+{
+ return hvm_funcs.injection_pending(v);
+}
+
#endif /* __ASM_X86_HVM_HVM_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|