win-pvdrivers

changeset 407:d84a58b968e8

implemented timers to make sure all cpu's are spinning, otherwise give up.
Manually masked stray interrupts which may occur even after we've disabled them
author James Harper <james.harper@bendigoit.com.au>
date Fri Jul 25 16:25:40 2008 +1000 (2008-07-25)
parents b9028997f48b
children 853fa6745f58
files xenpci/evtchn.c xenpci/xenpci.h xenpci/xenpci_fdo.c xenvbd/scsiport.c
line diff
     1.1 --- a/xenpci/evtchn.c	Fri Jul 25 11:17:41 2008 +1000
     1.2 +++ b/xenpci/evtchn.c	Fri Jul 25 16:25:40 2008 +1000
     1.3 @@ -75,10 +75,10 @@ EvtChn_Interrupt(PKINTERRUPT Interrupt, 
     1.4  
     1.5    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (cpu = %d)\n", cpu));
     1.6  
     1.7 -  if (no_more_interrupts)
     1.8 +  if (xpdd->interrupts_masked)
     1.9    {
    1.10 -    KdPrint((__DRIVER_NAME "     no_more_interrupts = TRUE\n"));
    1.11 -    KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000000, 0x00000000, 0x00000000);
    1.12 +    KdPrint((__DRIVER_NAME "     unhandled interrupt\n"));
    1.13 +    //KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000003, 0x00000000, 0x00000000, 0x00000000);
    1.14    }
    1.15      
    1.16    //ASSERT(!no_more_interrupts);
    1.17 @@ -287,13 +287,14 @@ EvtChn_Init(PXENPCI_DEVICE_DATA xpdd)
    1.18      xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
    1.19    }
    1.20  
    1.21 -  no_more_interrupts = FALSE;
    1.22    KeMemoryBarrier();
    1.23  
    1.24    hvm_set_parameter(xpdd, HVM_PARAM_CALLBACK_IRQ, xpdd->irq_number);
    1.25  
    1.26    for (i = 0; i < MAX_VIRT_CPUS; i++)
    1.27 -    xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 0;
    1.28 +    xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 0;  
    1.29 +  xpdd->interrupts_masked = FALSE;
    1.30 +  KeMemoryBarrier();
    1.31  
    1.32    
    1.33    FUNCTION_EXIT();
    1.34 @@ -336,12 +337,14 @@ EvtChn_Shutdown(PXENPCI_DEVICE_DATA xpdd
    1.35    int i;
    1.36  //  LARGE_INTEGER wait_time;
    1.37  
    1.38 +  xpdd->interrupts_masked = TRUE;
    1.39    for (i = 0; i < MAX_VIRT_CPUS; i++)
    1.40      xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
    1.41 -  hvm_set_parameter(xpdd, HVM_PARAM_CALLBACK_IRQ, 0);
    1.42    KeMemoryBarrier();
    1.43 -  no_more_interrupts = TRUE;
    1.44 -  KeMemoryBarrier();
    1.45 +  hvm_set_parameter(xpdd, HVM_PARAM_CALLBACK_IRQ, 0);
    1.46 +  //KeMemoryBarrier();
    1.47 +  //no_more_interrupts = TRUE;
    1.48 +  //KeMemoryBarrier();
    1.49  
    1.50  #if (NTDDI_VERSION >= NTDDI_WINXP)
    1.51    KeFlushQueuedDpcs();
     2.1 --- a/xenpci/xenpci.h	Fri Jul 25 11:17:41 2008 +1000
     2.2 +++ b/xenpci/xenpci.h	Fri Jul 25 16:25:40 2008 +1000
     2.3 @@ -176,6 +176,7 @@ typedef struct {
     2.4  
     2.5    PHYSICAL_ADDRESS shared_info_area_unmapped;
     2.6    shared_info_t *shared_info_area;
     2.7 +  BOOLEAN interrupts_masked;
     2.8  
     2.9    PHYSICAL_ADDRESS platform_mmio_addr;
    2.10    ULONG platform_mmio_orig_len;
     3.1 --- a/xenpci/xenpci_fdo.c	Fri Jul 25 11:17:41 2008 +1000
     3.2 +++ b/xenpci/xenpci_fdo.c	Fri Jul 25 16:25:40 2008 +1000
     3.3 @@ -304,6 +304,7 @@ XenBus_ShutdownIoCancel(PDEVICE_OBJECT d
     3.4  
     3.5  struct {
     3.6    volatile ULONG spin_state;
     3.7 +  volatile ULONG abort_spin;
     3.8    volatile LONG nr_spinning_dpc1;
     3.9    volatile LONG nr_spinning_high;
    3.10    volatile LONG nr_spinning_dpc2;
    3.11 @@ -362,6 +363,9 @@ XenPci_Suspend(
    3.12    int cancelled;
    3.13    PIO_WORKITEM work_item;
    3.14    PXEN_CHILD child;
    3.15 +  LARGE_INTEGER spin_abort_time;
    3.16 +  LARGE_INTEGER current_time;
    3.17 +  
    3.18    //PUCHAR gnttbl_backup[PAGE_SIZE * NR_GRANT_FRAMES];
    3.19  
    3.20    UNREFERENCED_PARAMETER(Dpc);
    3.21 @@ -373,13 +377,29 @@ XenPci_Suspend(
    3.22    if (KeGetCurrentProcessorNumber() != 0)
    3.23    {
    3.24      KdPrint((__DRIVER_NAME "     CPU %d spinning at dpc1...\n", KeGetCurrentProcessorNumber()));
    3.25 +    KeQuerySystemTime(&spin_abort_time);
    3.26 +    spin_abort_time.QuadPart += 10 * 1000 * 5000;
    3.27      InterlockedIncrement(&suspend_info->nr_spinning_dpc1);
    3.28 -    while(suspend_info->spin_state == SPIN_STATE_DPC1)
    3.29 +    while(suspend_info->spin_state == SPIN_STATE_DPC1 && !suspend_info->abort_spin)
    3.30      {
    3.31        KeStallExecutionProcessor(1);
    3.32        KeMemoryBarrier();
    3.33 +      KeQuerySystemTime(&current_time);
    3.34 +      if (current_time.QuadPart > spin_abort_time.QuadPart)
    3.35 +      {
    3.36 +        suspend_info->abort_spin = TRUE;
    3.37 +        KeMemoryBarrier();
    3.38 +        InterlockedDecrement(&suspend_info->nr_spinning_dpc1);    
    3.39 +        KdPrint((__DRIVER_NAME "     CPU %d waited long enough - aborting\n", KeGetCurrentProcessorNumber()));
    3.40 +        return;
    3.41 +      }
    3.42        /* can't call HYPERVISOR_yield() here as the stubs will be reset and we will crash */
    3.43      }
    3.44 +    if (suspend_info->abort_spin)
    3.45 +    {
    3.46 +      KdPrint((__DRIVER_NAME "     CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
    3.47 +      return;
    3.48 +    }
    3.49      InterlockedDecrement(&suspend_info->nr_spinning_dpc1);    
    3.50      KdPrint((__DRIVER_NAME "     CPU %d done spinning at dpc1\n", KeGetCurrentProcessorNumber()));
    3.51      KeRaiseIrql(HIGH_LEVEL, &old_irql);
    3.52 @@ -412,10 +432,27 @@ XenPci_Suspend(
    3.53    ActiveProcessorCount = (ULONG)KeNumberProcessors;
    3.54  
    3.55    KdPrint((__DRIVER_NAME "     waiting for all other processors to spin at dpc1\n"));
    3.56 -  while (suspend_info->nr_spinning_dpc1 < (LONG)ActiveProcessorCount - 1)
    3.57 +  KeQuerySystemTime(&spin_abort_time);
    3.58 +  spin_abort_time.QuadPart += 10 * 1000 * 5000;
    3.59 +  while (suspend_info->nr_spinning_dpc1 < (LONG)ActiveProcessorCount - 1 && !suspend_info->abort_spin)
    3.60    {
    3.61 -      HYPERVISOR_yield(xpdd);
    3.62 +    KeStallExecutionProcessor(1);
    3.63 +    //HYPERVISOR_yield(xpdd);
    3.64 +    KeMemoryBarrier();
    3.65 +    KeQuerySystemTime(&current_time);
    3.66 +    if (current_time.QuadPart > spin_abort_time.QuadPart)
    3.67 +    {
    3.68 +      suspend_info->abort_spin = TRUE;
    3.69        KeMemoryBarrier();
    3.70 +      InterlockedDecrement(&suspend_info->nr_spinning_dpc1);    
    3.71 +      KdPrint((__DRIVER_NAME "     CPU %d waited long enough - aborting\n", KeGetCurrentProcessorNumber()));
    3.72 +      return;
    3.73 +    }
    3.74 +  }
    3.75 +  if (suspend_info->abort_spin)
    3.76 +  {
    3.77 +    KdPrint((__DRIVER_NAME "     CPU %d spin aborted\n", KeGetCurrentProcessorNumber()));
    3.78 +    return;
    3.79    }
    3.80    KdPrint((__DRIVER_NAME "     all other processors are spinning at dpc1\n"));
    3.81    KeRaiseIrql(HIGH_LEVEL, &old_irql);
     4.1 --- a/xenvbd/scsiport.c	Fri Jul 25 11:17:41 2008 +1000
     4.2 +++ b/xenvbd/scsiport.c	Fri Jul 25 16:25:40 2008 +1000
     4.3 @@ -684,7 +684,7 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
     4.4  
     4.5    if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
     4.6    {
     4.7 -    KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
     4.8 +    //KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
     4.9      xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
    4.10      KeMemoryBarrier();
    4.11      return FALSE;
    4.12 @@ -832,7 +832,7 @@ XenVbd_HwScsiStartIo(PVOID DeviceExtensi
    4.13    {
    4.14      Srb->SrbStatus = SRB_STATUS_BUSY;
    4.15      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
    4.16 -    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Resuming)\n"));
    4.17 +    //KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Resuming)\n"));
    4.18      return TRUE;
    4.19    }
    4.20