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

Re: [win-pv-devel] [PATCH 2/4] Re-work interrupt code in FDO



> -----Original Message-----
> From: Paul Durrant [mailto:paul.durrant@xxxxxxxxxx]
> Sent: 07 November 2014 13:33
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Paul Durrant
> Subject: [PATCH 2/4] Re-work interrupt code in FDO
> 
> This patch adds code to the FDO handler to acquire extra message signaled
> (i.e. edge triggered) interrupt vectors that can be used for per-CPU event
> channel upcalls (with extra support in Xen).
> The existing callback via is also limited to upcall on CPU 0 meaning the
> interrupt callback in the EVTCHN code can pass the current CPU value
> through
> to the ABI.
> 
> Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
> ---
>  src/common/names.h  | 122 ++++++-
>  src/xenbus.inf      |  10 +-
>  src/xenbus/evtchn.c |  55 +++-
>  src/xenbus/fdo.c    | 894
> +++++++++++++++++++++++++++++++++++++++++-----------
>  src/xenbus/fdo.h    |  39 ++-
>  src/xenbus/pdo.c    |   2 +-
>  6 files changed, 897 insertions(+), 225 deletions(-)
> 
> diff --git a/src/common/names.h b/src/common/names.h
> index 89894b9..f4a8bd0 100644
> --- a/src/common/names.h
> +++ b/src/common/names.h
> @@ -196,32 +196,124 @@ PnpMinorFunctionName(
>  }
> 
>  static FORCEINLINE const CHAR *
> -PartialResourceDescriptorTypeName(
> +ResourceDescriptorTypeName(
>      IN  UCHAR   Type
>      )
>  {
> -#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
> -    case CmResourceType ## _Type:                       \
> +#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
> +    case CmResourceType ## _Type:               \
>          return #_Type;
> 
>      switch (Type) {
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
>      default:
>          break;
>      }
> 
>      return "UNKNOWN";
> 
> -#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
> +#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +ResourceDescriptorShareDispositionName(
> +    IN  UCHAR   Disposition
> +    )
> +{
> +#define
> _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
> +    case CmResourceShare ## _Disposition:                           \
> +        return #_Disposition;
> +
> +    switch (Disposition) {
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +IrqDevicePolicyName(
> +    IN  IRQ_DEVICE_POLICY   Policy
> +    )
> +{
> +#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
> +    case IrqPolicy ## _Policy:              \
> +        return #_Policy;
> +
> +    switch (Policy) {
> +    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
> +    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
> +    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
> +    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
> +    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
> +    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _IRQ_DEVICE_POLICY_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +IrqPriorityName(
> +    IN  IRQ_PRIORITY    Priority
> +    )
> +{
> +#define _IRQ_PRIORITY_NAME(_Priority)   \
> +    case IrqPriority ## _Priority:      \
> +        return #_Priority;
> +
> +    switch (Priority) {
> +    _IRQ_PRIORITY_NAME(Undefined);
> +    _IRQ_PRIORITY_NAME(Low);
> +    _IRQ_PRIORITY_NAME(Normal);
> +    _IRQ_PRIORITY_NAME(High);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _IRQ_PRIORITY_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +InterruptModeName(
> +    IN  KINTERRUPT_MODE Mode
> +    )
> +{
> +#define _INTERRUPT_MODE_NAME(_Mode) \
> +    case _Mode:                     \
> +        return #_Mode;
> +
> +    switch (Mode) {
> +    _INTERRUPT_MODE_NAME(LevelSensitive);
> +    _INTERRUPT_MODE_NAME(Latched);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _INTERRUPT_MODE_NAME
>  }
> 
>  static FORCEINLINE const CHAR *
> @@ -358,4 +450,6 @@ BusQueryIdTypeName(
>  #undef  _BUS_QUERY_ID_TYPE_NAME
>  }
> 
> +
> +
>  #endif // _COMMON_NAMES_H_
> diff --git a/src/xenbus.inf b/src/xenbus.inf
> index 544bb2c..b2c17c3 100644
> --- a/src/xenbus.inf
> +++ b/src/xenbus.inf
> @@ -78,20 +78,26 @@ AddService=xenfilt,,XenFilt_Service,
>  [XenBus_Service]
>  DisplayName=%XenBusDesc%
>  ServiceType=%SERVICE_KERNEL_DRIVER%
> -StartType=%SERVICE_BOOT_START%
> +StartType=%SERVICE_DEMAND_START%

This change was meant to be only for the sake of my own debugging. I'll remove 
it and re-post.

  Paul

>  ErrorControl=%SERVICE_ERROR_NORMAL%
>  ServiceBinary=%12%\xenbus.sys
>  LoadOrderGroup="Boot Bus Extender"
> -AddReg = XenBus_Parameters, XenBus_Interfaces
> +AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
> 
>  [XenBus_Parameters]
>  HKR,"Parameters",,0x00000010
>  HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE"
>  HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE"
> +HKR,"Parameters","ExtraInterrupts",0x00010001,64
> 
>  [XenBus_Interfaces]
>  HKR,"Interfaces",,0x00000010
> 
> +[XenBus_Interrupts]
> +HKR,"Interrupt Management",,0x00000010
> +HKR,"Interrupt
> Management\MessageSignaledInterruptProperties",,0x00000010
> +HKR,"Interrupt
> Management\MessageSignaledInterruptProperties","MSISupported",0x000
> 10001,1
> +
>  [XenFilt_Service]
>  DisplayName=%XenFiltDesc%
>  ServiceType=%SERVICE_KERNEL_DRIVER%
> diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
> index 1bd5e5f..44043d4 100644
> --- a/src/xenbus/evtchn.c
> +++ b/src/xenbus/evtchn.c
> @@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
>      PXENBUS_FDO                     Fdo;
>      KSPIN_LOCK                      Lock;
>      LONG                            References;
> -    ULONG                           Vector;
> +    PXENBUS_INTERRUPT               Interrupt;
>      BOOLEAN                         Enabled;
>      XENBUS_SUSPEND_INTERFACE        SuspendInterface;
>      PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
> @@ -127,11 +127,14 @@ EvtchnInterruptEnable(
>      IN  PXENBUS_EVTCHN_CONTEXT  Context
>      )
>  {
> +    ULONG                       Line;
>      NTSTATUS                    status;
> 
>      Trace("<===>\n");
> 
> -    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
> +    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
> +
> +    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
>      ASSERT(NT_SUCCESS(status));
>  }
> 
> @@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
>      IN  PXENBUS_EVTCHN_CONTEXT  Context
>      )
>  {
> -    return FdoAcquireInterruptLock(Context->Fdo);
> +    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
>  }
> 
>  static FORCEINLINE
> @@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
>      IN  __drv_restoresIRQL KIRQL    Irql
>      )
>  {
> -    FdoReleaseInterruptLock(Context->Fdo, Irql);
> +    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
>  }
> 
>  static NTSTATUS
> @@ -644,21 +647,32 @@ done:
>      return DoneSomething;
>  }
> 
> +static
> +_Function_class_(KSERVICE_ROUTINE)
> +__drv_requiresIRQL(HIGH_LEVEL)
>  BOOLEAN
> -EvtchnInterrupt(
> -    IN  PXENBUS_EVTCHN_CONTEXT  Context
> +EvtchnInterruptCallback(
> +    IN  PKINTERRUPT         InterruptObject,
> +    IN  PVOID               Argument
>      )
>  {
> -    BOOLEAN                     DoneSomething;
> +    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
> +    ULONG                   Cpu;
> +    BOOLEAN                 DoneSomething;
> +
> +    UNREFERENCED_PARAMETER(InterruptObject);
> +
> +    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
> +    Cpu = KeGetCurrentProcessorNumber();
> 
>      DoneSomething = FALSE;
> 
>      while (XENBUS_SHARED_INFO(UpcallPending,
>                                &Context->SharedInfoInterface,
> -                              0))
> +                              Cpu))
>          DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
>                                             &Context->EvtchnAbi,
> -                                           0,
> +                                           Cpu,
>                                             EvtchnPollCallback,
>                                             Context);
> 
> @@ -857,8 +871,6 @@ EvtchnAcquire(
> 
>      Trace("====>\n");
> 
> -    Context->Vector = FdoGetInterruptVector(Fdo);
> -
>      status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
>      if (!NT_SUCCESS(status))
>          goto fail1;
> @@ -902,6 +914,15 @@ EvtchnAcquire(
>      if (!NT_SUCCESS(status))
>          goto fail7;
> 
> +    status = FdoAllocateInterrupt(Fdo,
> +                                  LevelSensitive,
> +                                  0,
> +                                  EvtchnInterruptCallback,
> +                                  Context,
> +                                  &Context->Interrupt);
> +    if (!NT_SUCCESS(status))
> +        goto fail8;
> +
>      Trace("<====\n");
> 
>  done:
> @@ -909,6 +930,11 @@ done:
> 
>      return STATUS_SUCCESS;
> 
> +fail8:
> +    Error("fail8\n");
> +
> +    EvtchnAbiRelease(Context);
> +
>  fail7:
>      Error("fail7\n");
> 
> @@ -948,8 +974,6 @@ fail2:
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Context->Vector = 0;
> -
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -978,6 +1002,9 @@ EvtchnRelease(
>      if (!IsListEmpty(&Context->List))
>          BUG("OUTSTANDING EVENT CHANNELS");
> 
> +    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
> +    Context->Interrupt = NULL;
> +
>      EvtchnAbiRelease(Context);
> 
>      XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
> @@ -1001,8 +1028,6 @@ EvtchnRelease(
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Context->Vector = 0;
> -
>      Trace("<====\n");
> 
>  done:
> diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
> index 215c997..cc0c775 100644
> --- a/src/xenbus/fdo.c
> +++ b/src/xenbus/fdo.c
> @@ -45,6 +45,7 @@
>  #include "fdo.h"
>  #include "pdo.h"
>  #include "thread.h"
> +#include "high.h"
>  #include "mutex.h"
>  #include "shared_info.h"
>  #include "evtchn.h"
> @@ -64,16 +65,17 @@
> 
>  #define MAXNAMELEN  128
> 
> -typedef enum _XENBUS_RESOURCE_TYPE {
> -    MEMORY_RESOURCE = 0,
> -    INTERRUPT_RESOURCE,
> -    RESOURCE_COUNT
> -} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
> -
> -typedef struct _XENBUS_RESOURCE {
> -    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
> -    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> -} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
> +struct _XENBUS_INTERRUPT {
> +    PXENBUS_FDO         Fdo;
> +    LIST_ENTRY          ListEntry;
> +    KINTERRUPT_MODE     InterruptMode;
> +    PKINTERRUPT         InterruptObject;
> +    ULONG               Cpu;
> +    UCHAR               Vector;
> +    ULONG               Line;
> +    PKSERVICE_ROUTINE   Callback;
> +    PVOID               Argument;
> +};
> 
>  struct _XENBUS_FDO {
>      PXENBUS_DX                      Dx;
> @@ -108,8 +110,8 @@ struct _XENBUS_FDO {
>      PXENBUS_STORE_WATCH             BalloonWatch;
>      MUTEX                           BalloonSuspendMutex;
> 
> -    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
> -    PKINTERRUPT                     InterruptObject;
> +    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
> +    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
> 
>      PXENBUS_SUSPEND_CONTEXT         SuspendContext;
>      PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
> @@ -129,9 +131,11 @@ struct _XENBUS_FDO {
>      XENBUS_BALLOON_INTERFACE        BalloonInterface;
>      XENFILT_UNPLUG_INTERFACE        UnplugInterface;
> 
> +    PXENBUS_RANGE_SET               RangeSet;
> +    LIST_ENTRY                      List;
> +
>      PXENBUS_EVTCHN_CHANNEL          Channel;
>      PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
> -    PXENBUS_RANGE_SET               RangeSet;
>  };
> 
>  static FORCEINLINE PVOID
> @@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
>      return Dx->DevicePnpState;
>  }
> 
> +static FORCEINLINE DEVICE_PNP_STATE
> +__FdoGetPreviousDevicePnpState(
> +    IN  PXENBUS_FDO Fdo
> +    )
> +{
> +    PXENBUS_DX      Dx = Fdo->Dx;
> +
> +    return Dx->PreviousDevicePnpState;
> +}
> +
>  static FORCEINLINE VOID
>  __FdoSetDevicePowerState(
>      IN  PXENBUS_FDO         Fdo,
> @@ -1383,219 +1397,595 @@ loop:
>  }
> 
>  static VOID
> -FdoParseResources(
> +FdoDumpIoResourceDescriptor(
>      IN  PXENBUS_FDO             Fdo,
> -    IN  PCM_RESOURCE_LIST       RawResourceList,
> -    IN  PCM_RESOURCE_LIST       TranslatedResourceList
> +    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
>      )
>  {
> -    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
> -    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
> -    ULONG                       Index;
> +    Trace("%s: %s\n",
> +          __FdoGetName(Fdo),
> +          ResourceDescriptorTypeName(Descriptor->Type));
> +
> +    if (Descriptor->Option == 0)
> +        Trace("Required\n");
> +    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
> +        Trace("Alternative\n");
> +    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
> +        Trace("Preferred\n");
> +    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE |
> IO_RESOURCE_PREFERRED))
> +        Trace("Preferred Alternative\n");
> +
> +    Trace("ShareDisposition=%s Flags=%04x\n",
> +          ResourceDescriptorShareDispositionName(Descriptor-
> >ShareDisposition),
> +          Descriptor->Flags);
> +
> +    switch (Descriptor->Type) {
> +    case CmResourceTypeMemory:
> +        Trace("Length = %08x Alignment = %08x\n MinimumAddress =
> %08x.%08x MaximumAddress = %08x.%08x\n",
> +              Descriptor->u.Memory.Length,
> +              Descriptor->u.Memory.Alignment,
> +              Descriptor->u.Memory.MinimumAddress.HighPart,
> +              Descriptor->u.Memory.MinimumAddress.LowPart,
> +              Descriptor->u.Memory.MaximumAddress.HighPart,
> +              Descriptor->u.Memory.MaximumAddress.LowPart);
> +        break;
> 
> -    ASSERT3U(RawResourceList->Count, ==, 1);
> -    RawPartialList = &RawResourceList->List[0].PartialResourceList;
> +    case CmResourceTypeInterrupt:
> +        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s
> PriorityPolicy=%s TargettedProcessors = %p\n",
> +              Descriptor->u.Interrupt.MinimumVector,
> +              Descriptor->u.Interrupt.MaximumVector,
> +              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
> +              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
> +              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
> +        break;
> 
> -    ASSERT3U(RawPartialList->Version, ==, 1);
> -    ASSERT3U(RawPartialList->Revision, ==, 1);
> +    default:
> +        break;
> +    }
> +}
> 
> -    ASSERT3U(TranslatedResourceList->Count, ==, 1);
> -    TranslatedPartialList = &TranslatedResourceList-
> >List[0].PartialResourceList;
> +static VOID
> +FdoDumpIoResourceList(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PIO_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                   Index;
> 
> -    ASSERT3U(TranslatedPartialList->Version, ==, 1);
> -    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
> 
> -    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
> -        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
> -        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
> +        Trace("%s: %d\n",
> +              __FdoGetName(Fdo),
> +              Index);
> 
> -        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
> -        TranslatedPartialDescriptor = &TranslatedPartialList-
> >PartialDescriptors[Index];
> +        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
> +    }
> +}
> 
> -        Trace("%s: [%d] %02x:%s\n",
> -              __FdoGetName(Fdo),
> -              Index,
> -              TranslatedPartialDescriptor->Type,
> -              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor-
> >Type));
> -
> -        switch (TranslatedPartialDescriptor->Type) {
> -        case CmResourceTypeMemory:
> -            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x
> Length = %08x\n",
> -                  RawPartialDescriptor->ShareDisposition,
> -                  RawPartialDescriptor->Flags,
> -                  RawPartialDescriptor->u.Memory.Start.HighPart,
> -                  RawPartialDescriptor->u.Memory.Start.LowPart,
> -                  RawPartialDescriptor->u.Memory.Length);
> -
> -            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start =
> %08x.%08x Length = %08x\n",
> -                  TranslatedPartialDescriptor->ShareDisposition,
> -                  TranslatedPartialDescriptor->Flags,
> -                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
> -                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
> -                  TranslatedPartialDescriptor->u.Memory.Length);
> -
> -            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
> -            Fdo->Resource[MEMORY_RESOURCE].Translated =
> *TranslatedPartialDescriptor;
> +static NTSTATUS
> +FdoFilterResourceRequirements(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PIRP                        Irp
> +    )
> +{
> +    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
> +    ULONG                           Size;
> +    PIO_RESOURCE_REQUIREMENTS_LIST  New;
> +    IO_RESOURCE_DESCRIPTOR          Interrupt;
> +    PIO_RESOURCE_LIST               List;
> +    ULONG                           Index;
> +    NTSTATUS                        status;
> 
> -            break;
> +    status = FdoForwardIrpSynchronously(Fdo, Irp);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> 
> -        case CmResourceTypeInterrupt:
> -            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector
> = %08x Affinity = %p\n",
> -                  RawPartialDescriptor->ShareDisposition,
> -                  RawPartialDescriptor->Flags,
> -                  RawPartialDescriptor->u.Interrupt.Level,
> -                  RawPartialDescriptor->u.Interrupt.Vector,
> -                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
> +    if (!__FdoIsActive(Fdo))
> +        goto not_active;
> 
> -            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level =
> %08x Vector = %08x Affinity = %p\n",
> -                  TranslatedPartialDescriptor->ShareDisposition,
> -                  TranslatedPartialDescriptor->Flags,
> -                  TranslatedPartialDescriptor->u.Interrupt.Level,
> -                  TranslatedPartialDescriptor->u.Interrupt.Vector,
> -                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
> +    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
> +    ASSERT3U(Old->AlternativeLists, ==, 1);
> 
> -            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
> -            Fdo->Resource[INTERRUPT_RESOURCE].Translated =
> *TranslatedPartialDescriptor;
> +    Size = Old->ListSize +
> +        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
> 
> -            break;
> +    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
> 
> -        default:
> -            break;
> +    status = STATUS_NO_MEMORY;
> +    if (New == NULL)
> +        goto fail2;
> +
> +    RtlCopyMemory(New, Old, Old->ListSize);
> +    New->ListSize = Size;
> +
> +    List = &New->List[0];
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
> +
> +        if (Descriptor->Type != CmResourceTypeInterrupt)
> +            continue;
> +
> +        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
> +        Descriptor->u.Interrupt.AffinityPolicy = 
> IrqPolicySpecifiedProcessors;
> +        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
> +    }
> +
> +    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
> +    Interrupt.Option = 0; // Required
> +    Interrupt.Type = CmResourceTypeInterrupt;
> +    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
> +    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
> +                      CM_RESOURCE_INTERRUPT_MESSAGE |
> +                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
> +
> +    Interrupt.u.Interrupt.MinimumVector =
> CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
> +    Interrupt.u.Interrupt.MaximumVector =
> CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
> +    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
> +    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
> +
> +    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
> +        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
> +        List->Descriptors[List->Count++] = Interrupt;
> +    }
> +
> +    FdoDumpIoResourceList(Fdo, List);
> +
> +    Irp->IoStatus.Information = (ULONG_PTR)New;
> +    status = STATUS_SUCCESS;
> +
> +    ExFreePool(Old);
> +
> +not_active:
> +    status = Irp->IoStatus.Status;
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +
> +    return status;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    Irp->IoStatus.Status = status;
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +
> +    return status;
> +}
> +
> +static VOID
> +FdoDumpCmPartialResourceDescriptor(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  BOOLEAN                         Translated,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
> +    )
> +{
> +    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          ResourceDescriptorTypeName(Descriptor->Type),
> +          ResourceDescriptorShareDispositionName(Descriptor-
> >ShareDisposition),
> +          Descriptor->Flags);
> +
> +    switch (Descriptor->Type) {
> +    case CmResourceTypeMemory:
> +        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
> +              __FdoGetName(Fdo),
> +              (Translated) ? "TRANSLATED" : "RAW",
> +              Descriptor->u.Memory.Start.HighPart,
> +              Descriptor->u.Memory.Start.LowPart,
> +              Descriptor->u.Memory.Length);
> +        break;
> +
> +    case CmResourceTypeInterrupt:
> +        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
> +            if (Translated)
> +                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity =
> %p\n",
> +                      __FdoGetName(Fdo),
> +                      Descriptor->u.MessageInterrupt.Translated.Level,
> +                      Descriptor->u.MessageInterrupt.Translated.Vector,
> +                      
> (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
> +            else
> +                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity =
> %p\n",
> +                      __FdoGetName(Fdo),
> +                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
> +                      Descriptor->u.MessageInterrupt.Raw.Vector,
> +                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
> +        } else {
> +            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
> +                  __FdoGetName(Fdo),
> +                  (Translated) ? "TRANSLATED" : "RAW",
> +                  Descriptor->u.Interrupt.Level,
> +                  Descriptor->u.Interrupt.Vector,
> +                  (PVOID)Descriptor->u.Interrupt.Affinity);
>          }
> +        break;
> +    default:
> +        break;
>      }
> +}
> 
> -    Trace("<====\n");
> +static VOID
> +FdoDumpCmPartialResourceList(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  BOOLEAN                     Translated,
> +    IN  PCM_PARTIAL_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                           Index;
> +
> +    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          List->Version,
> +          List->Revision,
> +          List->Count);
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List-
> >PartialDescriptors[Index];
> +
> +        Trace("%s: %s: %d\n",
> +              __FdoGetName(Fdo),
> +              (Translated) ? "TRANSLATED" : "RAW",
> +              Index);
> +
> +        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
> +    }
>  }
> 
> -static FORCEINLINE PXENBUS_RESOURCE
> -__FdoGetResource(
> -    IN  PXENBUS_FDO             Fdo,
> -    IN  XENBUS_RESOURCE_TYPE    Type
> +static VOID
> +FdoDumpCmFullResourceDescriptor(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  BOOLEAN                         Translated,
> +    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
>      )
>  {
> -    ASSERT3U(Type, <, RESOURCE_COUNT);
> +    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          InterfaceTypeName(Descriptor->InterfaceType),
> +          Descriptor->BusNumber);
> 
> -    return &Fdo->Resource[Type];
> +    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor-
> >PartialResourceList);
> +}
> +
> +static VOID
> +FdoDumpCmResourceList(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  BOOLEAN             Translated,
> +    IN  PCM_RESOURCE_LIST   List
> +    )
> +{
> +    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
> +}
> +
> +_IRQL_requires_max_(HIGH_LEVEL)
> +_IRQL_saves_
> +_IRQL_raises_(HIGH_LEVEL)
> +KIRQL
> +FdoAcquireInterruptLock(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
> +}
> +
> +_IRQL_requires_(HIGH_LEVEL)
> +VOID
> +FdoReleaseInterruptLock(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PXENBUS_INTERRUPT           Interrupt,
> +    IN  __drv_restoresIRQL KIRQL    Irql
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
>  }
> 
>  static
>  _Function_class_(KSERVICE_ROUTINE)
> -_IRQL_requires_(HIGH_LEVEL)
> -_IRQL_requires_same_
> +__drv_requiresIRQL(HIGH_LEVEL)
>  BOOLEAN
> -FdoInterrupt(
> +FdoInterruptCallback(
>      IN  PKINTERRUPT             InterruptObject,
>      IN  PVOID                   Context
>      )
>  {
> -    PXENBUS_FDO                 Fdo = Context;
> +    PXENBUS_INTERRUPT           Interrupt = Context;
> 
> -    UNREFERENCED_PARAMETER(InterruptObject);
> +    if (Interrupt->Callback == NULL)
> +        return FALSE;
> 
> -    ASSERT(Fdo != NULL);
> -
> -    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
> +    return Interrupt->Callback(InterruptObject,
> +                               Interrupt->Argument);
>  }
> 
>  static NTSTATUS
>  FdoConnectInterrupt(
> -    IN  PXENBUS_FDO                 Fdo
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
> +    OUT PXENBUS_INTERRUPT               *Interrupt
>      )
>  {
> -    PXENBUS_RESOURCE                Interrupt;
> -    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
> -    NTSTATUS                        status;
> +    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
> +    ULONG                               Cpu;
> +    NTSTATUS                            status;
> 
>      Trace("====>\n");
> 
> -    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
> +    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (*Interrupt == NULL)
> +        goto fail1;
> +
> +    (*Interrupt)->Fdo = Fdo;
> +    (*Interrupt)->InterruptMode = (Translated->Flags &
> CM_RESOURCE_INTERRUPT_LATCHED) ?
> +                                  Latched :
> +                                  LevelSensitive;
> +
> +    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
> +        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
> 
>      RtlZeroMemory(&Connect, sizeof
> (IO_CONNECT_INTERRUPT_PARAMETERS));
>      Connect.Version = CONNECT_FULLY_SPECIFIED;
>      Connect.FullySpecified.PhysicalDeviceObject =
> __FdoGetPhysicalDeviceObject(Fdo);
> -    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt-
> >Translated.u.Interrupt.Level;
> -    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt-
> >Translated.ShareDisposition == CmResourceShareShared);
> -    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
> -    Connect.FullySpecified.Irql = (KIRQL)Interrupt-
> >Translated.u.Interrupt.Level;
> -    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags &
> CM_RESOURCE_INTERRUPT_LATCHED) ?
> -                                           Latched :
> -                                           LevelSensitive;
> -    Connect.FullySpecified.ProcessorEnableMask = Interrupt-
> >Translated.u.Interrupt.Affinity;
> -    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
> -    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
> -    Connect.FullySpecified.ServiceContext = Fdo;
> +    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated-
> >ShareDisposition == CmResourceShareShared);
> +    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
> +    Connect.FullySpecified.InterruptObject = &(*Interrupt)-
> >InterruptObject;
> +    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
> +    Connect.FullySpecified.ServiceContext = *Interrupt;
> +
> +    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
> +        Connect.FullySpecified.Vector = Translated-
> >u.MessageInterrupt.Translated.Vector;
> +        Connect.FullySpecified.Irql = (KIRQL)Translated-
> >u.MessageInterrupt.Translated.Level;
> +        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated-
> >u.MessageInterrupt.Translated.Level;
> +        Connect.FullySpecified.ProcessorEnableMask = Translated-
> >u.MessageInterrupt.Translated.Affinity;
> +    } else {
> +        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
> +        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
> +        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated-
> >u.Interrupt.Level;
> +        Connect.FullySpecified.ProcessorEnableMask = Translated-
> >u.Interrupt.Affinity;
> +    }
> 
>      status = IoConnectInterruptEx(&Connect);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> +
> +    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
> +
> +#if defined(__i386__)
> +    (VOID)_BitScanReverse(&Cpu,
> Connect.FullySpecified.ProcessorEnableMask);
> +#elif defined(__x86_64__)
> +    (VOID)_BitScanReverse64(&Cpu,
> Connect.FullySpecified.ProcessorEnableMask);
> +#else
> +#error 'Unrecognised architecture'
> +#endif
> +
> +    (*Interrupt)->Cpu = Cpu;
> +
> +    Info("%p: %s %s CPU %u VECTOR %02x\n",
> +         (*Interrupt)->InterruptObject,
> +         ResourceDescriptorShareDispositionName(Translated-
> >ShareDisposition),
> +         InterruptModeName((*Interrupt)->InterruptMode),
> +         (*Interrupt)->Cpu,
> +         (*Interrupt)->Vector);
> 
>      Trace("<====\n");
> 
>      return STATUS_SUCCESS;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    __FdoFree(*Interrupt);
> +    *Interrupt = NULL;
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
>      return status;
>  }
> 
> -_IRQL_requires_max_(HIGH_LEVEL)
> -_IRQL_saves_
> -_IRQL_raises_(HIGH_LEVEL)
> -KIRQL
> -FdoAcquireInterruptLock(
> -    IN  PXENBUS_FDO Fdo
> +static VOID
> +FdoDisconnectInterrupt(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  PXENBUS_INTERRUPT               Interrupt
>      )
>  {
> -    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
> +    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
> +
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    Trace("====>\n");
> +
> +    Info("%p: CPU %u VECTOR %02x\n",
> +         Interrupt->InterruptObject,
> +         Interrupt->Cpu,
> +         Interrupt->Vector);
> +
> +    Interrupt->Cpu = 0;
> +    Interrupt->Vector = 0;
> +
> +    RtlZeroMemory(&Disconnect, sizeof
> (IO_DISCONNECT_INTERRUPT_PARAMETERS));
> +    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
> +    Disconnect.ConnectionContext.InterruptObject = Interrupt-
> >InterruptObject;
> 
> -    return KeAcquireInterruptSpinLock(InterruptObject);
> +    IoDisconnectInterruptEx(&Disconnect);
> +
> +    Interrupt->Line = 0;
> +    Interrupt->InterruptObject = NULL;
> +    Interrupt->InterruptMode = 0;
> +    Interrupt->Fdo = NULL;
> +
> +    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
> +    __FdoFree(Interrupt);
> +
> +    Trace("<====\n");
>  }
> -
> -_IRQL_requires_(HIGH_LEVEL)
> -VOID
> -FdoReleaseInterruptLock(
> -    IN  PXENBUS_FDO                 Fdo,
> -    IN  __drv_restoresIRQL KIRQL    Irql
> +
> +static NTSTATUS
> +FdoCreateInterrupt(
> +    IN  PXENBUS_FDO     Fdo
>      )
>  {
> -    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
> +    ULONG               Index;
> +    PXENBUS_INTERRUPT   Interrupt;
> +    NTSTATUS            status;
> +
> +    InitializeListHead(&Fdo->List);
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo-
> >RawResourceList->PartialDescriptors[Index];
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo-
> >TranslatedResourceList->PartialDescriptors[Index];
> +
> +        if (Translated->Type != CmResourceTypeInterrupt)
> +            continue;
> +
> +        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
> +
> +        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    while (!IsListEmpty(&Fdo->List)) {
> +        PLIST_ENTRY ListEntry;
> +
> +        ListEntry = RemoveHeadList(&Fdo->List);
> +        ASSERT(ListEntry != &Fdo->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> +
> +        FdoDisconnectInterrupt(Fdo, Interrupt);
> +    }
> +
> +    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
> 
> -    KeReleaseInterruptSpinLock(InterruptObject, Irql);
> +    return status;
>  }
> 
> -ULONG
> +NTSTATUS
> +FdoAllocateInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  KINTERRUPT_MODE     InterruptMode,
> +    IN  ULONG               Cpu,
> +    IN  KSERVICE_ROUTINE    Callback,
> +    IN  PVOID               Argument OPTIONAL,
> +    OUT PXENBUS_INTERRUPT   *Interrupt
> +    )
> +{
> +    PLIST_ENTRY             ListEntry;
> +    KIRQL                   Irql;
> +    NTSTATUS                status;
> +
> +    for (ListEntry = Fdo->List.Flink;
> +         ListEntry != &Fdo->List;
> +         ListEntry = ListEntry->Flink) {
> +        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> +
> +        if ((*Interrupt)->Callback == NULL &&
> +            (*Interrupt)->InterruptMode == InterruptMode &&
> +            (*Interrupt)->Cpu == Cpu)
> +            goto found;
> +    }
> +
> +    *Interrupt = NULL;
> +
> +    status = STATUS_OBJECT_NAME_NOT_FOUND;
> +    goto fail1;
> +
> +found:
> +    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
> +    (*Interrupt)->Callback = Callback;
> +    (*Interrupt)->Argument = Argument;
> +    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +UCHAR
>  FdoGetInterruptVector(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return Interrupt->Vector;
> +}
> +
> +ULONG
> +FdoGetInterruptLine(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
>      )
>  {
> -    PXENBUS_RESOURCE    Interrupt;
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return Interrupt->Line;
> +}
> 
> -    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
> +VOID
> +FdoFreeInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    KIRQL                   Irql;
> 
> -    return Interrupt->Raw.u.Interrupt.Vector;
> +    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
> +    Interrupt->Callback = NULL;
> +    Interrupt->Argument = NULL;
> +    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
>  }
> 
>  static VOID
> -FdoDisconnectInterrupt(
> -    IN  PXENBUS_FDO                     Fdo
> +FdoDestroyInterrupt(
> +    IN  PXENBUS_FDO     Fdo
>      )
>  {
> -    PKINTERRUPT                         InterruptObject;
> -    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
> +    while (!IsListEmpty(&Fdo->List)) {
> +        PLIST_ENTRY         ListEntry;
> +        PXENBUS_INTERRUPT   Interrupt;
> 
> -    Trace("====>\n");
> +        ListEntry = RemoveHeadList(&Fdo->List);
> +        ASSERT(ListEntry != &Fdo->List);
> 
> -    InterruptObject = Fdo->InterruptObject;
> -    Fdo->InterruptObject = NULL;
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> 
> -    RtlZeroMemory(&Disconnect, sizeof
> (IO_DISCONNECT_INTERRUPT_PARAMETERS));
> -    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
> -    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
> +        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> 
> -    IoDisconnectInterruptEx(&Disconnect);
> +#pragma warning(push)
> +#pragma warning(disable:4054)   // 'type cast' : from function pointer to
> data pointer
> +        ASSERT3P(Interrupt->Callback, ==, NULL);
> +#pragma warning(pop)
> 
> -    Trace("<====\n");
> +        ASSERT3P(Interrupt->Argument, ==, NULL);
> +
> +        FdoDisconnectInterrupt(Fdo, Interrupt);
> +    }
> +
> +    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
>  }
> 
>  static
> @@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
> 
>  static NTSTATUS
>  FdoCreateIoSpace(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO                 Fdo
>      )
>  {
> -    PXENBUS_RESOURCE    Memory;
> -    NTSTATUS            status;
> +    ULONG                           Index;
> +    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> +    PHYSICAL_ADDRESS                End;
> +    NTSTATUS                        status;
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
> 
> -    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
> +        if (Translated->Type == CmResourceTypeMemory)
> +            goto found;
> +    }
> +
> +    status = STATUS_OBJECT_NAME_NOT_FOUND;
> +    goto fail1;
> 
> +found:
>      status = XENBUS_RANGE_SET(Create,
>                                &Fdo->RangeSetInterface,
>                                "io_space",
>                                &Fdo->RangeSet);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> 
>      status = XENBUS_RANGE_SET(Put,
>                                &Fdo->RangeSetInterface,
>                                Fdo->RangeSet,
> -                              Memory->Translated.u.Memory.Start.QuadPart,
> -                              Memory->Translated.u.Memory.Length);
> +                              Translated->u.Memory.Start.QuadPart,
> +                              Translated->u.Memory.Length);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail3;
> +
> +    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated-
> >u.Memory.Length - 1;
> +
> +    Info("%08x.%08x - %08x.%08x\n",
> +         Translated->u.Memory.Start.HighPart,
> +         Translated->u.Memory.Start.LowPart,
> +         End.HighPart,
> +         End.LowPart);
> 
>      return STATUS_SUCCESS;
> 
> -fail2:
> -    Error("fail2\n");
> +fail3:
> +    Error("fail3\n");
> 
>      XENBUS_RANGE_SET(Destroy,
>                       &Fdo->RangeSetInterface,
>                       Fdo->RangeSet);
>      Fdo->RangeSet = NULL;
> 
> +fail2:
> +    Error("fail2\n");
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
> 
>  static VOID
>  FdoDestroyIoSpace(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO                 Fdo
>      )
>  {
> -    PXENBUS_RESOURCE    Memory;
> -    NTSTATUS            status;
> +    ULONG                           Index;
> +    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> +    NTSTATUS                        status;
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
> 
> -    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
> +        if (Translated->Type == CmResourceTypeMemory)
> +            goto found;
> +    }
> +
> +    ASSERT(FALSE);
> +    return;
> 
> +found:
>      status = XENBUS_RANGE_SET(Get,
>                                &Fdo->RangeSetInterface,
>                                Fdo->RangeSet,
> -                              Memory->Translated.u.Memory.Start.QuadPart,
> -                              Memory->Translated.u.Memory.Length);
> +                              Translated->u.Memory.Start.QuadPart,
> +                              Translated->u.Memory.Length);
>      ASSERT(NT_SUCCESS(status));
> 
>      XENBUS_RANGE_SET(Destroy,
> @@ -2214,39 +2636,111 @@ FdoS3ToS4(
>      Trace("<====\n");
>  }
> 
> +static VOID
> +FdoFilterCmPartialResourceList(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PCM_PARTIAL_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                           Index;
> +
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List-
> >PartialDescriptors[Index];
> +
> +        //
> +        // These are additional resources that XENBUS requested, so they must
> +        // be filtered out before the underlying PCI bus driver sees them.
> Happily
> +        // it appears that swapping the type to DevicePrivate causes PCI.SYS 
> to
> ignore
> +        // them.
> +        //
> +        if (Descriptor->Type == CmResourceTypeInterrupt &&
> +            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
> +            Descriptor->Type = CmResourceTypeDevicePrivate;
> +    }
> +}
> +
>  static NTSTATUS
>  FdoStartDevice(
> -    IN  PXENBUS_FDO     Fdo,
> -    IN  PIRP            Irp
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PIRP                        Irp
>      )
>  {
> -    PIO_STACK_LOCATION  StackLocation;
> -    NTSTATUS            status;
> +    PIO_STACK_LOCATION              StackLocation;
> +    PCM_RESOURCE_LIST               ResourceList;
> +    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
> +    ULONG                           Size;
> +    NTSTATUS                        status;
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> 
> -    status = FdoForwardIrpSynchronously(Fdo, Irp);
> -    if (!NT_SUCCESS(status))
> +    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +
> +    // Raw
> +
> +    ResourceList = StackLocation-
> >Parameters.StartDevice.AllocatedResources;
> +    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
> +
> +    ASSERT3U(ResourceList->Count, ==, 1);
> +    Descriptor = &ResourceList->List[0];
> +
> +    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
> +    ASSERT3U(Descriptor->BusNumber, ==, 0);
> +
> +    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
> +           (Descriptor->PartialResourceList.Count) * sizeof
> (CM_PARTIAL_RESOURCE_DESCRIPTOR);
> +
> +    Fdo->RawResourceList = __FdoAllocate(Size);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Fdo->RawResourceList == NULL)
>          goto fail1;
> 
> -    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +    RtlCopyMemory(Fdo->RawResourceList, &Descriptor-
> >PartialResourceList, Size);
> +
> +    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
> +
> +    // Translated
> +
> +    ResourceList = StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated;
> +    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
> +
> +    ASSERT3U(ResourceList->Count, ==, 1);
> +    Descriptor = &ResourceList->List[0];
> +
> +    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
> +    ASSERT3U(Descriptor->BusNumber, ==, 0);
> +
> +    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
> +           (Descriptor->PartialResourceList.Count) * sizeof
> (CM_PARTIAL_RESOURCE_DESCRIPTOR);
> +
> +    Fdo->TranslatedResourceList = __FdoAllocate(Size);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Fdo->TranslatedResourceList == NULL)
> +        goto fail2;
> +
> +    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor-
> >PartialResourceList, Size);
> +
> +    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
> 
> -    FdoParseResources(Fdo,
> -                      
> StackLocation->Parameters.StartDevice.AllocatedResources,
> -                      StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated);
> +    status = FdoForwardIrpSynchronously(Fdo, Irp);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> 
>      if (!__FdoIsActive(Fdo))
>          goto not_active;
> 
> -    status = FdoConnectInterrupt(Fdo);
> +    status = FdoCreateInterrupt(Fdo);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail4;
> 
>      KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
> 
>      status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
>      if (!NT_SUCCESS(status))
> -        goto fail3;
> +        goto fail5;
> 
>      InitializeMutex(&Fdo->BalloonSuspendMutex);
> 
> @@ -2254,20 +2748,20 @@ FdoStartDevice(
> 
>      status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
>      if (!NT_SUCCESS(status))
> -        goto fail4;
> +        goto fail6;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
> 
>          status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
>          if (!NT_SUCCESS(status))
> -            goto fail5;
> +            goto fail7;
>      }
> 
>  not_active:
>      status = FdoD3ToD0(Fdo);
>      if (!NT_SUCCESS(status))
> -        goto fail6;
> +        goto fail8;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          BOOLEAN Warned;
> @@ -2306,11 +2800,11 @@ not_active:
> 
>      return status;
> 
> -fail6:
> -    Error("fail6\n");
> +fail8:
> +    Error("fail8\n");
> 
>      if (!__FdoIsActive(Fdo))
> -        goto fail2;
> +        goto fail4;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          ThreadAlert(Fdo->BalloonThread);
> @@ -2318,8 +2812,8 @@ fail6:
>          Fdo->BalloonThread = NULL;
>      }
> 
> -fail5:
> -    Error("fail5\n");
> +fail7:
> +    Error("fail7\n");
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL)
>          RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
> @@ -2328,8 +2822,8 @@ fail5:
>      ThreadJoin(Fdo->SuspendThread);
>      Fdo->SuspendThread = NULL;
> 
> -fail4:
> -    Error("fail4\n");
> +fail6:
> +    Error("fail6\n");
> 
>      RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
> 
> @@ -2339,17 +2833,27 @@ fail4:
>      ThreadJoin(Fdo->ScanThread);
>      Fdo->ScanThread = NULL;
> 
> -fail3:
> -    Error("fail3\n");
> +fail5:
> +    Error("fail5\n");
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> +
> +fail4:
> +    Error("fail4\n");
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> 
>  fail2:
>      Error("fail2\n");
> 
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
>  fail1:
>      Error("fail1 (%08x)\n", status);
> @@ -2445,10 +2949,14 @@ FdoStopDevice(
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> 
>  not_active:
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> +
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
>      __FdoSetDevicePnpState(Fdo, Stopped);
>      Irp->IoStatus.Status = STATUS_SUCCESS;
> @@ -2554,6 +3062,9 @@ FdoRemoveDevice(
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> 
> +    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
> +        goto done;
> +
>      if (__FdoIsActive(Fdo)) {
>          Trace("waiting for scan thread...\n");
> 
> @@ -2621,11 +3132,16 @@ FdoRemoveDevice(
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> 
>  not_active:
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> +
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
> +done:
>      __FdoSetDevicePnpState(Fdo, Deleted);
> 
>      Irp->IoStatus.Status = STATUS_SUCCESS;
> @@ -2937,6 +3453,10 @@ FdoDispatchPnp(
>            PnpMinorFunctionName(MinorFunction));
> 
>      switch (StackLocation->MinorFunction) {
> +    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
> +        status = FdoFilterResourceRequirements(Fdo, Irp);
> +        break;
> +
>      case IRP_MN_START_DEVICE:
>          status = FdoStartDevice(Fdo, Irp);
>          break;
> diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
> index fdb6f79..4916be4 100644
> --- a/src/xenbus/fdo.h
> +++ b/src/xenbus/fdo.h
> @@ -38,6 +38,8 @@
>  #include "driver.h"
>  #include "types.h"
> 
> +typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT,
> *PXENBUS_INTERRUPT;
> +
>  extern NTSTATUS
>  FdoCreate(
>      IN  PDEVICE_OBJECT  PhysicalDeviceObject,
> @@ -140,11 +142,6 @@ FdoFreeIoSpace(
>      IN  ULONG               Size
>      );
> 
> -extern ULONG
> -FdoGetInterruptVector(
> -    IN  PXENBUS_FDO Fdo
> -    );
> -
>  // Disable erroneous SAL warnings around use of interrupt locks
>  #pragma warning(disable:28230)
>  #pragma warning(disable:28285)
> @@ -155,7 +152,8 @@ _IRQL_saves_
>  _IRQL_raises_(HIGH_LEVEL)
>  KIRQL
>  FdoAcquireInterruptLock(
> -    IN  PXENBUS_FDO Fdo
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
>      );
> 
>  extern
> @@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
>  VOID
>  FdoReleaseInterruptLock(
>      IN  PXENBUS_FDO                 Fdo,
> +    IN  PXENBUS_INTERRUPT           Interrupt,
>      IN  __drv_restoresIRQL KIRQL    Irql
>      );
> 
> +extern NTSTATUS
> +FdoAllocateInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  KINTERRUPT_MODE     InterruptMode,
> +    IN  ULONG               Cpu,
> +    IN  KSERVICE_ROUTINE    Callback,
> +    IN  PVOID               Argument OPTIONAL,
> +    OUT PXENBUS_INTERRUPT   *Interrupt
> +    );
> +
> +extern UCHAR
> +FdoGetInterruptVector(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
> +extern ULONG
> +FdoGetInterruptLine(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
> +extern VOID
> +FdoFreeInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
>  #include "suspend.h"
> 
>  extern PXENBUS_SUSPEND_CONTEXT
> diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
> index 650e84d..ad0d4de 100644
> --- a/src/xenbus/pdo.c
> +++ b/src/xenbus/pdo.c
> @@ -682,7 +682,7 @@ PdoParseResources(
>                __PdoGetName(Pdo),
>                Index,
>                TranslatedPartialDescriptor->Type,
> -              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor-
> >Type));
> +              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
> 
>          switch (TranslatedPartialDescriptor->Type) {
>          case CmResourceTypeMemory:
> --
> 2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

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