hvmloader: clear the xenbus event-channel when we're done with it.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 20 Jul 2010 12:42:17 +0000 (13:42 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 20 Jul 2010 12:42:17 +0000 (13:42 +0100)
Otherwise a later xenbus client that naively waits for the rising edge
could get stuck.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
tools/firmware/hvmloader/util.c
tools/firmware/hvmloader/util.h
tools/firmware/hvmloader/xenbus.c

index 1467d5ca7edee3a8720ab47c6610ebc2d114743e..fe561a4f999bb78fa78bd6983f38bd5a07d06ac5 100644 (file)
@@ -587,10 +587,28 @@ struct hvm_info_table *get_hvm_info_table(void)
     return table;
 }
 
-uint16_t get_cpu_mhz(void)
+struct shared_info *get_shared_info(void) 
 {
+    static struct shared_info *shared_info = NULL;
     struct xen_add_to_physmap xatp;
-    struct shared_info *shared_info = (struct shared_info *)0xfffff000;
+
+    if ( shared_info != NULL )
+        return shared_info;
+
+    xatp.domid = DOMID_SELF;
+    xatp.space = XENMAPSPACE_shared_info;
+    xatp.idx   = 0;
+    xatp.gpfn  = 0xfffffu;
+    shared_info = (struct shared_info *)(xatp.gpfn << PAGE_SHIFT);
+    if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
+        BUG();
+
+    return shared_info;
+}
+
+uint16_t get_cpu_mhz(void)
+{
+    struct shared_info *shared_info = get_shared_info();
     struct vcpu_time_info *info = &shared_info->vcpu_info[0].time;
     uint64_t cpu_khz;
     uint32_t tsc_to_nsec_mul, version;
@@ -600,14 +618,6 @@ uint16_t get_cpu_mhz(void)
     if ( cpu_mhz != 0 )
         return cpu_mhz;
 
-    /* Map shared-info page. */
-    xatp.domid = DOMID_SELF;
-    xatp.space = XENMAPSPACE_shared_info;
-    xatp.idx   = 0;
-    xatp.gpfn  = (unsigned long)shared_info >> 12;
-    if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
-        BUG();
-
     /* Get a consistent snapshot of scale factor (multiplier and shift). */
     do {
         version = info->version;
index b5a84fd17745c1198e0c0f3269e41a849ee06f30..3c661360b29c627ab0bece329dfd7f46c52b5e3c 100644 (file)
@@ -69,6 +69,9 @@ void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val);
 #define pci_writew(devfn, reg, val) (pci_write(devfn, reg, 2, (uint16_t)val))
 #define pci_writel(devfn, reg, val) (pci_write(devfn, reg, 4, (uint32_t)val))
 
+/* Get a pointer to the shared-info page */
+struct shared_info *get_shared_info(void);
+
 /* Get CPU speed in MHz. */
 uint16_t get_cpu_mhz(void);
 
index aad8a441bb8a4f4de740478a88597257d9bc7af3..e980e47bef92c07ad680992f77e7e329c4aff56a 100644 (file)
@@ -53,14 +53,20 @@ void xenbus_setup(void)
            (unsigned long) rings, (unsigned long) event);
 }
 
-/* Reset the xenbus connection so the next kernel can start again. 
- * We zero out the whole ring -- the backend can handle this, and it's 
- * not going to surprise any frontends since it's equivalent to never 
- * having used the rings. */
+/* Reset the xenbus connection so the next kernel can start again. */
 void xenbus_shutdown(void)
 {
     ASSERT(rings != NULL);
+
+    /* We zero out the whole ring -- the backend can handle this, and it's 
+     * not going to surprise any frontends since it's equivalent to never 
+     * having used the rings. */
     memset(rings, 0, sizeof *rings);
+
+    /* Clear the xenbus event-channel too */
+    get_shared_info()->evtchn_pending[event / sizeof (unsigned long)]
+        &= ~(1UL << ((event % sizeof (unsigned long))));    
+
     rings = NULL;
 }