IN PINTERFACE Interface
);
+/*! \typedef XENBUS_SHARED_INFO_UPCALL_PENDING
+ \brief Private method for EVTCHN inerface
+*/
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_UPCALL_PENDING)(
+ IN PINTERFACE Interface,
+ IN ULONG Cpu
+ );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVENT)(
+ IN PVOID Argument,
+ IN ULONG Port
+ );
+
/*! \typedef XENBUS_SHARED_INFO_EVTCHN_POLL
\brief Private method for EVTCHN inerface
*/
typedef BOOLEAN
(*XENBUS_SHARED_INFO_EVTCHN_POLL)(
+ IN PINTERFACE Interface,
+ IN ULONG Cpu,
+ IN XENBUS_SHARED_INFO_EVENT Event,
+ IN PVOID Argument
+ );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVTCHN_POLL_V1)(
IN PINTERFACE Interface,
IN BOOLEAN (*Function)(PVOID, ULONG),
IN PVOID Argument
INTERFACE Interface;
XENBUS_SHARED_INFO_ACQUIRE SharedInfoAcquire;
XENBUS_SHARED_INFO_RELEASE SharedInfoRelease;
+ XENBUS_SHARED_INFO_EVTCHN_POLL_V1 SharedInfoEvtchnPollVersion1;
+ XENBUS_SHARED_INFO_EVTCHN_ACK SharedInfoEvtchnAck;
+ XENBUS_SHARED_INFO_EVTCHN_MASK SharedInfoEvtchnMask;
+ XENBUS_SHARED_INFO_EVTCHN_UNMASK SharedInfoEvtchnUnmask;
+ XENBUS_SHARED_INFO_GET_TIME SharedInfoGetTime;
+};
+
+/*! \struct _XENBUS_SHARED_INFO_INTERFACE_V2
+ \brief SHARED_INFO interface version 2
+ \ingroup interfaces
+*/
+struct _XENBUS_SHARED_INFO_INTERFACE_V2 {
+ INTERFACE Interface;
+ XENBUS_SHARED_INFO_ACQUIRE SharedInfoAcquire;
+ XENBUS_SHARED_INFO_RELEASE SharedInfoRelease;
+ XENBUS_SHARED_INFO_UPCALL_PENDING SharedInfoUpcallPending;
XENBUS_SHARED_INFO_EVTCHN_POLL SharedInfoEvtchnPoll;
XENBUS_SHARED_INFO_EVTCHN_ACK SharedInfoEvtchnAck;
XENBUS_SHARED_INFO_EVTCHN_MASK SharedInfoEvtchnMask;
XENBUS_SHARED_INFO_GET_TIME SharedInfoGetTime;
};
-typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
+typedef struct _XENBUS_SHARED_INFO_INTERFACE_V2 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
/*! \def XENBUS_SHARED_INFO
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN 1
-#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX 1
+#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX 2
#endif // _XENBUS_SHARED_INFO_H
LONG References;
PHYSICAL_ADDRESS Address;
shared_info_t *Shared;
+ ULONG Port;
XENBUS_SUSPEND_INTERFACE SuspendInterface;
PXENBUS_SUSPEND_CALLBACK SuspendCallbackEarly;
XENBUS_DEBUG_INTERFACE DebugInterface;
}
static VOID
-SharedInfoMaskAll(
+SharedInfoEvtchnMaskAll(
IN PXENBUS_SHARED_INFO_CONTEXT Context
)
{
}
static BOOLEAN
-SharedInfoEvtchnPoll(
+SharedInfoUpcallPending(
IN PINTERFACE Interface,
- IN BOOLEAN (*Function)(PVOID, ULONG),
- IN PVOID Argument OPTIONAL
+ IN ULONG Cpu
)
{
PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
- shared_info_t *Shared;
- static ULONG Port;
- BOOLEAN DoneSomething;
+ shared_info_t *Shared = Context->Shared;
+ int vcpu_id = SystemVirtualCpuIndex(Cpu);
+ UCHAR Pending;
- Shared = Context->Shared;
+ KeMemoryBarrier();
- DoneSomething = FALSE;
+ Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[vcpu_id].evtchn_upcall_pending, 0);
- for (;;) {
- UCHAR Pending;
- ULONG_PTR SelectorMask;
+ return (Pending != 0) ? TRUE : FALSE;
+}
- KeMemoryBarrier();
+static BOOLEAN
+SharedInfoEvtchnPoll(
+ IN PINTERFACE Interface,
+ IN ULONG Cpu,
+ 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);
+ ULONG Port;
+ ULONG_PTR SelectorMask;
+ BOOLEAN DoneSomething;
- Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[0].evtchn_upcall_pending, 0);
- if (Pending == 0)
- break;
+ DoneSomething = FALSE;
- SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[0].evtchn_pending_sel, (PVOID)0);
+ KeMemoryBarrier();
- KeMemoryBarrier();
+ SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[vcpu_id].evtchn_pending_sel, (PVOID)0);
+
+ KeMemoryBarrier();
- while (SelectorMask != 0) {
- ULONG SelectorBit;
- ULONG PortBit;
+ Port = Context->Port;
- SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
- PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+ while (SelectorMask != 0) {
+ ULONG SelectorBit;
+ ULONG PortBit;
- if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
- ULONG_PTR PortMask;
- PortMask = Shared->evtchn_pending[SelectorBit];
- PortMask &= ~Shared->evtchn_mask[SelectorBit];
+ SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+ PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+ if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
+ ULONG_PTR PortMask;
- while (PortMask != 0 && PortBit < XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
- if (SharedInfoTestBit(&PortMask, PortBit)) {
- DoneSomething |= Function(Argument, (SelectorBit * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
+ PortMask = Shared->evtchn_pending[SelectorBit];
+ PortMask &= ~Shared->evtchn_mask[SelectorBit];
- (VOID) SharedInfoClearBitUnlocked(&PortMask, PortBit);
- }
+ while (PortMask != 0 && PortBit < XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
+ if (SharedInfoTestBit(&PortMask, PortBit)) {
+ DoneSomething |= Event(Argument, (SelectorBit * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
- PortBit++;
+ PortMask &= ~((ULONG_PTR)1 << PortBit);
}
- // Are we done with this selector?
- if (PortMask == 0)
- (VOID) SharedInfoClearBitUnlocked(&SelectorMask, SelectorBit);
+ PortBit++;
}
- Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-
- if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
- Port = 0;
+ // Are we done with this selector?
+ if (PortMask == 0)
+ SelectorMask &= ~((ULONG_PTR)1 << SelectorBit);
}
+
+ Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+ if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
+ Port = 0;
}
+ Context->Port = Port;
+
+ return DoneSomething;
+}
+
+static BOOLEAN
+SharedInfoEvtchnPollVersion1(
+ IN PINTERFACE Interface,
+ IN BOOLEAN (*Function)(PVOID, ULONG),
+ IN PVOID Argument OPTIONAL
+ )
+{
+ BOOLEAN DoneSomething;
+
+ DoneSomething = FALSE;
+
+ while (SharedInfoUpcallPending(Interface, 0))
+ DoneSomething |= SharedInfoEvtchnPoll(Interface,
+ 0,
+ Function,
+ Argument);
+
return DoneSomething;
}
PXENBUS_SHARED_INFO_CONTEXT Context = Argument;
SharedInfoMap(Context);
- SharedInfoMaskAll(Context);
+ SharedInfoEvtchnMaskAll(Context);
}
static VOID
if (!Crashing) {
shared_info_t *Shared;
+ LONG Cpu;
ULONG Selector;
Shared = Context->Shared;
KeMemoryBarrier();
- XENBUS_DEBUG(Printf,
- &Context->DebugInterface,
- "CPU: PENDING: %s SELECTOR MASK: %p\n",
- Shared->vcpu_info[0].evtchn_upcall_pending ? "TRUE" : "FALSE",
- (PVOID)Shared->vcpu_info[0].evtchn_pending_sel);
+ for (Cpu = 0; Cpu < KeNumberProcessors; Cpu++) {
+ int vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+ XENBUS_DEBUG(Printf,
+ &Context->DebugInterface,
+ "CPU %u: PENDING: %s\n",
+ Cpu,
+ Shared->vcpu_info[vcpu_id].evtchn_upcall_pending ?
+ "TRUE" :
+ "FALSE");
+
+ XENBUS_DEBUG(Printf,
+ &Context->DebugInterface,
+ "CPU %u: SELECTOR MASK: %p\n",
+ Cpu,
+ (PVOID)Shared->vcpu_info[vcpu_id].evtchn_pending_sel);
+ }
for (Selector = 0; Selector < XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT; Selector += 4) {
XENBUS_DEBUG(Printf,
if (Context->Shared == NULL)
goto fail2;
- SharedInfoMaskAll(Context);
+ SharedInfoEvtchnMaskAll(Context);
status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
if (!NT_SUCCESS(status))
Trace("====>\n");
+ Context->Port = 0;
+
XENBUS_DEBUG(Deregister,
&Context->DebugInterface,
Context->DebugCallback);
{ sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V1), 1, NULL, NULL, NULL },
SharedInfoAcquire,
SharedInfoRelease,
+ SharedInfoEvtchnPollVersion1,
+ SharedInfoEvtchnAck,
+ SharedInfoEvtchnMask,
+ SharedInfoEvtchnUnmask,
+ SharedInfoGetTime
+};
+
+static struct _XENBUS_SHARED_INFO_INTERFACE_V2 SharedInfoInterfaceVersion2 = {
+ { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2), 2, NULL, NULL, NULL },
+ SharedInfoAcquire,
+ SharedInfoRelease,
+ SharedInfoUpcallPending,
SharedInfoEvtchnPoll,
SharedInfoEvtchnAck,
SharedInfoEvtchnMask,
status = STATUS_SUCCESS;
break;
}
+ case 2: {
+ struct _XENBUS_SHARED_INFO_INTERFACE_V2 *SharedInfoInterface;
+
+ SharedInfoInterface = (struct _XENBUS_SHARED_INFO_INTERFACE_V2 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2))
+ break;
+
+ *SharedInfoInterface = SharedInfoInterfaceVersion2;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;