...
);
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND_V2)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_EVTCHN_CHANNEL Channel,
+ IN ULONG Cpu
+ );
+
/*! \typedef XENBUS_EVTCHN_BIND
\brief Bind an event channel to a specific CPU
\param Interface The interface header
\param Channel The channel handle
- \param Cpu The CPU that should handle events
+ \param Group The group number of the CPU that should handle events
+ \param Number The relative number of the CPU that should handle events
*/
typedef NTSTATUS
(*XENBUS_EVTCHN_BIND)(
IN PINTERFACE Interface,
IN PXENBUS_EVTCHN_CHANNEL Channel,
- IN ULONG Cpu
+ IN USHORT Group,
+ IN UCHAR Number
);
typedef BOOLEAN
XENBUS_EVTCHN_ACQUIRE EvtchnAcquire;
XENBUS_EVTCHN_RELEASE EvtchnRelease;
XENBUS_EVTCHN_OPEN EvtchnOpen;
- XENBUS_EVTCHN_BIND EvtchnBind;
+ XENBUS_EVTCHN_BIND_V2 EvtchnBindVersion2;
XENBUS_EVTCHN_UNMASK_V1 EvtchnUnmaskVersion1;
XENBUS_EVTCHN_SEND EvtchnSend;
XENBUS_EVTCHN_TRIGGER EvtchnTrigger;
\ingroup interfaces
*/
struct _XENBUS_EVTCHN_INTERFACE_V3 {
+ INTERFACE Interface;
+ XENBUS_EVTCHN_ACQUIRE EvtchnAcquire;
+ XENBUS_EVTCHN_RELEASE EvtchnRelease;
+ XENBUS_EVTCHN_OPEN EvtchnOpen;
+ XENBUS_EVTCHN_BIND_V2 EvtchnBindVersion2;
+ XENBUS_EVTCHN_UNMASK EvtchnUnmask;
+ XENBUS_EVTCHN_SEND EvtchnSend;
+ XENBUS_EVTCHN_TRIGGER EvtchnTrigger;
+ XENBUS_EVTCHN_GET_PORT EvtchnGetPort;
+ XENBUS_EVTCHN_CLOSE EvtchnClose;
+};
+
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V4
+ \brief EVTCHN interface version 4
+ \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V4 {
INTERFACE Interface;
XENBUS_EVTCHN_ACQUIRE EvtchnAcquire;
XENBUS_EVTCHN_RELEASE EvtchnRelease;
XENBUS_EVTCHN_CLOSE EvtchnClose;
};
-typedef struct _XENBUS_EVTCHN_INTERFACE_V3 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+typedef struct _XENBUS_EVTCHN_INTERFACE_V4 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
/*! \def XENBUS_EVTCHN
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 3
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 4
#endif // _XENBUS_EVTCHN_INTERFACE_H
typedef BOOLEAN
(*XENBUS_SHARED_INFO_UPCALL_PENDING)(
IN PINTERFACE Interface,
- IN ULONG Cpu
+ IN ULONG Index
);
typedef BOOLEAN
typedef BOOLEAN
(*XENBUS_SHARED_INFO_EVTCHN_POLL)(
IN PINTERFACE Interface,
- IN ULONG Cpu,
+ IN ULONG Index,
IN XENBUS_SHARED_INFO_EVENT Event,
IN PVOID Argument
);
#include <public/grant_table.h>
#include <public/sched.h>
#include <public/hvm/params.h>
+#include <public/hvm/hvm_info_table.h>
// xs_wire.h gates the definition of the xsd_errors enumeration
// on whether EINVAL is defined. Unfortunately EINVAL is actually
#define XEN_API __declspec(dllexport)
#include <ntddk.h>
+#include <procgrp.h>
#include <xen.h>
#include "hypercall.h"
UNREFERENCED_PARAMETER(RegistryPath);
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+ WdmlibProcgrpInitialize();
__DbgPrintEnable();
#define XEN_API __declspec(dllexport)
#include <ntddk.h>
+#include <procgrp.h>
#include <ntstrsafe.h>
#include <stdlib.h>
#include <stdarg.h>
#define XEN_SYSTEM_TAG 'TSYS'
-typedef struct _SYSTEM_CPU {
- ULONG Index;
+typedef struct _SYSTEM_PROCESSOR {
CHAR Manufacturer[13];
UCHAR ApicID;
UCHAR ProcessorID;
-} SYSTEM_CPU, *PSYSTEM_CPU;
+} SYSTEM_PROCESSOR, *PSYSTEM_PROCESSOR;
typedef struct _SYSTEM_CONTEXT {
- LONG References;
- PACPI_MADT Madt;
- PSYSTEM_CPU Cpu[MAXIMUM_PROCESSORS];
- PVOID PowerStateHandle;
- PVOID ProcessorChangeHandle;
+ LONG References;
+ PACPI_MADT Madt;
+ PSYSTEM_PROCESSOR Processor;
+ ULONG ProcessorCount;
+ PVOID PowerStateHandle;
+ PVOID ProcessorChangeHandle;
} SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
static SYSTEM_CONTEXT SystemContext;
_IRQL_requires_(DISPATCH_LEVEL)
_IRQL_requires_same_
VOID
-SystemCpuInformation(
- IN PKDPC Dpc,
- IN PVOID _Context,
- IN PVOID Argument1,
- IN PVOID Argument2
+SystemProcessorInformation(
+ IN PKDPC Dpc,
+ IN PVOID _Context,
+ IN PVOID Argument1,
+ IN PVOID Argument2
)
{
- PSYSTEM_CONTEXT Context = &SystemContext;
- PKEVENT Event = _Context;
- ULONG Index;
- PSYSTEM_CPU Cpu;
- ULONG EBX;
- ULONG ECX;
- ULONG EDX;
+ PSYSTEM_CONTEXT Context = &SystemContext;
+ PKEVENT Event = _Context;
+ ULONG Index;
+ PROCESSOR_NUMBER ProcNumber;
+ PSYSTEM_PROCESSOR Processor;
+ ULONG EBX;
+ ULONG ECX;
+ ULONG EDX;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Argument1);
UNREFERENCED_PARAMETER(Argument2);
- Index = KeGetCurrentProcessorNumber();
- Cpu = Context->Cpu[Index];
+ Index = KeGetCurrentProcessorNumberEx(&ProcNumber);
+ ASSERT3U(Index, <, Context->ProcessorCount);
- ASSERT(Cpu != NULL);
- ASSERT3U(Cpu->Index, ==, Index);
+ Processor = &Context->Processor[Index];
- Info("====> (%u)\n", Index);
+ Info("====> (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
__CpuId(0, NULL, &EBX, &ECX, &EDX);
- RtlCopyMemory(&Cpu->Manufacturer[0], &EBX, sizeof (ULONG));
- RtlCopyMemory(&Cpu->Manufacturer[4], &EDX, sizeof (ULONG));
- RtlCopyMemory(&Cpu->Manufacturer[8], &ECX, sizeof (ULONG));
+ RtlCopyMemory(&Processor->Manufacturer[0], &EBX, sizeof (ULONG));
+ RtlCopyMemory(&Processor->Manufacturer[4], &EDX, sizeof (ULONG));
+ RtlCopyMemory(&Processor->Manufacturer[8], &ECX, sizeof (ULONG));
__CpuId(1, NULL, &EBX, NULL, NULL);
- Cpu->ApicID = EBX >> 24;
- Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+ Processor->ApicID = EBX >> 24;
+ Processor->ProcessorID = SystemApicIDToProcessorID(Processor->ApicID);
- Info("Manufacturer: %s\n", Cpu->Manufacturer);
- Info("APIC ID: %02X\n", Cpu->ApicID);
- Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
+ Info("Manufacturer: %s\n", Processor->Manufacturer);
+ Info("APIC ID: %02X\n", Processor->ApicID);
+ Info("PROCESSOR ID: %02X\n", Processor->ProcessorID);
KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
- Info("<==== (%u)\n", Index);
+ Info("<==== (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
}
static
)
{
PSYSTEM_CONTEXT Context = &SystemContext;
+ PROCESSOR_NUMBER ProcNumber;
ULONG Index;
+ NTSTATUS status;
UNREFERENCED_PARAMETER(Argument);
Index = Change->NtNumber;
- Trace("====> (%u:%s)\n", Index, ProcessorChangeName(Change->State));
+
+ status = KeGetProcessorNumberFromIndex(Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ Trace("====> (%u:%u:%s)\n",
+ ProcNumber.Group,
+ ProcNumber.Number,
+ ProcessorChangeName(Change->State));
switch (Change->State) {
case KeProcessorAddStartNotify: {
- PSYSTEM_CPU Cpu;
+ PSYSTEM_PROCESSOR Processor;
+ ULONG ProcessorCount;
+
+ if (Index < Context->ProcessorCount)
+ break;
- Cpu = __SystemAllocate(sizeof (SYSTEM_CPU));
+ ProcessorCount = Index + 1;
+ Processor = __SystemAllocate(sizeof (SYSTEM_PROCESSOR) *
+ ProcessorCount);
- if (Cpu == NULL) {
+ if (Processor == NULL) {
*Status = STATUS_NO_MEMORY;
break;
}
- Cpu->Index = Index;
- ASSERT3P(Context->Cpu[Index], ==, NULL);
- Context->Cpu[Index] = Cpu;
+ if (Context->ProcessorCount != 0) {
+ RtlCopyMemory(Processor,
+ Context->Processor,
+ sizeof (SYSTEM_PROCESSOR) *
+ Context->ProcessorCount);
+ __SystemFree(Context->Processor);
+ }
+
+ Context->Processor = Processor;
+ Context->ProcessorCount = ProcessorCount;
break;
}
case KeProcessorAddCompleteNotify: {
- PSYSTEM_CPU Cpu = Context->Cpu[Index];
- KEVENT Event;
- KDPC Dpc;
+ KEVENT Event;
+ KDPC Dpc;
- ASSERT(Cpu != NULL);
- ASSERT3U(Cpu->Index, ==, Index);
+ ASSERT3U(Index, <, Context->ProcessorCount);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
- KeInitializeDpc(&Dpc, SystemCpuInformation, &Event);
+ KeInitializeDpc(&Dpc, SystemProcessorInformation, &Event);
KeSetImportanceDpc(&Dpc, HighImportance);
- KeSetTargetProcessorDpc(&Dpc, (CCHAR)Index);
+ KeSetTargetProcessorDpcEx(&Dpc, &ProcNumber);
KeInsertQueueDpc(&Dpc, NULL, NULL);
NULL);
break;
}
- case KeProcessorAddFailureNotify: {
- PSYSTEM_CPU Cpu = Context->Cpu[Index];
-
- ASSERT(Cpu != NULL);
- ASSERT3U(Cpu->Index, ==, Index);
-
- Context->Cpu[Index] = NULL;
- __SystemFree(Cpu);
-
+ default:
+ ASSERT(FALSE);
break;
}
- }
- Trace("<==== (%u:%s)\n", Index, ProcessorChangeName(Change->State));
+ Trace("<==== (%u:%u:%s)\n",
+ ProcNumber.Group,
+ ProcNumber.Number,
+ ProcessorChangeName(Change->State));
}
static NTSTATUS
)
{
PSYSTEM_CONTEXT Context = &SystemContext;
+ PVOID Handle;
NTSTATUS status;
- Context->ProcessorChangeHandle = KeRegisterProcessorChangeCallback(SystemProcessorChangeCallback,
- NULL,
- KE_PROCESSOR_CHANGE_ADD_EXISTING);
+ Handle = KeRegisterProcessorChangeCallback(SystemProcessorChangeCallback,
+ NULL,
+ KE_PROCESSOR_CHANGE_ADD_EXISTING);
status = STATUS_UNSUCCESSFUL;
- if (Context->ProcessorChangeHandle == NULL)
+ if (Handle == NULL)
goto fail1;
+ Context->ProcessorChangeHandle = Handle;
+
return STATUS_SUCCESS;
fail1:
)
{
PSYSTEM_CONTEXT Context = &SystemContext;
- ULONG Index;
KeDeregisterProcessorChangeCallback(Context->ProcessorChangeHandle);
Context->ProcessorChangeHandle = NULL;
- for (Index = 0; Index < MAXIMUM_PROCESSORS; Index++) {
- PSYSTEM_CPU Cpu = Context->Cpu[Index];
-
- if (Cpu == NULL)
- continue;
-
- Context->Cpu[Index] = NULL;
- __SystemFree(Cpu);
- }
-
- ASSERT(IsZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS));
+ __SystemFree(Context->Processor);
+ Context->ProcessorCount = 0;
}
static NTSTATUS
)
{
PSYSTEM_CONTEXT Context = &SystemContext;
- PSYSTEM_CPU Cpu = Context->Cpu[Index];
+ PSYSTEM_PROCESSOR Processor = &Context->Processor[Index];
- ASSERT(Cpu != NULL);
+ ASSERT3U(Index, <, Context->ProcessorCount);
- return Cpu->ProcessorID;
+ return Processor->ProcessorID;
}
VOID
HKR,"Interrupt Management",,0x00000010
HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+HKR,"Interrupt Management\GroupPolicy",0x00010001,1
[XenFilt_Service]
DisplayName=%XenFiltDesc%
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <ntstrsafe.h>
#include <stdlib.h>
PVOID Argument;
LIST_ENTRY GetList;
PLIST_ENTRY PutList;
- LONG Count;
- XENBUS_CACHE_MAGAZINE Magazine[MAXIMUM_PROCESSORS];
+ LONG ObjectCount;
+ PXENBUS_CACHE_MAGAZINE Magazine;
+ ULONG MagazineCount;
XENBUS_CACHE_FIST FIST;
};
KIRQL Irql = PASSIVE_LEVEL;
NTSTATUS status;
- Count = InterlockedDecrement(&Cache->Count);
+ Count = InterlockedDecrement(&Cache->ObjectCount);
status = STATUS_NO_MEMORY;
if (Count < 0)
return Object;
fail1:
- (VOID) InterlockedIncrement(&Cache->Count);
+ (VOID) InterlockedIncrement(&Cache->ObjectCount);
return NULL;
}
KeMemoryBarrier();
- (VOID) InterlockedIncrement(&Cache->Count);
+ (VOID) InterlockedIncrement(&Cache->ObjectCount);
}
static PVOID
CacheGetObjectFromMagazine(
IN PXENBUS_CACHE Cache,
- IN ULONG Cpu
+ IN ULONG Index
)
{
PXENBUS_CACHE_MAGAZINE Magazine;
- ULONG Index;
- Magazine = &Cache->Magazine[Cpu];
+ Magazine = &Cache->Magazine[Index];
for (Index = 0; Index < XENBUS_CACHE_MAGAZINE_SLOTS; Index++) {
PVOID Object;
static BOOLEAN
CachePutObjectToMagazine(
IN PXENBUS_CACHE Cache,
- IN ULONG Cpu,
+ IN ULONG Index,
IN PVOID Object
)
{
PXENBUS_CACHE_MAGAZINE Magazine;
- ULONG Index;
- Magazine = &Cache->Magazine[Cpu];
+ Magazine = &Cache->Magazine[Index];
for (Index = 0; Index < XENBUS_CACHE_MAGAZINE_SLOTS; Index++) {
if (Magazine->Slot[Index] == NULL) {
)
{
KIRQL Irql;
- ULONG Cpu;
+ ULONG Index;
PVOID Object;
UNREFERENCED_PARAMETER(Interface);
}
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
- Cpu = KeGetCurrentProcessorNumber();
+ Index = KeGetCurrentProcessorNumberEx(NULL);
- Object = CacheGetObjectFromMagazine(Cache, Cpu);
+ Object = CacheGetObjectFromMagazine(Cache, Index);
if (Object != NULL)
goto done;
)
{
KIRQL Irql;
- ULONG Cpu;
+ ULONG Index;
UNREFERENCED_PARAMETER(Interface);
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
- Cpu = KeGetCurrentProcessorNumber();
+ Index = KeGetCurrentProcessorNumberEx(NULL);
- if (CachePutObjectToMagazine(Cache, Cpu, Object))
+ if (CachePutObjectToMagazine(Cache, Index, Object))
goto done;
CachePutObjectToList(Cache, Object, Locked);
IN PXENBUS_CACHE Cache
)
{
- ULONG Cpu;
+ ULONG Index;
- for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
+ for (Index = 0; Index < Cache->MagazineCount; Index++) {
PVOID Object;
- while ((Object = CacheGetObjectFromMagazine(Cache, Cpu)) != NULL)
+ while ((Object = CacheGetObjectFromMagazine(Cache, Index)) != NULL)
CachePutObjectToList(Cache, Object, TRUE);
}
}
if (!NT_SUCCESS(status))
goto fail4;
+ (*Cache)->MagazineCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
+ (*Cache)->Magazine = __CacheAllocate(sizeof (XENBUS_CACHE_MAGAZINE) * (*Cache)->MagazineCount);
+
+ status = STATUS_NO_MEMORY;
+ if ((*Cache)->Magazine == NULL)
+ goto fail5;
+
(*Cache)->Reservation = Reservation;
KeAcquireSpinLock(&Context->Lock, &Irql);
return STATUS_SUCCESS;
+fail5:
+ Error("fail5\n");
+
+ (*Cache)->MagazineCount = 0;
+
fail4:
Error("fail4\n");
Cache->Reservation = 0;
CacheFlushMagazines(Cache);
- CacheSpill(Cache, Cache->Count);
+ CacheSpill(Cache, Cache->ObjectCount);
+
+ ASSERT3U(Cache->ObjectCount, ==, 0);
- ASSERT3U(Cache->Count, ==, 0);
+ ASSERT(IsZeroMemory(Cache->Magazine, sizeof (XENBUS_CACHE_MAGAZINE) * Cache->MagazineCount));
+ __CacheFree(Cache->Magazine);
+ Cache->Magazine = NULL;
+ Cache->MagazineCount = 0;
RtlZeroMemory(&Cache->GetList, sizeof (LIST_ENTRY));
&Context->DebugInterface,
"- %s: Count = %d (Reservation = %d)\n",
Cache->Name,
- Cache->Count,
+ Cache->ObjectCount,
Cache->Reservation);
}
}
Cache = CONTAINING_RECORD(ListEntry, XENBUS_CACHE, ListEntry);
- Count = Cache->Count;
+ Count = Cache->ObjectCount;
if (Count < Cache->Reservation)
CacheFill(Cache, Cache->Reservation - Count);
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <ntstrsafe.h>
#include "registry.h"
ASSERT3P(__DriverGetDriverObject(), ==, NULL);
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+ WdmlibProcgrpInitialize();
__DbgPrintEnable();
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <stdarg.h>
#include <xen.h>
XENBUS_EVTCHN_PARAMETERS Parameters;
BOOLEAN Mask;
ULONG LocalPort;
- ULONG Cpu;
+ PROCESSOR_NUMBER ProcNumber;
BOOLEAN Closed;
};
+typedef struct _XENBUS_EVTCHN_PROCESSOR {
+ PXENBUS_INTERRUPT Interrupt;
+ LIST_ENTRY PendingList;
+ KDPC Dpc;
+ BOOLEAN UpcallEnabled;
+} XENBUS_EVTCHN_PROCESSOR, *PXENBUS_EVTCHN_PROCESSOR;
+
struct _XENBUS_EVTCHN_CONTEXT {
PXENBUS_FDO Fdo;
KSPIN_LOCK Lock;
LONG References;
- PXENBUS_INTERRUPT LevelSensitiveInterrupt;
- PXENBUS_INTERRUPT LatchedInterrupt[MAXIMUM_PROCESSORS];
- KAFFINITY Affinity;
+ PXENBUS_INTERRUPT Interrupt;
+ PXENBUS_EVTCHN_PROCESSOR Processor;
+ ULONG ProcessorCount;
XENBUS_SUSPEND_INTERFACE SuspendInterface;
PXENBUS_SUSPEND_CALLBACK SuspendCallbackEarly;
PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate;
BOOLEAN UseEvtchnFifoAbi;
PXENBUS_HASH_TABLE Table;
LIST_ENTRY List;
- LIST_ENTRY PendingList[MAXIMUM_PROCESSORS];
- KDPC Dpc[MAXIMUM_PROCESSORS];
};
#define XENBUS_EVTCHN_TAG 'CTVE'
RemoveEntryList(&Channel->ListEntry);
RtlZeroMemory(&Channel->ListEntry, sizeof (LIST_ENTRY));
- Channel->Cpu = 0;
+ RtlZeroMemory(&Channel->ProcNumber, sizeof (PROCESSOR_NUMBER));
ASSERT(IsListEmpty(&Channel->PendingListEntry));
RtlZeroMemory(&Channel->PendingListEntry, sizeof (LIST_ENTRY));
static BOOLEAN
EvtchnPollCallback(
- IN PVOID Argument,
- IN ULONG LocalPort
+ IN PVOID Argument,
+ IN ULONG LocalPort
)
{
- PXENBUS_EVTCHN_CONTEXT Context = Argument;
- ULONG Cpu;
- PXENBUS_EVTCHN_CHANNEL Channel;
- BOOLEAN Pending;
- NTSTATUS status;
+ PXENBUS_EVTCHN_CONTEXT Context = Argument;
+ ULONG Index;
+ PXENBUS_EVTCHN_PROCESSOR Processor;
+ PXENBUS_EVTCHN_CHANNEL Channel;
+ BOOLEAN Pending;
+ NTSTATUS status;
ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
- Cpu = KeGetCurrentProcessorNumber();
+ Index = KeGetCurrentProcessorNumberEx(NULL);
+
+ ASSERT3U(Index, <, Context->ProcessorCount);
+ Processor = &Context->Processor[Index];
status = HashTableLookup(Context->Table,
LocalPort,
Pending = !IsListEmpty(&Channel->PendingListEntry);
if (!Pending)
- InsertTailList(&Context->PendingList[Cpu],
+ InsertTailList(&Processor->PendingList,
&Channel->PendingListEntry);
done:
static BOOLEAN
EvtchnPoll(
IN PXENBUS_EVTCHN_CONTEXT Context,
- IN ULONG Cpu,
+ IN ULONG Index,
IN PLIST_ENTRY List
)
{
+ PXENBUS_EVTCHN_PROCESSOR Processor;
BOOLEAN DoneSomething;
PLIST_ENTRY ListEntry;
+ ASSERT3U(Index, <, Context->ProcessorCount);
+ Processor = &Context->Processor[Index];
+
(VOID) XENBUS_EVTCHN_ABI(Poll,
&Context->EvtchnAbi,
- Cpu,
+ Index,
EvtchnPollCallback,
Context);
DoneSomething = FALSE;
- ListEntry = Context->PendingList[Cpu].Flink;
- while (ListEntry != &Context->PendingList[Cpu]) {
+ ListEntry = Processor->PendingList.Flink;
+ while (ListEntry != &Processor->PendingList) {
PLIST_ENTRY Next = ListEntry->Flink;
PXENBUS_EVTCHN_CHANNEL Channel;
static VOID
EvtchnFlush(
IN PXENBUS_EVTCHN_CONTEXT Context,
- IN ULONG Cpu
+ IN ULONG Index
)
{
+ PXENBUS_EVTCHN_PROCESSOR Processor;
LIST_ENTRY List;
PXENBUS_INTERRUPT Interrupt;
KIRQL Irql;
- Interrupt = (Context->Affinity != 0) ? // Latched available
- Context->LatchedInterrupt[Cpu] :
- Context->LevelSensitiveInterrupt;
+ ASSERT3U(Index, <, Context->ProcessorCount);
+ Processor = &Context->Processor[Index];
+
+ Interrupt = (Processor->UpcallEnabled) ?
+ Processor->Interrupt :
+ Context->Interrupt;
InitializeListHead(&List);
Irql = FdoAcquireInterruptLock(Context->Fdo, Interrupt);
-
- (VOID) EvtchnPoll(Context, Cpu, &List);
-
+ (VOID) EvtchnPoll(Context, Index, &List);
FdoReleaseInterruptLock(Context->Fdo, Interrupt, Irql);
while (!IsListEmpty(&List)) {
)
{
PXENBUS_EVTCHN_CONTEXT Context = _Context;
- ULONG Cpu;
+ ULONG Index;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(Argument1);
UNREFERENCED_PARAMETER(Argument2);
ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
- Cpu = KeGetCurrentProcessorNumber();
+ Index = KeGetCurrentProcessorNumberEx(NULL);
KeAcquireSpinLockAtDpcLevel(&Context->Lock);
if (Context->References == 0)
goto done;
- EvtchnFlush(Context, Cpu);
+ EvtchnFlush(Context, Index);
done:
KeReleaseSpinLockFromDpcLevel(&Context->Lock);
)
{
PXENBUS_EVTCHN_CONTEXT Context = Interface->Context;
- PKDPC Dpc;
KIRQL Irql;
- ULONG Cpu;
+ PROCESSOR_NUMBER ProcNumber;
+ ULONG Index;
+ PXENBUS_EVTCHN_PROCESSOR Processor;
PXENBUS_INTERRUPT Interrupt;
BOOLEAN Pending;
ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
KeAcquireSpinLock(&Channel->Lock, &Irql);
- Cpu = Channel->Cpu;
+ ProcNumber = Channel->ProcNumber;
KeReleaseSpinLock(&Channel->Lock, Irql);
- Interrupt = (Context->Affinity != 0) ? // Latched available
- Context->LatchedInterrupt[Cpu] :
- Context->LevelSensitiveInterrupt;
+ Index = KeGetProcessorIndexFromNumber(&ProcNumber);
+
+ ASSERT3U(Index, <, Context->ProcessorCount);
+ Processor = &Context->Processor[Index];
+
+ Interrupt = (Processor->UpcallEnabled) ?
+ Processor->Interrupt :
+ Context->Interrupt;
Irql = FdoAcquireInterruptLock(Context->Fdo, Interrupt);
Pending = !IsListEmpty(&Channel->PendingListEntry);
if (!Pending)
- InsertTailList(&Context->PendingList[Cpu],
+ InsertTailList(&Processor->PendingList,
&Channel->PendingListEntry);
FdoReleaseInterruptLock(Context->Fdo, Interrupt, Irql);
if (Pending)
return;
- Dpc = &Context->Dpc[Cpu];
- KeInsertQueueDpc(Dpc, NULL, NULL);
+ KeInsertQueueDpc(&Processor->Dpc, NULL, NULL);
}
static NTSTATUS
EvtchnBind(
IN PINTERFACE Interface,
IN PXENBUS_EVTCHN_CHANNEL Channel,
- IN ULONG Cpu
+ IN USHORT Group,
+ IN UCHAR Number
)
{
PXENBUS_EVTCHN_CONTEXT Context = Interface->Context;
+ PROCESSOR_NUMBER ProcNumber;
+ ULONG Index;
+ PXENBUS_EVTCHN_PROCESSOR Processor;
ULONG LocalPort;
unsigned int vcpu_id;
KIRQL Irql;
ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
+ RtlZeroMemory(&ProcNumber, sizeof (PROCESSOR_NUMBER));
+ ProcNumber.Group = Group;
+ ProcNumber.Number = Number;
+
+ Index = KeGetProcessorIndexFromNumber(&ProcNumber);
+
+ ASSERT3U(Index, <, Context->ProcessorCount);
+ Processor = &Context->Processor[Index];
+
status = STATUS_NOT_SUPPORTED;
- if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+ if (!Processor->UpcallEnabled)
goto fail1;
KeAcquireSpinLock(&Channel->Lock, &Irql);
if (!Channel->Active)
goto done;
- if (Channel->Cpu == Cpu)
+ if (Channel->ProcNumber.Group == Group &&
+ Channel->ProcNumber.Number == Number)
goto done;
LocalPort = Channel->LocalPort;
- vcpu_id = SystemVirtualCpuIndex(Cpu);
+ vcpu_id = SystemVirtualCpuIndex(Index);
status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
if (!NT_SUCCESS(status))
goto fail2;
- Channel->Cpu = Cpu;
+ Channel->ProcNumber = ProcNumber;
- Info("[%u]: CPU %u\n", LocalPort, Cpu);
+ Info("[%u]: CPU %u:%u\n", LocalPort, Group, Number);
done:
KeReleaseSpinLock(&Channel->Lock, Irql);
return status;
}
+static NTSTATUS
+EvtchnBindVersion2(
+ IN PINTERFACE Interface,
+ IN PXENBUS_EVTCHN_CHANNEL Channel,
+ IN ULONG Cpu
+ )
+{
+ ASSERT3U(Cpu, <, MAXIMUM_PROCESSORS);
+
+ return EvtchnBind(Interface, Channel, 0, (CHAR)Cpu);
+}
+
static VOID
EvtchnUnmask(
IN PINTERFACE Interface,
)
{
PXENBUS_EVTCHN_CONTEXT Context = Argument;
- ULONG Cpu;
+ ULONG Index;
BOOLEAN DoneSomething;
UNREFERENCED_PARAMETER(InterruptObject);
ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
- Cpu = KeGetCurrentProcessorNumber();
+ Index = KeGetCurrentProcessorNumberEx(NULL);
DoneSomething = FALSE;
while (XENBUS_SHARED_INFO(UpcallPending,
&Context->SharedInfoInterface,
- Cpu))
- DoneSomething |= EvtchnPoll(Context, Cpu, NULL);
+ Index))
+ DoneSomething |= EvtchnPoll(Context, Index, NULL);
return DoneSomething;
}
static NTSTATUS
EvtchnAbiAcquire(
- IN PXENBUS_EVTCHN_CONTEXT Context,
- OUT PKAFFINITY Affinity
+ IN PXENBUS_EVTCHN_CONTEXT Context
)
{
NTSTATUS status;
&Context->EvtchnAbi);
status = XENBUS_EVTCHN_ABI(Acquire,
- &Context->EvtchnAbi,
- Affinity);
+ &Context->EvtchnAbi);
if (!NT_SUCCESS(status))
goto use_two_level;
&Context->EvtchnAbi);
status = XENBUS_EVTCHN_ABI(Acquire,
- &Context->EvtchnAbi,
- Affinity);
+ &Context->EvtchnAbi);
if (!NT_SUCCESS(status))
goto fail1;
IN PXENBUS_EVTCHN_CONTEXT Context
)
{
- LONG Cpu;
+ ULONG Index;
ULONG Line;
NTSTATUS status;
Trace("====>\n");
- for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
- unsigned int vcpu_id;
- UCHAR Vector;
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PXENBUS_EVTCHN_PROCESSOR Processor;
+ unsigned int vcpu_id;
+ UCHAR Vector;
+
+ Processor = &Context->Processor[Index];
- if (Context->LatchedInterrupt[Cpu] == NULL)
+ if (Processor->Interrupt == NULL)
continue;
- vcpu_id = SystemVirtualCpuIndex(Cpu);
- Vector = FdoGetInterruptVector(Context->Fdo,
- Context->LatchedInterrupt[Cpu]);
+ vcpu_id = SystemVirtualCpuIndex(Index);
+ Vector = FdoGetInterruptVector(Context->Fdo, Processor->Interrupt);
status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
if (NT_SUCCESS(status)) {
- Info("CPU %u\n", Cpu);
- Context->Affinity |= (KAFFINITY)1 << Cpu;
+ PROCESSOR_NUMBER ProcNumber;
+
+ status = KeGetProcessorNumberFromIndex(Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ Info("CPU %u:%u\n", ProcNumber.Group, ProcNumber.Number);
+ Processor->UpcallEnabled = TRUE;
}
}
- Line = FdoGetInterruptLine(Context->Fdo,
- Context->LevelSensitiveInterrupt);
+ Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
ASSERT(NT_SUCCESS(status));
IN PXENBUS_EVTCHN_CONTEXT Context
)
{
- ULONG Cpu;
+ ULONG Index;
NTSTATUS status;
UNREFERENCED_PARAMETER(Context);
status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
ASSERT(NT_SUCCESS(status));
- for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
- unsigned int vcpu_id;
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PXENBUS_EVTCHN_PROCESSOR Processor;
+ unsigned int vcpu_id;
+
+ Processor = &Context->Processor[Index];
- if (~Context->Affinity & (KAFFINITY)1 << Cpu)
+ if (!Processor->UpcallEnabled)
continue;
- vcpu_id = SystemVirtualCpuIndex(Cpu);
+ vcpu_id = SystemVirtualCpuIndex(Index);
(VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
- Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+ Processor->UpcallEnabled = FALSE;
}
- ASSERT3U(Context->Affinity, ==, 0);
-
Trace("<====\n");
}
)
{
PXENBUS_EVTCHN_CONTEXT Context = Argument;
- KAFFINITY Affinity;
NTSTATUS status;
EvtchnAbiRelease(Context);
- status = EvtchnAbiAcquire(Context, &Affinity);
+ status = EvtchnAbiAcquire(Context);
ASSERT(NT_SUCCESS(status));
- // Affinity must be a superset of Context->Affinity
- ASSERT3U(Affinity & Context->Affinity, ==, Context->Affinity);
-
EvtchnInterruptDisable(Context);
EvtchnInterruptEnable(Context);
}
PXENBUS_EVTCHN_CONTEXT Context = Interface->Context;
PXENBUS_FDO Fdo = Context->Fdo;
KIRQL Irql;
- ULONG Cpu;
- KAFFINITY Affinity;
+ PROCESSOR_NUMBER ProcNumber;
+ ULONG Index;
NTSTATUS status;
KeAcquireSpinLock(&Context->Lock, &Irql);
if (!NT_SUCCESS(status))
goto fail6;
- status = EvtchnAbiAcquire(Context, &Affinity);
+ status = EvtchnAbiAcquire(Context);
if (!NT_SUCCESS(status))
goto fail7;
- Context->LevelSensitiveInterrupt = FdoAllocateInterrupt(Fdo,
- LevelSensitive,
- 0,
- EvtchnInterruptCallback,
- Context);
+ status = KeGetProcessorNumberFromIndex(0, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ Context->Interrupt = FdoAllocateInterrupt(Fdo,
+ LevelSensitive,
+ ProcNumber.Group,
+ ProcNumber.Number,
+ EvtchnInterruptCallback,
+ Context);
status = STATUS_UNSUCCESSFUL;
- if (Context->LevelSensitiveInterrupt == NULL)
+ if (Context->Interrupt == NULL)
goto fail8;
- for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
- if (~Affinity & (KAFFINITY)1 << Cpu)
+ Context->ProcessorCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
+ Context->Processor = __EvtchnAllocate(sizeof (XENBUS_EVTCHN_PROCESSOR) * Context->ProcessorCount);
+
+ status = STATUS_NO_MEMORY;
+ if (Context->Processor == NULL)
+ goto fail9;
+
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PXENBUS_EVTCHN_PROCESSOR Processor;
+
+ if (!XENBUS_EVTCHN_ABI(IsProcessorEnabled,
+ &Context->EvtchnAbi,
+ Index))
continue;
- Context->LatchedInterrupt[Cpu] = FdoAllocateInterrupt(Fdo,
- Latched,
- Cpu,
- EvtchnInterruptCallback,
- Context);
+ status = KeGetProcessorNumberFromIndex(Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ Processor = &Context->Processor[Index];
+
+ Processor->Interrupt = FdoAllocateInterrupt(Fdo,
+ Latched,
+ ProcNumber.Group,
+ ProcNumber.Number,
+ EvtchnInterruptCallback,
+ Context);
+ ASSERT(Processor->Interrupt != NULL);
+
+ InitializeListHead(&Processor->PendingList);
+
+ KeInitializeDpc(&Processor->Dpc, EvtchnDpc, Context);
+ KeSetTargetProcessorDpcEx(&Processor->Dpc, &ProcNumber);
}
EvtchnInterruptEnable(Context);
return STATUS_SUCCESS;
+fail9:
+ Error("fail9\n");
+
+ Context->ProcessorCount = 0;
+
fail8:
Error("fail8\n");
PXENBUS_EVTCHN_CONTEXT Context = Interface->Context;
PXENBUS_FDO Fdo = Context->Fdo;
KIRQL Irql;
- ULONG Cpu;
+ ULONG Index;
KeAcquireSpinLock(&Context->Lock, &Irql);
EvtchnInterruptDisable(Context);
- for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
- if (Context->LatchedInterrupt[Cpu] == NULL)
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PXENBUS_EVTCHN_PROCESSOR Processor;
+
+ ASSERT(Context->Processor != NULL);
+ Processor = &Context->Processor[Index];
+
+ if (Processor->Interrupt == NULL)
continue;
- EvtchnFlush(Context, Cpu);
+ EvtchnFlush(Context, Index);
+
+ RtlZeroMemory(&Processor->Dpc, sizeof (KDPC));
+ RtlZeroMemory(&Processor->PendingList, sizeof (LIST_ENTRY));
- FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
- Context->LatchedInterrupt[Cpu] = NULL;
+ FdoFreeInterrupt(Fdo, Processor->Interrupt);
+ Processor->Interrupt = NULL;
}
- FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
- Context->LevelSensitiveInterrupt = NULL;
+ ASSERT(IsZeroMemory(Context->Processor, sizeof (XENBUS_EVTCHN_PROCESSOR) * Context->ProcessorCount));
+ __EvtchnFree(Context->Processor);
+ Context->ProcessorCount = 0;
+
+ FdoFreeInterrupt(Fdo, Context->Interrupt);
+ Context->Interrupt = NULL;
if (!IsListEmpty(&Context->List))
BUG("OUTSTANDING EVENT CHANNELS");
EvtchnAcquire,
EvtchnRelease,
EvtchnOpen,
- EvtchnBind,
+ EvtchnBindVersion2,
EvtchnUnmaskVersion1,
EvtchnSend,
EvtchnTrigger,
EvtchnAcquire,
EvtchnRelease,
EvtchnOpen,
+ EvtchnBindVersion2,
+ EvtchnUnmask,
+ EvtchnSend,
+ EvtchnTrigger,
+ EvtchnGetPort,
+ EvtchnClose
+};
+
+static struct _XENBUS_EVTCHN_INTERFACE_V4 EvtchnInterfaceVersion4 = {
+ { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V4), 4, NULL, NULL, NULL },
+ EvtchnAcquire,
+ EvtchnRelease,
+ EvtchnOpen,
EvtchnBind,
EvtchnUnmask,
EvtchnSend,
{
HANDLE ParametersKey;
ULONG UseEvtchnFifoAbi;
- ULONG Cpu;
NTSTATUS status;
Trace("====>\n");
InitializeListHead(&(*Context)->List);
KeInitializeSpinLock(&(*Context)->Lock);
- for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
- PKDPC Dpc = &(*Context)->Dpc[Cpu];
-
- InitializeListHead(&(*Context)->PendingList[Cpu]);
-
- KeInitializeDpc(Dpc, EvtchnDpc, *Context);
- KeSetTargetProcessorDpc(Dpc, (CCHAR)Cpu);
- }
-
(*Context)->Fdo = Fdo;
Trace("<====\n");
status = STATUS_SUCCESS;
break;
}
+ case 4: {
+ struct _XENBUS_EVTCHN_INTERFACE_V4 *EvtchnInterface;
+
+ EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V4 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V4))
+ break;
+
+ *EvtchnInterface = EvtchnInterfaceVersion4;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;
Context->Fdo = NULL;
- RtlZeroMemory(&Context->Dpc, sizeof (KDPC) * MAXIMUM_PROCESSORS);
RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
RtlZeroMemory(&Context->List, sizeof (LIST_ENTRY));
- RtlZeroMemory(&Context->PendingList, sizeof (LIST_ENTRY) * MAXIMUM_PROCESSORS);
RtlZeroMemory(&Context->SharedInfoInterface,
sizeof (XENBUS_SHARED_INFO_INTERFACE));
ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_TWO_LEVEL_TAG);
}
+static BOOLEAN
+EvtchnTwoLevelIsProcessorEnabled(
+ IN PXENBUS_EVTCHN_ABI_CONTEXT _Context,
+ IN ULONG Index
+ )
+{
+ UNREFERENCED_PARAMETER(_Context);
+
+ return (SystemVirtualCpuIndex(Index) == 0) ? TRUE : FALSE;
+}
+
static BOOLEAN
EvtchnTwoLevelPoll(
IN PXENBUS_EVTCHN_ABI_CONTEXT _Context,
- IN ULONG Cpu,
+ IN ULONG Index,
IN XENBUS_EVTCHN_ABI_EVENT Event,
IN PVOID Argument
)
return XENBUS_SHARED_INFO(EvtchnPoll,
&Context->SharedInfoInterface,
- Cpu,
+ Index,
Event,
Argument);
}
static NTSTATUS
EvtchnTwoLevelAcquire(
- IN PXENBUS_EVTCHN_ABI_CONTEXT _Context,
- OUT PKAFFINITY Affinity
+ IN PXENBUS_EVTCHN_ABI_CONTEXT _Context
)
{
PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT Context = (PVOID)_Context;
if (!NT_SUCCESS(status))
goto fail1;
- *Affinity = (KAFFINITY)1;
-
Trace("<====\n");
done:
NULL,
EvtchnTwoLevelAcquire,
EvtchnTwoLevelRelease,
+ EvtchnTwoLevelIsProcessorEnabled,
EvtchnTwoLevelPoll,
EvtchnTwoLevelPortEnable,
EvtchnTwoLevelPortDisable,
typedef NTSTATUS
(*XENBUS_EVTCHN_ABI_ACQUIRE)(
- IN PXENBUS_EVTCHN_ABI_CONTEXT Context,
- OUT PKAFFINITY Affinity
+ IN PXENBUS_EVTCHN_ABI_CONTEXT Context
);
typedef VOID
IN PXENBUS_EVTCHN_ABI_CONTEXT Context
);
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_IS_PROCESSOR_ENABLED)(
+ IN PXENBUS_EVTCHN_ABI_CONTEXT Context,
+ IN ULONG Index
+ );
+
typedef BOOLEAN
(*XENBUS_EVTCHN_ABI_EVENT)(
IN PVOID Argument,
typedef BOOLEAN
(*XENBUS_EVTCHN_ABI_POLL)(
IN PXENBUS_EVTCHN_ABI_CONTEXT Context,
- IN ULONG Cpu,
+ IN ULONG Index,
IN XENBUS_EVTCHN_ABI_EVENT Event,
IN PVOID Argument
);
);
typedef struct _XENBUS_EVTCHN_ABI {
- PXENBUS_EVTCHN_ABI_CONTEXT Context;
- XENBUS_EVTCHN_ABI_ACQUIRE EvtchnAbiAcquire;
- XENBUS_EVTCHN_ABI_RELEASE EvtchnAbiRelease;
- XENBUS_EVTCHN_ABI_POLL EvtchnAbiPoll;
- XENBUS_EVTCHN_ABI_PORT_ENABLE EvtchnAbiPortEnable;
- XENBUS_EVTCHN_ABI_PORT_DISABLE EvtchnAbiPortDisable;
- XENBUS_EVTCHN_ABI_PORT_ACK EvtchnAbiPortAck;
- XENBUS_EVTCHN_ABI_PORT_MASK EvtchnAbiPortMask;
- XENBUS_EVTCHN_ABI_PORT_UNMASK EvtchnAbiPortUnmask;
+ PXENBUS_EVTCHN_ABI_CONTEXT Context;
+ XENBUS_EVTCHN_ABI_ACQUIRE EvtchnAbiAcquire;
+ XENBUS_EVTCHN_ABI_RELEASE EvtchnAbiRelease;
+ XENBUS_EVTCHN_ABI_IS_PROCESSOR_ENABLED EvtchnAbiIsProcessorEnabled;
+ XENBUS_EVTCHN_ABI_POLL EvtchnAbiPoll;
+ XENBUS_EVTCHN_ABI_PORT_ENABLE EvtchnAbiPortEnable;
+ XENBUS_EVTCHN_ABI_PORT_DISABLE EvtchnAbiPortDisable;
+ XENBUS_EVTCHN_ABI_PORT_ACK EvtchnAbiPortAck;
+ XENBUS_EVTCHN_ABI_PORT_MASK EvtchnAbiPortMask;
+ XENBUS_EVTCHN_ABI_PORT_UNMASK EvtchnAbiPortUnmask;
} XENBUS_EVTCHN_ABI, *PXENBUS_EVTCHN_ABI;
#define XENBUS_EVTCHN_ABI(_Method, _Abi, ...) \
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <stdarg.h>
#include <xen.h>
#include "assert.h"
#include "util.h"
-#define MAX_HVM_VCPUS 128
-
typedef struct _XENBUS_EVTCHN_FIFO_CONTEXT {
PXENBUS_FDO Fdo;
KSPIN_LOCK Lock;
LONG References;
- PMDL ControlBlockMdl[MAX_HVM_VCPUS];
+ PMDL ControlBlockMdl[HVM_MAX_VCPUS];
PMDL *EventPageMdl;
ULONG EventPageCount;
- ULONG Head[MAX_HVM_VCPUS][EVTCHN_FIFO_MAX_QUEUES];
+ ULONG Head[HVM_MAX_VCPUS][EVTCHN_FIFO_MAX_QUEUES];
} XENBUS_EVTCHN_FIFO_CONTEXT, *PXENBUS_EVTCHN_FIFO_CONTEXT;
#define EVENT_WORDS_PER_PAGE (PAGE_SIZE / sizeof (event_word_t))
Context->EventPageCount = 0;
}
+static BOOLEAN
+EvtchnFifoIsProcessorEnabled(
+ IN PXENBUS_EVTCHN_ABI_CONTEXT _Context,
+ IN ULONG Index
+ )
+{
+ PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context;
+ unsigned int vcpu_id = SystemVirtualCpuIndex(Index);
+
+ return (Context->ControlBlockMdl[vcpu_id] != NULL) ? TRUE : FALSE;
+}
+
static BOOLEAN
EvtchnFifoPollPriority(
IN PXENBUS_EVTCHN_FIFO_CONTEXT Context,
static BOOLEAN
EvtchnFifoPoll(
IN PXENBUS_EVTCHN_ABI_CONTEXT _Context,
- IN ULONG Cpu,
+ IN ULONG Index,
IN XENBUS_EVTCHN_ABI_EVENT Event,
IN PVOID Argument
)
{
PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context;
- unsigned int vcpu_id = SystemVirtualCpuIndex(Cpu);
+ unsigned int vcpu_id = SystemVirtualCpuIndex(Index);
PMDL Mdl;
evtchn_fifo_control_block_t *ControlBlock;
ULONG Ready;
Mdl = Context->ControlBlockMdl[vcpu_id];
+ DoneSomething = FALSE;
+ if (Mdl == NULL)
+ goto done;
+
ControlBlock = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
ASSERT(ControlBlock != NULL);
Ready = InterlockedExchange((LONG *)&ControlBlock->ready, 0);
- DoneSomething = FALSE;
while (_BitScanReverse(&Priority, Ready)) {
DoneSomething |= EvtchnFifoPollPriority(Context,
Ready |= InterlockedExchange((LONG *)&ControlBlock->ready, 0);
}
+done:
return DoneSomething;
}
static NTSTATUS
EvtchnFifoAcquire(
- IN PXENBUS_EVTCHN_ABI_CONTEXT _Context,
- OUT PKAFFINITY Affinity
+ IN PXENBUS_EVTCHN_ABI_CONTEXT _Context
)
{
PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context;
KIRQL Irql;
- LONG Cpu;
+ LONG Index;
PMDL Mdl;
NTSTATUS status;
Trace("====>\n");
- *Affinity = 0;
- Cpu = 0;
-
- while (Cpu < (LONG)KeQueryActiveProcessorCount(NULL)) {
+ Index = 0;
+ while (Index < (LONG)KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS)) {
unsigned int vcpu_id;
PFN_NUMBER Pfn;
PHYSICAL_ADDRESS Address;
if (Mdl == NULL)
goto fail1;
- vcpu_id = SystemVirtualCpuIndex(Cpu);
+ vcpu_id = SystemVirtualCpuIndex(Index);
Pfn = MmGetMdlPfnArray(Mdl)[0];
status = EventChannelInitControl(Pfn, vcpu_id);
Context->ControlBlockMdl[vcpu_id] = Mdl;
- *Affinity |= (KAFFINITY)1 << Cpu;
- Cpu++;
+ Index++;
}
Trace("<====\n");
(VOID) EventChannelReset();
- while (--Cpu >= 0) {
+ while (--Index >= 0) {
unsigned int vcpu_id;
- vcpu_id = SystemVirtualCpuIndex(Cpu);
+ vcpu_id = SystemVirtualCpuIndex(Index);
Mdl = Context->ControlBlockMdl[vcpu_id];
Context->ControlBlockMdl[vcpu_id] = NULL;
EvtchnFifoContract(Context);
- vcpu_id = MAX_HVM_VCPUS;
+ vcpu_id = HVM_MAX_VCPUS;
while (--vcpu_id >= 0) {
PMDL Mdl;
NULL,
EvtchnFifoAcquire,
EvtchnFifoRelease,
+ EvtchnFifoIsProcessorEnabled,
EvtchnFifoPoll,
EvtchnFifoPortEnable,
EvtchnFifoPortDisable,
#define INITGUID 1
#include <ntddk.h>
+#include <procgrp.h>
#include <wdmguid.h>
#include <ntstrsafe.h>
#include <stdlib.h>
LIST_ENTRY ListEntry;
KINTERRUPT_MODE InterruptMode;
PKINTERRUPT InterruptObject;
- ULONG Cpu;
+ PROCESSOR_NUMBER ProcNumber;
UCHAR Vector;
ULONG Line;
PKSERVICE_ROUTINE Callback;
)
{
PXENBUS_FDO Fdo = Context;
+ GROUP_AFFINITY Affinity;
PKEVENT Event;
Info("====>\n");
// We really want to know what CPU this thread will run on
- KeSetSystemAffinityThread((KAFFINITY)1);
+ Affinity.Group = 0;
+ Affinity.Mask = (KAFFINITY)1;
+ KeSetSystemGroupAffinityThread(&Affinity, NULL);
Event = ThreadGetEvent(Self);
else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
Trace("Preferred Alternative\n");
- Trace("ShareDisposition=%s Flags=%04x\n",
+ Trace("ShareDisposition = %s Flags = %04x\n",
ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
Descriptor->Flags);
break;
case CmResourceTypeInterrupt:
- Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+ Trace("MinimumVector = %08x MaximumVector = %08x AffinityPolicy = %s PriorityPolicy = %s Group = %u TargettedProcessors = %p\n",
Descriptor->u.Interrupt.MinimumVector,
Descriptor->u.Interrupt.MaximumVector,
IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+ Descriptor->u.Interrupt.Group,
(PVOID)Descriptor->u.Interrupt.TargetedProcessors);
break;
Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
ASSERT3U(Old->AlternativeLists, ==, 1);
- Count = KeQueryActiveProcessorCount(NULL);
+ Count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
Size = Old->ListSize +
(sizeof (IO_RESOURCE_DESCRIPTOR) * Count);
Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+ Descriptor->u.Interrupt.Group = 0;
Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
}
Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
for (Index = 0; Index < Count; Index++) {
- Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+ PROCESSOR_NUMBER ProcNumber;
+
+ status = KeGetProcessorNumberFromIndex(Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ Interrupt.u.Interrupt.Group = ProcNumber.Group;
+ Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << ProcNumber.Number;
List->Descriptors[List->Count++] = Interrupt;
}
{
IO_CONNECT_INTERRUPT_PARAMETERS Connect;
BOOLEAN Found;
- ULONG Cpu;
+ ULONG Number;
NTSTATUS status;
Trace("====>\n");
(*Interrupt)->Line = Raw->u.Interrupt.Vector;
RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
- Connect.Version = CONNECT_FULLY_SPECIFIED;
+ Connect.Version = CONNECT_FULLY_SPECIFIED_GROUP;
Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
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.Group = Translated->u.MessageInterrupt.Translated.Group;
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.Group = Translated->u.Interrupt.Group;
Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
}
(*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+ (*Interrupt)->ProcNumber.Group = Connect.FullySpecified.Group;
+
#if defined(__i386__)
- Found = _BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+ Found = _BitScanReverse(&Number, Connect.FullySpecified.ProcessorEnableMask);
#elif defined(__x86_64__)
- Found = _BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+ Found = _BitScanReverse64(&Number, Connect.FullySpecified.ProcessorEnableMask);
#else
#error 'Unrecognised architecture'
#endif
ASSERT(Found);
- (*Interrupt)->Cpu = Cpu;
+ (*Interrupt)->ProcNumber.Number = (UCHAR)Number;
- Info("%p: %s %s CPU %u VECTOR %02x\n",
+ Info("%p: %s %s CPU %u:%u VECTOR %02x\n",
(*Interrupt)->InterruptObject,
ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
InterruptModeName((*Interrupt)->InterruptMode),
- (*Interrupt)->Cpu,
+ (*Interrupt)->ProcNumber.Group,
+ (*Interrupt)->ProcNumber.Number,
(*Interrupt)->Vector);
Trace("<====\n");
Trace("====>\n");
- Info("%p: CPU %u VECTOR %02x\n",
+ Info("%p: CPU %u:%u VECTOR %02x\n",
Interrupt->InterruptObject,
- Interrupt->Cpu,
+ Interrupt->ProcNumber.Group,
+ Interrupt->ProcNumber.Number,
Interrupt->Vector);
- Interrupt->Cpu = 0;
+ RtlZeroMemory(&Interrupt->ProcNumber, sizeof (PROCESSOR_NUMBER));
Interrupt->Vector = 0;
RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
FdoAllocateInterrupt(
IN PXENBUS_FDO Fdo,
IN KINTERRUPT_MODE InterruptMode,
- IN ULONG Cpu,
+ IN USHORT Group,
+ IN UCHAR Number,
IN KSERVICE_ROUTINE Callback,
IN PVOID Argument OPTIONAL
)
if (Interrupt->Callback == NULL &&
Interrupt->InterruptMode == InterruptMode &&
- Interrupt->Cpu == Cpu)
+ Interrupt->ProcNumber.Group == Group &&
+ Interrupt->ProcNumber.Number == Number)
goto found;
}
FdoAllocateInterrupt(
IN PXENBUS_FDO Fdo,
IN KINTERRUPT_MODE InterruptMode,
- IN ULONG Cpu,
+ IN USHORT Group,
+ IN UCHAR Number,
IN KSERVICE_ROUTINE Callback,
IN PVOID Argument OPTIONAL
);
Trace("(%s) <====\n", __PdoGetName(Pdo));
}
-static VOID
-PdoParseResources(
- IN PXENBUS_PDO Pdo,
- IN PCM_RESOURCE_LIST RawResourceList,
- IN PCM_RESOURCE_LIST TranslatedResourceList
- )
-{
- PCM_PARTIAL_RESOURCE_LIST RawPartialList;
- PCM_PARTIAL_RESOURCE_LIST TranslatedPartialList;
- ULONG Index;
-
- UNREFERENCED_PARAMETER(Pdo);
-
- ASSERT3U(RawResourceList->Count, ==, 1);
- RawPartialList = &RawResourceList->List[0].PartialResourceList;
-
- ASSERT3U(RawPartialList->Version, ==, 1);
- ASSERT3U(RawPartialList->Revision, ==, 1);
-
- ASSERT3U(TranslatedResourceList->Count, ==, 1);
- TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
-
- ASSERT3U(TranslatedPartialList->Version, ==, 1);
- ASSERT3U(TranslatedPartialList->Revision, ==, 1);
-
- for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
- PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
- PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
-
- RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
- TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
-
- Trace("%s: [%d] %02x:%s\n",
- __PdoGetName(Pdo),
- Index,
- TranslatedPartialDescriptor->Type,
- ResourceDescriptorTypeName(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);
- break;
-
- 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);
-
- 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);
- break;
-
- default:
- break;
- }
- }
-
- Trace("<====\n");
-}
-
static NTSTATUS
PdoStartDevice(
IN PXENBUS_PDO Pdo,
IN PIRP Irp
)
{
- PIO_STACK_LOCATION StackLocation;
NTSTATUS status;
- StackLocation = IoGetCurrentIrpStackLocation(Irp);
-
- PdoParseResources(Pdo,
- StackLocation->Parameters.StartDevice.AllocatedResources,
- StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
-
PdoD3ToD0(Pdo);
__PdoSetDevicePnpState(Pdo, Started);
Interrupt.u.Interrupt.MaximumVector = (ULONG)-1;
Interrupt.u.Interrupt.AffinityPolicy = IrqPolicyOneCloseProcessor;
Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+ Interrupt.u.Interrupt.Group = ALL_PROCESSOR_GROUPS;
Size = sizeof (IO_RESOURCE_DESCRIPTOR) * 2;
Size += FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors);
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <xen.h>
#include "shared_info.h"
static BOOLEAN
SharedInfoUpcallPending(
IN PINTERFACE Interface,
- IN ULONG Cpu
+ IN ULONG Index
)
{
PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
shared_info_t *Shared = Context->Shared;
- int vcpu_id = SystemVirtualCpuIndex(Cpu);
+ int vcpu_id = SystemVirtualCpuIndex(Index);
UCHAR Pending;
KeMemoryBarrier();
static BOOLEAN
SharedInfoEvtchnPoll(
IN PINTERFACE Interface,
- IN ULONG Cpu,
+ IN ULONG Index,
IN XENBUS_SHARED_INFO_EVENT Event,
IN PVOID Argument OPTIONAL
)
{
PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
shared_info_t *Shared = Context->Shared;
- int vcpu_id = SystemVirtualCpuIndex(Cpu);
+ int vcpu_id = SystemVirtualCpuIndex(Index);
ULONG Port;
ULONG_PTR SelectorMask;
BOOLEAN DoneSomething;
if (!Crashing) {
shared_info_t *Shared;
- ULONG Cpu;
+ ULONG Index;
ULONG Selector;
Shared = Context->Shared;
KeMemoryBarrier();
- for (Cpu = 0; Cpu < KeQueryActiveProcessorCount(NULL); Cpu++) {
- int vcpu_id = SystemVirtualCpuIndex(Cpu);
+ for (Index = 0;
+ Index < KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
+ Index++) {
+ PROCESSOR_NUMBER ProcNumber;
+ int vcpu_id;
+
+ (VOID) KeGetProcessorNumberFromIndex(Index, &ProcNumber);
+ vcpu_id = SystemVirtualCpuIndex(Index);
XENBUS_DEBUG(Printf,
&Context->DebugInterface,
- "CPU %u: PENDING: %s\n",
- Cpu,
+ "CPU %u:%u: PENDING: %s\n",
+ ProcNumber.Group,
+ ProcNumber.Number,
Shared->vcpu_info[vcpu_id].evtchn_upcall_pending ?
"TRUE" :
"FALSE");
XENBUS_DEBUG(Printf,
&Context->DebugInterface,
- "CPU %u: SELECTOR MASK: %p\n",
- Cpu,
+ "CPU %u:u: SELECTOR MASK: %p\n",
+ ProcNumber.Group,
+ ProcNumber.Number,
(PVOID)Shared->vcpu_info[vcpu_id].evtchn_pending_sel);
}
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <stdarg.h>
#include <xen.h>
#include "util.h"
// Routines to capture all CPUs in a spinning state with interrupts
-// disabled (so that we remain in a known code context) and optionally
-// execute a function on each CPU.
+// disabled (so that we remain in a known code context).
// These routines are used for suspend/resume and live snapshot.
// The general sequence of steps is follows:
//
-// - SyncCaptureAndCall() is called on an arbitrary CPU
+// - SyncCapture() is called on an arbitrary CPU. It must be called at
+// DISPATCH_LEVEL so it cannot be pre-empted and moved to another CPU.
+// It schedules a DPC on each of the other CPUs and spins until all
+// CPUs are executing the DPC, which will in-turn spin awaiting
+// further instruction.
//
-// - It raises to DISPATCH_LEVEL to avoid pre-emption and schedules
-// a DPC on each of the other CPUs.
+// - SyncDisableInterrputs() instructs the DPC routines to all raise
+// to HIGH_LEVEL and disable interrupts for its CPU. It then raises
+// to HIGH_LEVEL itself, spins waiting for confirmation from each
+// DPC that it has disabled interrupts and then disables interrupts
+// itself.
//
-// - It, and the DPC routines, all raise to HIGH_LEVEL, clear a
-// a bit corresponding to their CPU in a 'captured' mask, and then
-// spin waiting for the mask to become zero (i.e. all CPUs captured).
+// NOTE: There is a back-off in trying to disable interrupts. It is
+// possible that CPU A is waiting for an IPI to CPU B to
+// complete, but CPU B is spinning with interrupts disabled.
+// Thus the DPC on CPU A will never make it to HIGH_LEVEL and
+// hence never get to disable interrupts. Thus if, while
+// spinning with interrupts disabled, one DPC notices that
+// another DPC has not made it, it briefly enables interrupts
+// and drops back down to DISPATCH_LEVEL before trying again.
+// This should allow any pending IPI to complete.
//
-// NOTE: There is a back-off in this spin. It is possible that CPU A
-// is waiting for an IPI to CPU B to complete, but CPU B is
-// spinning at HIGH_LEVEL. Thus CPU A will never make it to
-// HIGH_LEVEL. Thus if, while spinning at HIGH_LEVEL, we notice
-// that another CPU has not made it, we set our bit in the
-// 'captured' mask again and briefly drop down to DISPATCH_LEVEL
-// before trying again. This should allow any pending IPI to
-// complete.
+// - SyncEnableInterrupts() instructs the DPC routines to all enable
+// interrupts and drop back to DISPATCH_LEVEL before enabling
+// interrupts and dropping back to DISPATCH_LEVEL itself.
//
-// - Once all CPUs are captured, each disables interrupts, executes an
-// optional function. All the DPC routined clear a bit corresponding
-// to their CPU in a 'completed' mask and then spin waiting for the
-// mask to become zero. The requesting CPU also executes the optional
-// function bit it then waits for the mask to only contain the bit
-// corresponding to its CPU and then returns from
-// SyncCaptureAndCall() at HIGH_LEVEL.
-//
-// - A subsequent call to SyncRelease() will clear the last
-// remaining bit (clearly it is necessarily executed on the same CPU
-// as SyncCaptureAndCall()) and thus allow all the DPC
-// routines to lower back to DISPATCH_LEVEL and complete.
-//
-// - SyncRelease() also lowers back to DISPATCH_LEVEL and then
-// back to the IRQL is was originally entered at.
+// - SyncRelease() instructs the DPC routines to exit, thus allowing
+// the scheduler to run on the other CPUs again. It spins until all
+// DPCs have completed and then returns.
+
+#pragma data_seg("sync")
+__declspec(allocate("sync"))
+static UCHAR __Section[PAGE_SIZE];
+
+typedef struct _SYNC_PROCESSOR {
+ KDPC Dpc;
+ BOOLEAN DisableInterrupts;
+ BOOLEAN Exit;
+} SYNC_PROCESSOR, *PSYNC_PROCESSOR;
typedef struct _SYNC_CONTEXT {
- KDPC Dpc[MAXIMUM_PROCESSORS];
ULONG Sequence;
- LONG CpuCount;
+ LONG ProcessorCount;
LONG CompletionCount;
- BOOLEAN DisableInterrupts[MAXIMUM_PROCESSORS];
- BOOLEAN Exit[MAXIMUM_PROCESSORS];
+ SYNC_PROCESSOR Processor[1];
} SYNC_CONTEXT, *PSYNC_CONTEXT;
-static LONG SyncOwner = MAXIMUM_PROCESSORS;
+static PSYNC_CONTEXT SyncContext = (PVOID)__Section;
+static LONG SyncOwner = -1;
static FORCEINLINE VOID
__SyncAcquire(
- IN LONG Cpu
+ IN LONG Index
)
{
LONG Old;
- Old = InterlockedExchange(&SyncOwner, Cpu);
- ASSERT3U(Old, ==, MAXIMUM_PROCESSORS);
+ Old = InterlockedExchange(&SyncOwner, Index);
+ ASSERT3U(Old, ==, -1);
}
static FORCEINLINE VOID
__SyncRelease(
- IN LONG Cpu
+ IN LONG Index
)
{
LONG Old;
- Old = InterlockedExchange(&SyncOwner, MAXIMUM_PROCESSORS);
- ASSERT3U(Old, ==, Cpu);
+ Old = InterlockedExchange(&SyncOwner, -1);
+ ASSERT3U(Old, ==, Index);
}
-static SYNC_CONTEXT SyncContext;
KDEFERRED_ROUTINE SyncWorker;
VOID
#pragma prefast(suppress:28166) // Function does not restore IRQL
SyncWorker(
- IN PKDPC Dpc,
- IN PVOID Context,
- IN PVOID Argument1,
- IN PVOID Argument2
+ IN PKDPC Dpc,
+ IN PVOID _Context,
+ IN PVOID Argument1,
+ IN PVOID Argument2
)
{
- BOOLEAN InterruptsDisabled;
- ULONG Cpu;
+ PSYNC_CONTEXT Context = SyncContext;
+ BOOLEAN InterruptsDisabled;
+ ULONG Index;
+ PSYNC_PROCESSOR Processor;
+ PROCESSOR_NUMBER ProcNumber;
UNREFERENCED_PARAMETER(Dpc);
- UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(_Context);
UNREFERENCED_PARAMETER(Argument1);
UNREFERENCED_PARAMETER(Argument2);
InterruptsDisabled = FALSE;
- Cpu = KeGetCurrentProcessorNumber();
+ Index = KeGetCurrentProcessorNumberEx(&ProcNumber);
+ Processor = &Context->Processor[Index];
- Trace("====> (%u)\n", Cpu);
- InterlockedIncrement(&SyncContext.CompletionCount);
+ Trace("====> (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
+ InterlockedIncrement(&Context->CompletionCount);
for (;;) {
ULONG Sequence;
- if (SyncContext.Exit[Cpu])
+ if (Processor->Exit)
break;
- if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
+ if (Processor->DisableInterrupts == InterruptsDisabled) {
_mm_pause();
KeMemoryBarrier();
continue;
}
- Sequence = SyncContext.Sequence;
+ Sequence = Context->Sequence;
- if (SyncContext.DisableInterrupts[Cpu]) {
+ if (Processor->DisableInterrupts) {
ULONG Attempts;
NTSTATUS status;
(VOID) KfRaiseIrql(HIGH_LEVEL);
status = STATUS_SUCCESS;
- InterlockedIncrement(&SyncContext.CompletionCount);
+ InterlockedIncrement(&Context->CompletionCount);
Attempts = 0;
- while (SyncContext.Sequence == Sequence &&
- SyncContext.CompletionCount < SyncContext.CpuCount) {
+ while (Context->Sequence == Sequence &&
+ Context->CompletionCount < Context->ProcessorCount) {
_mm_pause();
KeMemoryBarrier();
LONG New;
do {
- Old = SyncContext.CompletionCount;
+ Old = Context->CompletionCount;
New = Old - 1;
- if (Old == SyncContext.CpuCount)
+ if (Old == Context->ProcessorCount)
break;
- } while (InterlockedCompareExchange(&SyncContext.CompletionCount, New, Old) != Old);
+ } while (InterlockedCompareExchange(&Context->CompletionCount, New, Old) != Old);
- if (Old < SyncContext.CpuCount) {
+ if (Old < Context->ProcessorCount) {
#pragma prefast(suppress:28138) // Use constant rather than variable
KeLowerIrql(DISPATCH_LEVEL);
status = STATUS_UNSUCCESSFUL;
#pragma prefast(suppress:28138) // Use constant rather than variable
KeLowerIrql(DISPATCH_LEVEL);
- InterlockedIncrement(&SyncContext.CompletionCount);
+ InterlockedIncrement(&Context->CompletionCount);
- while (SyncContext.Sequence == Sequence &&
- SyncContext.CompletionCount < SyncContext.CpuCount) {
+ while (Context->Sequence == Sequence &&
+ Context->CompletionCount < Context->ProcessorCount) {
_mm_pause();
KeMemoryBarrier();
}
}
}
- Trace("<==== (%u)\n", Cpu);
- InterlockedIncrement(&SyncContext.CompletionCount);
+ Trace("<==== (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
+ InterlockedIncrement(&Context->CompletionCount);
ASSERT(!InterruptsDisabled);
}
VOID
)
{
- ULONG Cpu;
- ULONG Index;
+ PSYNC_CONTEXT Context = SyncContext;
+ LONG Index;
+ PROCESSOR_NUMBER ProcNumber;
+ USHORT Group;
+ UCHAR Number;
ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
- Cpu = KeGetCurrentProcessorNumber();
- __SyncAcquire(Cpu);
+ Index = KeGetCurrentProcessorNumberEx(&ProcNumber);
+ __SyncAcquire(Index);
- Trace("====> (%u)\n", Cpu);
+ Group = ProcNumber.Group;
+ Number = ProcNumber.Number;
- ASSERT(IsZeroMemory(&SyncContext, sizeof (SYNC_CONTEXT)));
+ Trace("====> (%u:%u)\n", Group, Number);
- SyncContext.Sequence++;
- SyncContext.CompletionCount = 0;
- SyncContext.CpuCount = KeQueryActiveProcessorCount(NULL);
+ ASSERT(IsZeroMemory(Context, sizeof (SYNC_CONTEXT)));
- for (Index = 0; Index < (ULONG)SyncContext.CpuCount; Index++) {
- PKDPC Dpc = &SyncContext.Dpc[Index];
+ Context->Sequence++;
+ Context->CompletionCount = 0;
- SyncContext.DisableInterrupts[Index] = FALSE;
- SyncContext.Exit[Index] = FALSE;
+ Context->ProcessorCount = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
- if (Index == Cpu)
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PSYNC_PROCESSOR Processor = &Context->Processor[Index];
+ NTSTATUS status;
+
+ ASSERT3U((ULONG_PTR)(Processor + 1), <, (ULONG_PTR)__Section + PAGE_SIZE);
+
+ status = KeGetProcessorNumberFromIndex(Index, &ProcNumber);
+ ASSERT(NT_SUCCESS(status));
+
+ if (ProcNumber.Group == Group &&
+ ProcNumber.Number == Number)
continue;
- KeInitializeDpc(Dpc, SyncWorker, NULL);
- KeSetTargetProcessorDpc(Dpc, (CCHAR)Index);
- KeInsertQueueDpc(Dpc, NULL, NULL);
+ KeInitializeDpc(&Processor->Dpc, SyncWorker, NULL);
+ KeSetTargetProcessorDpcEx(&Processor->Dpc, &ProcNumber);
+ KeInsertQueueDpc(&Processor->Dpc, NULL, NULL);
}
- InterlockedIncrement(&SyncContext.CompletionCount);
+ InterlockedIncrement(&Context->CompletionCount);
- while (SyncContext.CompletionCount < SyncContext.CpuCount) {
+ while (Context->CompletionCount < Context->ProcessorCount) {
_mm_pause();
KeMemoryBarrier();
}
- Trace("<==== (%u)\n", Cpu);
+ Trace("<==== (%u:%u)\n", Group, Number);
}
__drv_requiresIRQL(DISPATCH_LEVEL)
VOID
)
{
- ULONG Index;
- ULONG Attempts;
- NTSTATUS status;
+ PSYNC_CONTEXT Context = SyncContext;
+ LONG Index;
+ ULONG Attempts;
+ NTSTATUS status;
Trace("====>\n");
- SyncContext.Sequence++;
- SyncContext.CompletionCount = 0;
+ Context->Sequence++;
+ Context->CompletionCount = 0;
+
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PSYNC_PROCESSOR Processor = &Context->Processor[Index];
- for (Index = 0; Index < (ULONG)SyncContext.CpuCount; Index++)
- SyncContext.DisableInterrupts[Index] = TRUE;
+ Processor->DisableInterrupts = TRUE;
+ }
+
+ KeMemoryBarrier();
again:
(VOID) KfRaiseIrql(HIGH_LEVEL);
status = STATUS_SUCCESS;
- InterlockedIncrement(&SyncContext.CompletionCount);
+ InterlockedIncrement(&Context->CompletionCount);
Attempts = 0;
- while (SyncContext.CompletionCount < SyncContext.CpuCount) {
+ while (Context->CompletionCount < Context->ProcessorCount) {
_mm_pause();
KeMemoryBarrier();
LONG New;
do {
- Old = SyncContext.CompletionCount;
+ Old = Context->CompletionCount;
New = Old - 1;
- if (Old == SyncContext.CpuCount)
+ if (Old == Context->ProcessorCount)
break;
- } while (InterlockedCompareExchange(&SyncContext.CompletionCount, New, Old) != Old);
+ } while (InterlockedCompareExchange(&Context->CompletionCount, New, Old) != Old);
- if (Old < SyncContext.CpuCount) {
+ if (Old < Context->ProcessorCount) {
LogPrintf(LOG_LEVEL_WARNING,
"SYNC: %d < %d\n",
Old,
- SyncContext.CpuCount);
+ Context->ProcessorCount);
#pragma prefast(suppress:28138) // Use constant rather than variable
KeLowerIrql(DISPATCH_LEVEL);
SyncEnableInterrupts(
)
{
- KIRQL Irql;
- ULONG Index;
+ PSYNC_CONTEXT Context = SyncContext;
+ KIRQL Irql;
+ LONG Index;
_enable();
Irql = KeGetCurrentIrql();
ASSERT3U(Irql, ==, HIGH_LEVEL);
- SyncContext.Sequence++;
- SyncContext.CompletionCount = 0;
+ Context->Sequence++;
+ Context->CompletionCount = 0;
+
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PSYNC_PROCESSOR Processor = &Context->Processor[Index];
+
+ Processor->DisableInterrupts = FALSE;
+ }
- for (Index = 0; Index < (ULONG)SyncContext.CpuCount; Index++)
- SyncContext.DisableInterrupts[Index] = FALSE;
+ KeMemoryBarrier();
- InterlockedIncrement(&SyncContext.CompletionCount);
+ InterlockedIncrement(&Context->CompletionCount);
- while (SyncContext.CompletionCount < SyncContext.CpuCount) {
+ while (Context->CompletionCount < Context->ProcessorCount) {
_mm_pause();
KeMemoryBarrier();
}
VOID
)
{
- ULONG Cpu;
- ULONG Index;
+ PSYNC_CONTEXT Context = SyncContext;
+ LONG Index;
Trace("====>\n");
- SyncContext.Sequence++;
- SyncContext.CompletionCount = 0;
+ Context->Sequence++;
+ Context->CompletionCount = 0;
+
+ for (Index = 0; Index < Context->ProcessorCount; Index++) {
+ PSYNC_PROCESSOR Processor = &Context->Processor[Index];
+
+ Processor->Exit = TRUE;
+ }
- for (Index = 0; Index < (ULONG)SyncContext.CpuCount; Index++)
- SyncContext.Exit[Index] = TRUE;
+ KeMemoryBarrier();
- InterlockedIncrement(&SyncContext.CompletionCount);
+ InterlockedIncrement(&Context->CompletionCount);
- while (SyncContext.CompletionCount < SyncContext.CpuCount) {
+ while (Context->CompletionCount < Context->ProcessorCount) {
_mm_pause();
KeMemoryBarrier();
}
- RtlZeroMemory(&SyncContext, sizeof (SYNC_CONTEXT));
+ RtlZeroMemory(Context, sizeof (SYNC_CONTEXT));
- Cpu = KeGetCurrentProcessorNumber();
- __SyncRelease(Cpu);
+ Index = KeGetCurrentProcessorNumberEx(NULL);
+ __SyncRelease(Index);
Trace("<====\n");
}
*/
#include <ntddk.h>
+#include <procgrp.h>
#include <xen.h>
#include "registry.h"
ASSERT3P(__DriverGetDriverObject(), ==, NULL);
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+ WdmlibProcgrpInitialize();
__DbgPrintEnable();
<Inputs>..\..\include\version.hx</Inputs>
</CustomBuildStep>
<ClCompile>
- <PreprocessorDefinitions>__MODULE__="XEN";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>__MODULE__="XEN";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- <AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>../../src/xen/xen.def</ModuleDefinitionFile>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
</Link>
<Inputs>..\..\src\xenbus.inf</Inputs>
</CustomBuildStep>
<ClCompile>
- <PreprocessorDefinitions>__MODULE__="XENBUS";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>__MODULE__="XENBUS";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
</Link>
<Inf>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
- <PreprocessorDefinitions>__MODULE__="XENFILT";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>__MODULE__="XENFILT";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
</Link>
<Inf>
</CustomBuildStep>
<ClCompile>
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>__MODULE__="XEN";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>__MODULE__="XEN";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ResourceCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- <AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>../../src/xen/xen.def</ModuleDefinitionFile>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
</Link>
<Inputs>..\..\src\xenbus.inf</Inputs>
</CustomBuildStep>
<ClCompile>
- <PreprocessorDefinitions>__MODULE__="XENBUS";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>__MODULE__="XENBUS";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;..\..\src\common;</AdditionalIncludeDirectories>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ResourceCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
</Link>
<Inf>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
- <PreprocessorDefinitions>__MODULE__="XENFILT";POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>__MODULE__="XENFILT";POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;..\..\src\common;</AdditionalIncludeDirectories>
<WarningLevel>EnableAllWarnings</WarningLevel>
<DisableSpecificWarnings>4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ResourceCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
- <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(ProjectDir)..\$(ConfigurationName)\$(Platform)\xen.lib;$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/procgrp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<EnableCOMDATFolding>false</EnableCOMDATFolding>
</Link>
<Inf>