]> xenbits.xensource.com Git - pvdrivers/win/xenbus.git/commitdiff
Make sure the interrupt handler for each vCPU is run...
authorPaul Durrant <pdurrant@amazon.com>
Fri, 4 Dec 2020 20:01:41 +0000 (20:01 +0000)
committerPaul Durrant <pdurrant@amazon.com>
Fri, 4 Dec 2020 20:14:26 +0000 (20:14 +0000)
... 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@amazon.com>
src/xenbus/evtchn.c
src/xenbus/fdo.c

index 55c16b73212a837f267de4c2d103373ccd3e8543..d0702686aeea041e3a063eb6f2208a10a71c8893 100644 (file)
@@ -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");
 }
 
index 9944ef6d5c0e72c60c7be030d128959eda7c51a3..21de8678c9595e47d28547d94a4449f41313a317 100644 (file)
@@ -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);
 }