x86/hvm: wait for at least one ioreq server to be enabled
authorPaul Durrant <paul.durrant@citrix.com>
Tue, 10 Feb 2015 12:28:40 +0000 (13:28 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 10 Feb 2015 12:28:40 +0000 (13:28 +0100)
In the case where a stub domain is providing emulation for an HVM
guest, there is no interlock in the toolstack to make sure that
the stub domain is up and running before the guest is unpaused.

Prior to the introduction of ioreq servers this was not a problem,
since there was only ever one emulator so ioreqs were simply
created anyway and the vcpu remained blocked until the stub domain
started and picked up the ioreq.

Since ioreq servers allow for multiple emulators for a single guest
it's not possible to know a priori which emulator will handle a
particular ioreq, so emulators must attach to a guest before the
guest runs.

This patch works around the lack of interlock in the toolstack for
stub domains by keeping the domain paused until at least one ioreq
server is created and enabled, which in practice means the stub
domain is indeed up and running.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
xen/arch/x86/hvm/hvm.c
xen/include/asm-x86/hvm/domain.h

index b03ee4e9d978ca25cf3d1e44073753fa1b27eb64..952f9653d8342800b1e90b0c1a6f597e14bd82c4 100644 (file)
@@ -886,6 +886,13 @@ static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s,
 
   done:
     spin_unlock(&s->lock);
+
+    /* This check is protected by the domain ioreq server lock. */
+    if ( d->arch.hvm_domain.ioreq_server.waiting )
+    {
+        d->arch.hvm_domain.ioreq_server.waiting = 0;
+        domain_unpause(d);
+    }
 }
 
 static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s,
@@ -1437,6 +1444,20 @@ int hvm_domain_initialise(struct domain *d)
 
     spin_lock_init(&d->arch.hvm_domain.ioreq_server.lock);
     INIT_LIST_HEAD(&d->arch.hvm_domain.ioreq_server.list);
+    
+    /*
+     * In the case where a stub domain is providing emulation for
+     * the guest, there is no interlock in the toolstack to prevent
+     * the guest from running before the stub domain is ready.
+     * Hence the domain must remain paused until at least one ioreq
+     * server is created and enabled.
+     */
+    if ( !is_pvh_domain(d) )
+    {
+        domain_pause(d);
+        d->arch.hvm_domain.ioreq_server.waiting = 1;
+    }
+
     spin_lock_init(&d->arch.hvm_domain.irq_lock);
     spin_lock_init(&d->arch.hvm_domain.uc_lock);
 
index 2757c7fedd4fa8a0c8f7b0d7b0c5f0cc2bc6cbd1..0702bf5aa8db33cc37a045078c4b333551bbd58d 100644 (file)
@@ -83,6 +83,7 @@ struct hvm_domain {
     struct {
         spinlock_t       lock;
         ioservid_t       id;
+        bool_t           waiting;
         struct list_head list;
     } ioreq_server;
     struct hvm_ioreq_server *default_ioreq_server;