mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/mem_sharing: block interrupt injection for forks
When running VM forks without device models (QEMU), it may be undesirable for Xen to inject interrupts. When creating such forks from Windows VMs we have observed the kernel trying to process interrupts immediately after the fork is executed. However without QEMU running such interrupt handling may not be possible because it may attempt to interact with devices that are not emulated by a backend. In the best case scenario such interrupt handling would only present a detour in the VM forks' execution flow, but in the worst case as we actually observed can completely stall it. By disabling interrupt injection a fuzzer can exercise the target code without interference. For other use-cases this option probably doesn't make sense, that's why this is not enabled by default. Forks & memory sharing are only available on Intel CPUs so this only applies to vmx. Note that this is part of the experimental VM forking feature that's completely disabled by default and can only be enabled by using XEN_CONFIG_EXPERT during compile time. Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Wei Liu <wl@xen.org> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Release-acked-by: Paul Durrant <paul@xen.org>
This commit is contained in:
1 parent
1251402caf
commit
3371ced37c
4 files changed
+15
-2
No files matched your search
@@ -256,6 +256,12 @@ void vmx_intr_assist(void)
|
||||
if ( unlikely(v->arch.vm_event) && v->arch.vm_event->sync_event )
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_MEM_SHARING
|
||||
/* Block event injection for VM fork if requested */
|
||||
if ( unlikely(v->domain->arch.hvm.mem_sharing.block_interrupts) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Crank the handle on interrupt state. */
|
||||
pt_vector = pt_update_irq(v);
|
||||
|
||||
|
||||
@@ -2106,7 +2106,8 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
|
||||
rc = -EINVAL;
|
||||
if ( mso.u.fork.pad )
|
||||
goto out;
|
||||
if ( mso.u.fork.flags & ~XENMEM_FORK_WITH_IOMMU_ALLOWED )
|
||||
if ( mso.u.fork.flags &
|
||||
~(XENMEM_FORK_WITH_IOMMU_ALLOWED | XENMEM_FORK_BLOCK_INTERRUPTS) )
|
||||
goto out;
|
||||
|
||||
rc = rcu_lock_live_remote_domain_by_id(mso.u.fork.parent_domain,
|
||||
@@ -2134,6 +2135,9 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
|
||||
rc = hypercall_create_continuation(__HYPERVISOR_memory_op,
|
||||
"lh", XENMEM_sharing_op,
|
||||
arg);
|
||||
else if ( !rc && (mso.u.fork.flags & XENMEM_FORK_BLOCK_INTERRUPTS) )
|
||||
d->arch.hvm.mem_sharing.block_interrupts = true;
|
||||
|
||||
rcu_unlock_domain(pd);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ struct hvm_ioreq_server {
|
||||
#ifdef CONFIG_MEM_SHARING
|
||||
struct mem_sharing_domain
|
||||
{
|
||||
bool enabled;
|
||||
bool enabled, block_interrupts;
|
||||
|
||||
/*
|
||||
* When releasing shared gfn's in a preemptible manner, recall where
|
||||
|
||||
@@ -536,7 +536,10 @@ struct xen_mem_sharing_op {
|
||||
} debug;
|
||||
struct mem_sharing_op_fork { /* OP_FORK */
|
||||
domid_t parent_domain; /* IN: parent's domain id */
|
||||
/* Only makes sense for short-lived forks */
|
||||
#define XENMEM_FORK_WITH_IOMMU_ALLOWED (1u << 0)
|
||||
/* Only makes sense for short-lived forks */
|
||||
#define XENMEM_FORK_BLOCK_INTERRUPTS (1u << 1)
|
||||
uint16_t flags; /* IN: optional settings */
|
||||
uint32_t pad; /* Must be set to 0 */
|
||||
} fork;
|
||||
|
||||