[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH xenbus] Make sure the interrupt handler for each vCPU is run...



From: Paul Durrant <pdurrant@xxxxxxxxxx>

... after enabling event channel delivery.

New versions of Xen have this sequence in their map_vcpu_info() function:

    /*
     * Mark everything as being pending just to make sure nothing gets
     * lost.  The domain will get a spurious event, but it can cope.
     */
    if ( !has_32bit_shinfo(d) )
        write_atomic(&new_info->native.evtchn_pending_sel, ~0);
    else
        write_atomic(&vcpu_info(v, evtchn_pending_sel), ~0);
    vcpu_mark_events_pending(v);

whereas older versions code this differently:

    /*
     * Mark everything as being pending just to make sure nothing gets
     * lost.  The domain will get a spurious event, but it can cope.
     */
    vcpu_info(v, evtchn_upcall_pending) = 1;
    for ( i = 0; i < BITS_PER_EVTCHN_WORD(d); i++ )
        set_bit(i, &vcpu_info(v, evtchn_pending_sel));

The crucial difference is that in the older variant there is no call to
vcpu_mark_events_pending() which means that, for an HVM guest at least,
the upcall function that clears 'evtchn_upcall_pending' does not get
run and hence no events will be received on that vCPU.

This patch makes sure the upcall function for each vCPU is run at least once
thereby ensuring that 'evtchn_upcall_pending' is cleared.

NOTE: The patch also adds a 'Count' to each XENBUS_INTERRUPT object,
      incremented each time the interrupt is triggred, and emits a log line
      when the value transitions from zero.

Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 src/xenbus/evtchn.c | 9 +++++++++
 src/xenbus/fdo.c    | 7 +++++++
 2 files changed, 16 insertions(+)

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 55c16b73212a..d0702686aeea 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -1269,6 +1269,7 @@ EvtchnInterruptEnable(
 {
     ULONG                       Cpu;
     ULONG                       Line;
+    KIRQL                       Irql;
     NTSTATUS                    status;
 
     Trace("====>\n");
@@ -1312,6 +1313,10 @@ EvtchnInterruptEnable(
              ProcNumber.Number,
              Vector);
         Processor->UpcallEnabled = TRUE;
+
+        Irql = FdoAcquireInterruptLock(Context->Fdo, Processor->Interrupt);
+        (VOID) EvtchnInterruptCallback(NULL, Processor);
+        FdoReleaseInterruptLock(Context->Fdo, Processor->Interrupt, Irql);
     }
 
 line:
@@ -1322,6 +1327,10 @@ line:
 
     Info("CALLBACK VIA (Vector = %u)\n", Line);
 
+    Irql = FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    (VOID) EvtchnInterruptCallback(NULL, &Context->Processor[0]);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+
     Trace("<====\n");
 }
 
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 9944ef6d5c0e..21de8678c959 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -78,6 +78,7 @@ struct _XENBUS_INTERRUPT {
     ULONG               Line;
     PKSERVICE_ROUTINE   Callback;
     PVOID               Argument;
+    ULONG               Count;
 };
 
 typedef struct _XENBUS_VIRQ {
@@ -2212,6 +2213,12 @@ FdoInterruptCallback(
     if (Interrupt->Callback == NULL)
         return FALSE;
 
+    if (Interrupt->Count++ == 0)
+        LogPrintf(LOG_LEVEL_INFO,
+                  "XENBUS: %u:%u INTERRUPT\n",
+                  Interrupt->ProcNumber.Group,
+                  Interrupt->ProcNumber.Number);
+
     return Interrupt->Callback(InterruptObject,
                                Interrupt->Argument);
 }
-- 
2.17.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.