Quellcode durchsuchen

[xen] Wait for and clear XenStore event before receiving data

Older, out-of-tree Xen kernel modules (such as those provided with
SuSE Linux Enterprise Server 11) do not clear the leftover "event
pending" bit when opening an event channel.  Consequently, no event is
ever delivered to indicate that there is information in the XenStore
ring buffer, and the system hangs shortly after loading the
xen-platform-pci kernel module.

Work around this problem by always waiting for the XenStore event
channel to be signalled, and clearing the event before processing the
received data.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown vor 9 Jahren
Ursprung
Commit
211529a7fe
2 geänderte Dateien mit 23 neuen und 0 gelöschten Zeilen
  1. 19
    0
      src/arch/x86/include/bits/xen.h
  2. 4
    0
      src/interface/xen/xenstore.c

+ 19
- 0
src/arch/x86/include/bits/xen.h Datei anzeigen

@@ -161,4 +161,23 @@ xen_hypercall_5 ( struct xen_hypervisor *xen, unsigned int hypercall,
161 161
 	return retval;
162 162
 }
163 163
 
164
+/**
165
+ * Test and clear pending event
166
+ *
167
+ * @v xen		Xen hypervisor
168
+ * @v port		Event channel port
169
+ * @ret pending		Event was pending
170
+ */
171
+static inline __attribute__ (( always_inline )) uint8_t
172
+xenevent_pending ( struct xen_hypervisor *xen, evtchn_port_t port ) {
173
+	uint8_t pending;
174
+
175
+	__asm__ __volatile__ ( "lock btr %2, %0\n\t"
176
+			       "setc %1\n\t"
177
+			       : "+m" ( xen->shared->evtchn_pending ),
178
+				 "=a"  ( pending )
179
+			       : "Ir" ( port ) );
180
+	return pending;
181
+}
182
+
164 183
 #endif /* _BITS_XEN_H */

+ 4
- 0
src/interface/xen/xenstore.c Datei anzeigen

@@ -242,6 +242,10 @@ static int xenstore_response ( struct xen_hypervisor *xen, uint32_t req_id,
242 242
 	char *string;
243 243
 	int rc;
244 244
 
245
+	/* Wait for response to become available */
246
+	while ( ! xenevent_pending ( xen, xen->store.port ) )
247
+		cpu_nap();
248
+
245 249
 	/* Receive message header */
246 250
 	xenstore_recv ( xen, &msg, sizeof ( msg ) );
247 251
 	*len = msg.len;

Laden…
Abbrechen
Speichern