win-pvdrivers

changeset 198:c5f21187ef46

Working on suspend/resume. Suspend works (well... you get a checkpoint file), but resume fails.
author James Harper <james.harper@bendigoit.com.au>
date Thu Feb 28 09:06:35 2008 +1100 (2008-02-28)
parents 62ff836f2d58
children 99985a5aa1dc
files common.inc xenpci/hypercall_x86.h xenpci/xenpci.c xenpci/xenpci.h
line diff
     1.1 --- a/common.inc	Wed Feb 27 11:01:07 2008 +1100
     1.2 +++ b/common.inc	Thu Feb 28 09:06:35 2008 +1100
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.4.0
     1.5 +VERSION=0.8.4.3
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  KMDF_VERSION=1
     1.8  !IF $(_NT_TOOLS_VERSION) > 0x700
     2.1 --- a/xenpci/hypercall_x86.h	Wed Feb 27 11:01:07 2008 +1100
     2.2 +++ b/xenpci/hypercall_x86.h	Thu Feb 28 09:06:35 2008 +1100
     2.3 @@ -34,6 +34,22 @@ HYPERVISOR_memory_op(WDFDEVICE Device, i
     2.4  }
     2.5  
     2.6  static __inline int
     2.7 +HYPERVISOR_sched_op(WDFDEVICE Device, int cmd, void *arg)
     2.8 +{
     2.9 +  char *hypercall_stubs = GetDeviceData(Device)->hypercall_stubs;
    2.10 +  long __res;
    2.11 +  __asm {
    2.12 +    mov ebx, cmd
    2.13 +    mov ecx, arg
    2.14 +    mov eax, hypercall_stubs
    2.15 +    add eax, (__HYPERVISOR_sched_op * 32)
    2.16 +    call eax
    2.17 +    mov [__res], eax
    2.18 +  }
    2.19 +  return __res;
    2.20 +}
    2.21 +
    2.22 +static __inline int
    2.23  HYPERVISOR_xen_version(WDFDEVICE Device, int cmd, void *arg)
    2.24  {
    2.25    char *hypercall_stubs = GetDeviceData(Device)->hypercall_stubs;
    2.26 @@ -149,3 +165,23 @@ hvm_get_parameter(WDFDEVICE Device, int 
    2.27    KdPrint((__DRIVER_NAME " <-- hvm_get_parameter\n"));
    2.28    return a.value;
    2.29  }
    2.30 +
    2.31 +static __inline int
    2.32 +HYPERVISOR_shutdown(WDFDEVICE Device, unsigned int reason)
    2.33 +{
    2.34 +  struct sched_shutdown ss;
    2.35 +  int retval;
    2.36 +
    2.37 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.38 +
    2.39 +  ss.reason = reason;
    2.40 +
    2.41 +  KdPrint((__DRIVER_NAME "     A\n"));
    2.42 +
    2.43 +  retval = HYPERVISOR_sched_op(Device, SCHEDOP_shutdown, &ss);
    2.44 +
    2.45 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    2.46 +
    2.47 +  return retval;
    2.48 +}
    2.49 +
     3.1 --- a/xenpci/xenpci.c	Wed Feb 27 11:01:07 2008 +1100
     3.2 +++ b/xenpci/xenpci.c	Thu Feb 28 09:06:35 2008 +1100
     3.3 @@ -851,6 +851,104 @@ struct {
     3.4    ULONG nr_spinning;
     3.5  } typedef SUSPEND_INFO, *PSUSPEND_INFO;
     3.6  
     3.7 +static VOID
     3.8 +XenPci_Suspend(
     3.9 + PRKDPC Dpc,
    3.10 + PVOID Context,
    3.11 + PVOID SystemArgument1,
    3.12 + PVOID SystemArgument2)
    3.13 +{
    3.14 +  WDFDEVICE Device = Context;
    3.15 +//  PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
    3.16 +  PSUSPEND_INFO suspend_info = SystemArgument1;
    3.17 +  ULONG ActiveProcessorCount;
    3.18 +  KIRQL OldIrql;
    3.19 +  int cancelled;
    3.20 +
    3.21 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (CPU = %d)\n", KeGetCurrentProcessorNumber()));
    3.22 +  KdPrint((__DRIVER_NAME "     Device = %p\n", Device));
    3.23 +
    3.24 +  if (KeGetCurrentProcessorNumber() != 0)
    3.25 +  {
    3.26 +    KdPrint((__DRIVER_NAME "     spinning...\n"));
    3.27 +    InterlockedIncrement((volatile LONG *)&suspend_info->nr_spinning);
    3.28 +    KeMemoryBarrier();
    3.29 +    while(suspend_info->do_spin)
    3.30 +    {
    3.31 +      /* we should be able to wait more nicely than this... */
    3.32 +    }
    3.33 +    KeMemoryBarrier();
    3.34 +    InterlockedDecrement((volatile LONG *)&suspend_info->nr_spinning);    
    3.35 +    KdPrint((__DRIVER_NAME "     ...done spinning\n"));
    3.36 +    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
    3.37 +    return;
    3.38 +  }
    3.39 +  ActiveProcessorCount = KeNumberProcessors;
    3.40 +
    3.41 +  KdPrint((__DRIVER_NAME "     waiting for all other processors to spin\n"));
    3.42 +  while (suspend_info->nr_spinning < ActiveProcessorCount - 1)
    3.43 +  {
    3.44 +      /* we should be able to wait more nicely than this... */
    3.45 +  }
    3.46 +  KdPrint((__DRIVER_NAME "     all other processors are spinning\n"));
    3.47 +
    3.48 +  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    3.49 +  KdPrint((__DRIVER_NAME "     calling suspend\n"));
    3.50 +  cancelled = HYPERVISOR_shutdown(Device, SHUTDOWN_suspend);
    3.51 +  KdPrint((__DRIVER_NAME "     back from suspend, cancelled = %d\n", cancelled));
    3.52 +  KeLowerIrql(OldIrql);
    3.53 +
    3.54 +  KdPrint((__DRIVER_NAME "     waiting for all other processors to stop spinning\n"));
    3.55 +  suspend_info->do_spin = 0;
    3.56 +  while (suspend_info->nr_spinning != 0)
    3.57 +  {
    3.58 +      /* we should be able to wait more nicely than this... */
    3.59 +  }
    3.60 +  KdPrint((__DRIVER_NAME "     all other processors have stopped spinning\n"));
    3.61 +
    3.62 +  // TODO: Enable xenbus
    3.63 +  // TODO: Enable our IRQ
    3.64 +
    3.65 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n", KeGetCurrentProcessorNumber()));
    3.66 +}
    3.67 +
    3.68 +static VOID
    3.69 +XenPci_BeginSuspend(WDFDEVICE Device)
    3.70 +{
    3.71 +  PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
    3.72 +//  KAFFINITY ActiveProcessorMask = 0;
    3.73 +  ULONG ActiveProcessorCount;
    3.74 +  ULONG i;
    3.75 +  PSUSPEND_INFO suspend_info;
    3.76 +  PKDPC Dpc;
    3.77 +  KIRQL OldIrql;
    3.78 +
    3.79 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    3.80 +  KdPrint((__DRIVER_NAME "     Device = %p\n", Device));
    3.81 +
    3.82 +  if (!xpdd->suspending)
    3.83 +  {
    3.84 +    xpdd->suspending = 1;
    3.85 +    suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
    3.86 +    suspend_info->do_spin = 1;
    3.87 +    RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO));
    3.88 +    // TODO: Disable xenbus
    3.89 +    // TODO: Disable our IRQ
    3.90 +    //ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask);
    3.91 +    ActiveProcessorCount = KeNumberProcessors;
    3.92 +    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    3.93 +    for (i = 0; i < ActiveProcessorCount; i++)
    3.94 +    {
    3.95 +      Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
    3.96 +      KeInitializeDpc(Dpc, XenPci_Suspend, Device);
    3.97 +      KeSetTargetProcessorDpc(Dpc, (CCHAR)i);
    3.98 +      KeInsertQueueDpc(Dpc, suspend_info, NULL);
    3.99 +    }
   3.100 +    KeLowerIrql(OldIrql);
   3.101 +  }
   3.102 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.103 +}
   3.104 +
   3.105  static void
   3.106  XenBus_ShutdownHandler(char *Path, PVOID Data)
   3.107  {
   3.108 @@ -860,15 +958,11 @@ XenBus_ShutdownHandler(char *Path, PVOID
   3.109    xenbus_transaction_t xbt;
   3.110    int retry;
   3.111    PSHUTDOWN_MSG_ENTRY Entry;
   3.112 -  PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
   3.113 -  KAFFINITY ActiveProcessorMask = 0;
   3.114 -  ULONG ActiveProcessorCount;
   3.115 -  int i;
   3.116 -  PSUSPEND_INFO suspend_info;
   3.117  
   3.118    UNREFERENCED_PARAMETER(Path);
   3.119  
   3.120 -  KdPrint((__DRIVER_NAME " --> XenBus_ShutdownHandler\n"));
   3.121 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.122 +  KdPrint((__DRIVER_NAME "     Device = %p\n", Device));
   3.123  
   3.124    res = XenBus_StartTransaction(Device, &xbt);
   3.125    if (res)
   3.126 @@ -921,23 +1015,8 @@ XenBus_ShutdownHandler(char *Path, PVOID
   3.127    {
   3.128      if (strcmp(Value, "suspend") == 0)
   3.129      {
   3.130 -#if 0
   3.131 -// this won't work this way... 
   3.132 -// need to create a thread at PASSIVE_LEVEL, turn off xenbus, then go to DISPATCH_LEVEL on all CPU's
   3.133 -      if (!xpdd->suspending)
   3.134 -      {
   3.135 -        suspend_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(SUSPEND_INFO), XENPCI_POOL_TAG);
   3.136 -        RtlZeroMemory(suspend_info, sizeof(SUSPEND_INFO);
   3.137 -        xpdd->suspending = 1;
   3.138 -        ActiveProcessorCount = KeQueryActiveProcessorCount(&ActiveProcessorMask);
   3.139 -        for (i = 0; i < ActiveProcessorCount; i++)
   3.140 -        {
   3.141 -          Dpc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), XENPCI_POOL_TAG);
   3.142 -          KeInitializeDpc(&Dpc, XenPci_Suspend, xpdd);
   3.143 -          KeSetTargetProcessorDpc(&Dpc, i);
   3.144 -          KeInsertQueueDpc(&Dpc, suspend_info, NULL);
   3.145 -        }
   3.146 -#endif
   3.147 +      KdPrint((__DRIVER_NAME "     Suspend detected\n"));
   3.148 +      XenPci_BeginSuspend(Device);
   3.149      }
   3.150      else
   3.151      {
   3.152 @@ -951,7 +1030,7 @@ XenBus_ShutdownHandler(char *Path, PVOID
   3.153  
   3.154    XenPCI_FreeMem(Value);
   3.155  
   3.156 -  KdPrint((__DRIVER_NAME " <-- XenBus_ShutdownHandler\n"));
   3.157 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.158  }
   3.159  
   3.160  static VOID
     4.1 --- a/xenpci/xenpci.h	Wed Feb 27 11:01:07 2008 +1100
     4.2 +++ b/xenpci/xenpci.h	Thu Feb 28 09:06:35 2008 +1100
     4.3 @@ -41,6 +41,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     4.4  #include <event_channel.h>
     4.5  #include <hvm/params.h>
     4.6  #include <hvm/hvm_op.h>
     4.7 +#include <sched.h>
     4.8  
     4.9  #include <xen_public.h>
    4.10  
    4.11 @@ -144,6 +145,8 @@ typedef struct {
    4.12    KSPIN_LOCK grant_lock;
    4.13  
    4.14    KGUARDED_MUTEX WatchHandlerMutex;
    4.15 +
    4.16 +  int suspending;
    4.17  } XENPCI_DEVICE_DATA, *PXENPCI_DEVICE_DATA;
    4.18  
    4.19  WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENPCI_DEVICE_DATA, GetDeviceData);