]> xenbits.xensource.com Git - people/dwmw2/xen.git/commitdiff
x86/vm_event: block interrupt injection for sync vm_events
authorRazvan Cojocaru <rcojocaru@bitdefender.com>
Mon, 21 Jan 2019 11:13:22 +0000 (12:13 +0100)
committerJan Beulich <jbeulich@suse.com>
Mon, 21 Jan 2019 11:13:22 +0000 (12:13 +0100)
Block interrupts (in vmx_intr_assist()) for the duration of
processing a sync vm_event (similarly to the strategy
currently used for single-stepping). Otherwise, attempting
to emulate an instruction when requested by a vm_event
reply may legitimately need to call e.g.
hvm_inject_page_fault(), which then overwrites the active
interrupt in the VMCS.

The sync vm_event handling path on x86/VMX is (roughly):
monitor_traps() -> process vm_event -> vmx_intr_assist()
(possibly writing VM_ENTRY_INTR_INFO) ->
hvm_vm_event_do_resume() -> hvm_emulate_one_vm_event()
(possibly overwriting the VM_ENTRY_INTR_INFO value).

This patch may also be helpful for the future removal
of may_defer in hvm_set_cr{0,3,4} and hvm_set_msr().

Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Tamas K Lengyel <tamas@tklengyel.com>
Release-acked-by: Juergen Gross <jgross@suse.com>
xen/arch/x86/hvm/svm/intr.c
xen/arch/x86/hvm/vm_event.c
xen/arch/x86/hvm/vmx/intr.c
xen/arch/x86/vm_event.c
xen/common/monitor.c
xen/include/asm-arm/vm_event.h
xen/include/asm-x86/vm_event.h

index 79673535d1f4730715bce44d8e553f14f10ca8bc..ff755165cd6c7be0dab818a6c7c1adc02e9c9339 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/hvm/svm/svm.h>
 #include <asm/hvm/svm/intr.h>
 #include <asm/hvm/nestedhvm.h> /* for nestedhvm_vcpu_in_guestmode */
+#include <asm/vm_event.h>
 #include <xen/event.h>
 #include <xen/kernel.h>
 #include <public/hvm/ioreq.h>
@@ -137,6 +138,10 @@ void svm_intr_assist(void)
     struct hvm_intack intack;
     enum hvm_intblk intblk;
 
+    /* Block event injection while handling a sync vm_event. */
+    if ( unlikely(v->arch.vm_event) && v->arch.vm_event->sync_event )
+        return;
+
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
 
index 0df8ab40e663edb6e8f530055ac459075fa47492..121de230719e21fd1f232a751424ee69a32063b8 100644 (file)
@@ -124,6 +124,8 @@ void hvm_vm_event_do_resume(struct vcpu *v)
 
         w->do_write.msr = 0;
     }
+
+    vm_event_sync_event(v, false);
 }
 
 /*
index 5e8cbd4b4a7f13d0f3eea41121363a59d58fd752..0d097cf1f290aa65ad4c471f224b63c25d4814ed 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/hvm/nestedhvm.h>
 #include <public/hvm/ioreq.h>
 #include <asm/hvm/trace.h>
+#include <asm/vm_event.h>
 
 /*
  * A few notes on virtual NMI and INTR delivery, and interactions with
@@ -239,6 +240,10 @@ void vmx_intr_assist(void)
         return;
     }
 
+    /* Block event injection while handling a sync vm_event. */
+    if ( unlikely(v->arch.vm_event) && v->arch.vm_event->sync_event )
+        return;
+
     /* Crank the handle on interrupt state. */
     pt_vector = pt_update_irq(v);
 
index 713e684abe473f2dd4601efd7977f46016c1eeb0..51c3493b1d765be86847712939a494f9b6306ed0 100644 (file)
@@ -122,6 +122,11 @@ void vm_event_monitor_next_interrupt(struct vcpu *v)
     v->arch.monitor.next_interrupt_enabled = true;
 }
 
+void vm_event_sync_event(struct vcpu *v, bool value)
+{
+    v->arch.vm_event->sync_event = value;
+}
+
 #ifdef CONFIG_HVM
 static void vm_event_pack_segment_register(enum x86_segment segment,
                                            struct vm_event_regs_x86 *reg)
index c6066830e3ec45d201f324ca71f83a43522d6b3b..cb5f37fdb245d97c00270612ee66afb99175ba44 100644 (file)
@@ -113,6 +113,7 @@ int monitor_traps(struct vcpu *v, bool sync, vm_event_request_t *req)
     if ( sync )
     {
         req->flags |= VM_EVENT_FLAG_VCPU_PAUSED;
+        vm_event_sync_event(v, true);
         vm_event_vcpu_pause(v);
         rc = 1;
     }
index 66f2474fe135f7beef8e35023d74e8320025ea41..14d1d341cc799bc12244a3017b4f525cc8d8da90 100644 (file)
@@ -52,4 +52,10 @@ void vm_event_emulate_check(struct vcpu *v, vm_event_response_t *rsp)
     /* Not supported on ARM. */
 }
 
+static inline
+void vm_event_sync_event(struct vcpu *v, bool value)
+{
+    /* Not supported on ARM. */
+}
+
 #endif /* __ASM_ARM_VM_EVENT_H__ */
index 39e73c83ca270f1210f9e36e94396e8979839c86..23e655710ba2945970e1e710625f11c1110e94fa 100644 (file)
@@ -34,6 +34,8 @@ struct arch_vm_event {
     struct monitor_write_data write_data;
     struct vm_event_regs_x86 gprs;
     bool set_gprs;
+    /* A sync vm_event has been sent and we're not done handling it. */
+    bool sync_event;
 };
 
 int vm_event_init_domain(struct domain *d);
@@ -47,4 +49,6 @@ void vm_event_register_write_resume(struct vcpu *v, vm_event_response_t *rsp);
 
 void vm_event_emulate_check(struct vcpu *v, vm_event_response_t *rsp);
 
+void vm_event_sync_event(struct vcpu *v, bool value);
+
 #endif /* __ASM_X86_VM_EVENT_H__ */