win-pvdrivers

changeset 390:46b6fa5bb7ad

Put synchronisation code into xenbus. We also now kill the xenbus threads before suspend and start them again on resume, to avoid any chance of a race.
author James Harper <james.harper@bendigoit.com.au>
date Mon Jul 14 23:04:23 2008 +1000 (2008-07-14)
parents 3ffdcb607981
children 8e10579159a0
files xenpci/gnttbl.c xenpci/xenbus.c xenpci/xenpci.h xenpci/xenpci_fdo.c
line diff
     1.1 --- a/xenpci/gnttbl.c	Mon Jul 14 20:03:18 2008 +1000
     1.2 +++ b/xenpci/gnttbl.c	Mon Jul 14 23:04:23 2008 +1000
     1.3 @@ -196,6 +196,7 @@ GntTbl_InitMap(PXENPCI_DEVICE_DATA xpdd)
     1.4    {
     1.5      if (grant_frames > xpdd->max_grant_frames)
     1.6      {
     1.7 +      ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
     1.8        /* this won't actually work as it will be called at HIGH_IRQL and the free and unmap functions won't work... */
     1.9        ExFreePoolWithTag(xpdd->gnttab_list, XENPCI_POOL_TAG);
    1.10        MmUnmapIoSpace(xpdd->gnttab_table, PAGE_SIZE * xpdd->max_grant_frames);
    1.11 @@ -204,7 +205,8 @@ GntTbl_InitMap(PXENPCI_DEVICE_DATA xpdd)
    1.12    }
    1.13    
    1.14    if (!xpdd->gnttab_list)
    1.15 -  {  
    1.16 +  {
    1.17 +    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    1.18      xpdd->gnttab_list = ExAllocatePoolWithTag(NonPagedPool, sizeof(grant_ref_t) * grant_entries, XENPCI_POOL_TAG);
    1.19      xpdd->gnttab_table_physical = XenPci_AllocMMIO(xpdd,
    1.20        PAGE_SIZE * grant_frames);
     2.1 --- a/xenpci/xenbus.c	Mon Jul 14 20:03:18 2008 +1000
     2.2 +++ b/xenpci/xenbus.c	Mon Jul 14 23:04:23 2008 +1000
     2.3 @@ -40,16 +40,17 @@ static int allocate_xenbus_id(PXENPCI_DE
     2.4  {
     2.5    static int probe;
     2.6    int o_probe;
     2.7 +  KIRQL old_irql;
     2.8  
     2.9    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.10  
    2.11    for (;;)
    2.12    {
    2.13 -//    spin_lock(&req_lock);
    2.14 +    KeAcquireSpinLock(&xpdd->xenbus_id_lock, &old_irql);
    2.15      if (xpdd->nr_live_reqs < NR_XB_REQS)
    2.16        break;
    2.17 -//    spin_unlock(&req_lock);
    2.18 -//    wait_event(req_wq, (nr_live_reqs < NR_REQS));
    2.19 +    KeReleaseSpinLock(&xpdd->xenbus_id_lock, old_irql);
    2.20 +    KeWaitForSingleObject(&xpdd->xenbus_id_event, Executive, KernelMode, FALSE, NULL);
    2.21    }
    2.22  
    2.23    o_probe = probe;
    2.24 @@ -59,13 +60,12 @@ static int allocate_xenbus_id(PXENPCI_DE
    2.25      if (!xpdd->req_info[o_probe].In_Use)
    2.26        break;
    2.27      o_probe = (o_probe + 1) % NR_XB_REQS;
    2.28 -//    BUG_ON(o_probe == probe);
    2.29 +    ASSERT(o_probe != probe);
    2.30    }
    2.31    xpdd->nr_live_reqs++;
    2.32    xpdd->req_info[o_probe].In_Use = 1;
    2.33    probe = (o_probe + 1) % NR_XB_REQS;
    2.34 -  //spin_unlock(&req_lock);
    2.35 -  //init_waitqueue_head(&req_info[o_probe].waitq);
    2.36 +  KeReleaseSpinLock(&xpdd->xenbus_id_lock, old_irql);
    2.37    KeInitializeEvent(&xpdd->req_info[o_probe].WaitEvent, SynchronizationEvent, FALSE);
    2.38  
    2.39    //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    2.40 @@ -75,14 +75,16 @@ static int allocate_xenbus_id(PXENPCI_DE
    2.41  
    2.42  static void release_xenbus_id(PXENPCI_DEVICE_DATA xpdd, int id)
    2.43  {
    2.44 -//    BUG_ON(!req_info[id].in_use);
    2.45 -//    spin_lock(&req_lock);
    2.46 -    xpdd->req_info[id].In_Use = 0;
    2.47 -    xpdd->nr_live_reqs--;
    2.48 -    xpdd->req_info[id].In_Use = 0;
    2.49 -//    if (nr_live_reqs == NR_REQS - 1)
    2.50 -//        wake_up(&req_wq);
    2.51 -//    spin_unlock(&req_lock);
    2.52 +  KIRQL old_irql;
    2.53 +
    2.54 +  ASSERT(xpdd->req_info[id].In_Use);
    2.55 +  KeAcquireSpinLock(&xpdd->xenbus_id_lock, &old_irql);
    2.56 +  xpdd->req_info[id].In_Use = 0;
    2.57 +  xpdd->nr_live_reqs--;
    2.58 +  xpdd->req_info[id].In_Use = 0;
    2.59 +  if (xpdd->nr_live_reqs == NR_XB_REQS - 1)
    2.60 +    KeSetEvent(&xpdd->xenbus_id_event, IO_NO_INCREMENT, FALSE);
    2.61 +  KeReleaseSpinLock(&xpdd->xenbus_id_lock, old_irql);
    2.62  }
    2.63  
    2.64  // This routine free's the rep structure if there was an error!!!
    2.65 @@ -145,19 +147,15 @@ static void xb_write(
    2.66  
    2.67    cur_req = &header_req;
    2.68  
    2.69 -//  BUG_ON(len > XENSTORE_RING_SIZE);
    2.70 +  ASSERT(len <= XENSTORE_RING_SIZE);
    2.71    /* Wait for the ring to drain to the point where we can send the
    2.72       message. */
    2.73    prod = xpdd->xen_store_interface->req_prod;
    2.74  
    2.75 -  //KdPrint((__DRIVER_NAME " prod = %08x\n", prod));
    2.76 -
    2.77 -  if (prod + len - xpdd->xen_store_interface->req_cons > XENSTORE_RING_SIZE)
    2.78 +  while (prod + len - xpdd->xen_store_interface->req_cons > XENSTORE_RING_SIZE)
    2.79    {
    2.80      /* Wait for there to be space on the ring */
    2.81 -    //KdPrint((__DRIVER_NAME " prod %d, len %d, cons %d, size %d; waiting.\n", prod, len, xen_store_interface->req_cons, XENSTORE_RING_SIZE));
    2.82 -//    wait_event(xb_waitq, xen_store_interface->req_prod + len - xen_store_interface->req_cons <= XENSTORE_RING_SIZE);
    2.83 -    //KdPrint((__DRIVER_NAME " Back from wait.\n"));
    2.84 +    KeWaitForSingleObject(&xpdd->XenBus_ReadThreadEvent, Executive, KernelMode, FALSE, NULL);
    2.85      prod = xpdd->xen_store_interface->req_prod;
    2.86    }
    2.87  
    2.88 @@ -184,20 +182,11 @@ static void xb_write(
    2.89      }
    2.90    }
    2.91  
    2.92 -  //KdPrint((__DRIVER_NAME " Complete main loop of xb_write.\n"));
    2.93 -
    2.94 -//  BUG_ON(req_off != 0);
    2.95 -//  BUG_ON(total_off != len);
    2.96 -//  BUG_ON(prod > xen_store_interface->req_cons + XENSTORE_RING_SIZE);
    2.97 -
    2.98    /* Remote must see entire message before updating indexes */
    2.99 -  //_WriteBarrier();
   2.100    KeMemoryBarrier();
   2.101  
   2.102    xpdd->xen_store_interface->req_prod += (XENSTORE_RING_IDX)len;
   2.103  
   2.104 -  //KdPrint((__DRIVER_NAME " prod = %08x\n", xen_store_interface->req_prod));
   2.105 -
   2.106    /* Send evtchn to notify remote */
   2.107    EvtChn_Notify(xpdd, xpdd->xen_store_evtchn);
   2.108  
   2.109 @@ -274,8 +263,6 @@ XenBus_Write(
   2.110    struct write_req req[] = {
   2.111      {path, (ULONG)strlen(path) + 1},
   2.112      {value, (ULONG)strlen(value)},
   2.113 -//    {path, (ULONG)strlen(path)},
   2.114 -//    {value, (ULONG)strlen(value)},
   2.115    };
   2.116    struct xsd_sockmsg *rep;
   2.117    char *msg;
   2.118 @@ -295,11 +282,12 @@ XenBus_Write(
   2.119    return NULL;
   2.120  }
   2.121  
   2.122 -static VOID
   2.123 +NTSTATUS
   2.124  XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
   2.125  {
   2.126    PHYSICAL_ADDRESS pa_xen_store_interface;
   2.127    xen_ulong_t xen_store_mfn;
   2.128 +  NTSTATUS status;
   2.129  
   2.130    xpdd->xen_store_evtchn = (evtchn_port_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_EVTCHN);
   2.131    xen_store_mfn = (xen_ulong_t)hvm_get_parameter(xpdd, HVM_PARAM_STORE_PFN);
   2.132 @@ -307,12 +295,31 @@ XenBus_Connect(PXENPCI_DEVICE_DATA xpdd)
   2.133    xpdd->xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
   2.134  
   2.135    EvtChn_BindDpc(xpdd, xpdd->xen_store_evtchn, XenBus_Interrupt, xpdd);
   2.136 +
   2.137 +  xpdd->XenBus_ShuttingDown = FALSE;
   2.138 +  KeMemoryBarrier();
   2.139 +
   2.140 +  status = PsCreateSystemThread(&xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, xpdd);
   2.141 +  if (!NT_SUCCESS(status))
   2.142 +  {
   2.143 +    KdPrint((__DRIVER_NAME " Could not start read thread\n"));
   2.144 +    return status;
   2.145 +  }
   2.146 +
   2.147 +  status = PsCreateSystemThread(&xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, xpdd);
   2.148 +  if (!NT_SUCCESS(status))
   2.149 +  {
   2.150 +    KdPrint((__DRIVER_NAME " Could not start watch thread\n"));
   2.151 +    return status;
   2.152 +  }
   2.153 +  
   2.154 +  return STATUS_SUCCESS;
   2.155  }
   2.156  
   2.157  NTSTATUS
   2.158  XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
   2.159  {
   2.160 -  NTSTATUS Status;
   2.161 +  NTSTATUS status;
   2.162    int i;
   2.163      
   2.164  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   2.165 @@ -330,29 +337,22 @@ XenBus_Init(PXENPCI_DEVICE_DATA xpdd)
   2.166  
   2.167    KeInitializeEvent(&xpdd->XenBus_ReadThreadEvent, SynchronizationEvent, FALSE);
   2.168    KeInitializeEvent(&xpdd->XenBus_WatchThreadEvent, SynchronizationEvent, FALSE);
   2.169 +  KeInitializeEvent(&xpdd->xenbus_id_event, SynchronizationEvent, FALSE);
   2.170 +  KeInitializeSpinLock(&xpdd->xenbus_id_lock);
   2.171    xpdd->XenBus_ShuttingDown = FALSE;
   2.172  
   2.173 -  Status = PsCreateSystemThread(&xpdd->XenBus_ReadThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_ReadThreadProc, xpdd);
   2.174 -  if (!NT_SUCCESS(Status))
   2.175 +  status = XenBus_Connect(xpdd);
   2.176 +  if (!NT_SUCCESS(status))
   2.177    {
   2.178 -    KdPrint((__DRIVER_NAME " Could not start read thread\n"));
   2.179 -    return STATUS_UNSUCCESSFUL;
   2.180 +    return status;
   2.181    }
   2.182 -
   2.183 -  Status = PsCreateSystemThread(&xpdd->XenBus_WatchThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, XenBus_WatchThreadProc, xpdd);
   2.184 -  if (!NT_SUCCESS(Status))
   2.185 -  {
   2.186 -    KdPrint((__DRIVER_NAME " Could not start watch thread\n"));
   2.187 -    return STATUS_UNSUCCESSFUL;
   2.188 -  }
   2.189 -
   2.190 -  XenBus_Connect(xpdd);
   2.191    
   2.192  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.193  
   2.194    return STATUS_SUCCESS;
   2.195  }
   2.196  
   2.197 +#if 0
   2.198  NTSTATUS
   2.199  XenBus_Stop(PXENPCI_DEVICE_DATA xpdd)
   2.200  {
   2.201 @@ -374,9 +374,10 @@ XenBus_Stop(PXENPCI_DEVICE_DATA xpdd)
   2.202  
   2.203    return STATUS_SUCCESS;
   2.204  }
   2.205 +#endif
   2.206  
   2.207  NTSTATUS
   2.208 -XenBus_Close(PXENPCI_DEVICE_DATA xpdd)
   2.209 +XenBus_StopThreads(PXENPCI_DEVICE_DATA xpdd)
   2.210  {
   2.211    //KWAIT_BLOCK WaitBlockArray[2];
   2.212    PVOID WaitArray[2];
   2.213 @@ -473,7 +474,6 @@ XenBus_ReadThreadProc(PVOID StartContext
   2.214          //KdPrint((__DRIVER_NAME " +++ Message incomplete (not even a full header)\n"));
   2.215          break;
   2.216        }
   2.217 -      //_ReadBarrier();
   2.218        KeMemoryBarrier();
   2.219        memcpy_from_ring(xpdd->xen_store_interface->rsp, &msg,
   2.220          MASK_XENSTORE_IDX(xpdd->xen_store_interface->rsp_cons), sizeof(msg));
   2.221 @@ -517,7 +517,6 @@ XenBus_ReadThreadProc(PVOID StartContext
   2.222          }
   2.223  
   2.224          ExFreePoolWithTag(payload, XENPCI_POOL_TAG);
   2.225 -        //KdPrint((__DRIVER_NAME " +++ Watch Path = %s Token = %s\n", path, token));
   2.226          KeSetEvent(&xpdd->XenBus_WatchThreadEvent, IO_NO_INCREMENT, FALSE);
   2.227        }
   2.228      }
   2.229 @@ -599,14 +598,19 @@ XenBus_SendAddWatch(
   2.230  }
   2.231  
   2.232  /* called at PASSIVE_LEVEL */
   2.233 -VOID
   2.234 +NTSTATUS
   2.235  XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
   2.236  {
   2.237 +  NTSTATUS status;
   2.238    int i;
   2.239  
   2.240    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   2.241  
   2.242 -  XenBus_Connect(xpdd);
   2.243 +  status = XenBus_Connect(xpdd);
   2.244 +  if (!NT_SUCCESS(status))
   2.245 +  {
   2.246 +    return status;
   2.247 +  }
   2.248    
   2.249    for (i = 0; i < MAX_WATCH_ENTRIES; i++)
   2.250    {
   2.251 @@ -617,6 +621,8 @@ XenBus_Resume(PXENPCI_DEVICE_DATA xpdd)
   2.252      }
   2.253    }
   2.254    KdPrint((__DRIVER_NAME " <-- XenBus_AddWatch\n"));
   2.255 +  
   2.256 +  return STATUS_SUCCESS;
   2.257  }
   2.258  
   2.259  char *
     3.1 --- a/xenpci/xenpci.h	Mon Jul 14 20:03:18 2008 +1000
     3.2 +++ b/xenpci/xenpci.h	Mon Jul 14 23:04:23 2008 +1000
     3.3 @@ -202,6 +202,9 @@ typedef struct {
     3.4    HANDLE XenBus_WatchThreadHandle;
     3.5    KEVENT XenBus_WatchThreadEvent;
     3.6  
     3.7 +  KSPIN_LOCK xenbus_id_lock;
     3.8 +  KEVENT xenbus_id_event;
     3.9 +  
    3.10    XENBUS_WATCH_RING XenBus_WatchRing[WATCH_RING_SIZE];
    3.11    int XenBus_WatchRingReadIndex;
    3.12    int XenBus_WatchRingWriteIndex;
    3.13 @@ -394,8 +397,10 @@ NTSTATUS
    3.14  XenBus_Start(PXENPCI_DEVICE_DATA xpdd);
    3.15  NTSTATUS
    3.16  XenBus_Stop(PXENPCI_DEVICE_DATA xpdd);
    3.17 -VOID
    3.18 +NTSTATUS
    3.19  XenBus_Resume(PXENPCI_DEVICE_DATA xpdd);
    3.20 +NTSTATUS
    3.21 +XenBus_StopThreads(PXENPCI_DEVICE_DATA xpdd);
    3.22  
    3.23  PHYSICAL_ADDRESS
    3.24  XenPci_AllocMMIO(PXENPCI_DEVICE_DATA xpdd, ULONG len);
    3.25 @@ -404,10 +409,6 @@ NTSTATUS
    3.26  EvtChn_Init(PXENPCI_DEVICE_DATA xpdd);
    3.27  NTSTATUS
    3.28  EvtChn_ConnectInterrupt(PXENPCI_DEVICE_DATA xpdd);
    3.29 -/*
    3.30 -VOID
    3.31 -EvtChn_Resume(PXENPCI_DEVICE_DATA xpdd);
    3.32 -*/
    3.33  NTSTATUS
    3.34  EvtChn_Shutdown(PXENPCI_DEVICE_DATA xpdd);
    3.35  
     4.1 --- a/xenpci/xenpci_fdo.c	Mon Jul 14 20:03:18 2008 +1000
     4.2 +++ b/xenpci/xenpci_fdo.c	Mon Jul 14 23:04:23 2008 +1000
     4.3 @@ -438,26 +438,29 @@ XenPci_Suspend(
     4.4  
     4.5  /* Called at PASSIVE_LEVEL */
     4.6  static VOID
     4.7 -XenPci_BeginSuspend(PXENPCI_DEVICE_DATA xpdd)
     4.8 +XenPci_BeginSuspend(PDEVICE_OBJECT device_object, PVOID context)
     4.9  {
    4.10    //KAFFINITY ActiveProcessorMask = 0; // this is for Vista+
    4.11 +  PXENPCI_DEVICE_DATA xpdd = device_object->DeviceExtension;
    4.12    ULONG ActiveProcessorCount;
    4.13    ULONG i;
    4.14    PSUSPEND_INFO suspend_info;
    4.15    PKDPC Dpc;
    4.16    KIRQL OldIrql;
    4.17  
    4.18 +  UNREFERENCED_PARAMETER(context);
    4.19    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    4.20  
    4.21    if (xpdd->suspend_state == SUSPEND_STATE_NONE)
    4.22    {
    4.23 +    XenBus_StopThreads(xpdd);
    4.24      xpdd->suspend_state = SUSPEND_STATE_SCHEDULED;
    4.25      suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
    4.26      RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
    4.27      KeInitializeEvent(&suspend_info->stopped_spinning_event, SynchronizationEvent, FALSE);
    4.28      suspend_info->do_spin = 1;
    4.29  
    4.30 -     for (i = 0; i < MAX_VIRT_CPUS; i++)
    4.31 +    for (i = 0; i < MAX_VIRT_CPUS; i++)
    4.32      {
    4.33        xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
    4.34      }
    4.35 @@ -486,6 +489,7 @@ XenPci_ShutdownHandler(char *path, PVOID
    4.36    char *res;
    4.37    char *value;
    4.38    KIRQL old_irql;
    4.39 +  PIO_WORKITEM work_item;
    4.40  
    4.41    UNREFERENCED_PARAMETER(path);
    4.42  
    4.43 @@ -506,7 +510,10 @@ XenPci_ShutdownHandler(char *path, PVOID
    4.44      if (strcmp(value, "suspend") == 0)
    4.45      {
    4.46        KdPrint((__DRIVER_NAME "     Suspend detected\n"));
    4.47 -      XenPci_BeginSuspend(xpdd);
    4.48 +      /* we have to queue this as a work item as we stop the xenbus thread, which we are currently running in! */
    4.49 +    	work_item = IoAllocateWorkItem(xpdd->common.fdo);
    4.50 +      IoQueueWorkItem(work_item, XenPci_BeginSuspend, DelayedWorkQueue, NULL);
    4.51 +      //XenPci_BeginSuspend(xpdd);
    4.52      }
    4.53      else
    4.54      {