[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH v3 4/4] Use per-CPU event channel upcalls if available
A recent patch to Xen introduced a new HVM op to set a per-vcpu event channel upcall. This patch adds code to make use of the latched interrupts allocated by the FDO code to enable per-vcpu upcalls and adds an extra EvtchnBind operation to a new v2 EVTCHN interface so that events can be steered to a specified CPU. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/evtchn_interface.h | 35 +++- include/xen.h | 16 ++ src/xen/event_channel.c | 30 ++++ src/xen/hvm.c | 28 ++++ src/xenbus/evtchn.c | 409 +++++++++++++++++++++++++++++++++++++-------- src/xenbus/store.c | 9 + 6 files changed, 453 insertions(+), 74 deletions(-) diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h index 5898e08..4ab2b28 100644 --- a/include/evtchn_interface.h +++ b/include/evtchn_interface.h @@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL ... ); +/*! \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 +*/ +typedef NTSTATUS +(*XENBUS_EVTCHN_BIND)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Cpu + ); + /*! \typedef XENBUS_EVTCHN_UNMASK \brief Unmask an event channel @@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 { XENBUS_EVTCHN_CLOSE EvtchnClose; }; -typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; +/*! \struct _XENBUS_EVTCHN_INTERFACE_V2 + \brief EVTCHN interface version 2 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V2 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK EvtchnUnmask; + XENBUS_EVTCHN_SEND EvtchnSend; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; /*! \def XENBUS_EVTCHN \brief Macro at assist in method invocation @@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT #endif // _WINDLL #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1 -#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1 +#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2 #endif // _XENBUS_EVTCHN_INTERFACE_H diff --git a/include/xen.h b/include/xen.h index 0dabc74..84197a5 100644 --- a/include/xen.h +++ b/include/xen.h @@ -97,6 +97,14 @@ HvmPagetableDying( IN PHYSICAL_ADDRESS Address ); +__checkReturn +XEN_API +NTSTATUS +HvmSetEvtchnUpcallVector( + IN unsigned int vcpu_id, + IN UCHAR Vector + ); + // MEMORY __checkReturn @@ -196,6 +204,14 @@ EventChannelReset( VOID ); +__checkReturn +XEN_API +NTSTATUS +EventChannelBindVirtualCpu( + IN ULONG LocalPort, + IN unsigned int vcpu_id + ); + // GRANT TABLE __checkReturn diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c index aa87fd4..94a6b82 100644 --- a/src/xen/event_channel.c +++ b/src/xen/event_channel.c @@ -327,3 +327,33 @@ fail1: return status; } + +__checkReturn +XEN_API +NTSTATUS +EventChannelBindVirtualCpu( + IN ULONG LocalPort, + IN unsigned int vcpu_id + ) +{ + struct evtchn_bind_vcpu op; + LONG_PTR rc; + NTSTATUS status; + + op.port = LocalPort; + op.vcpu = vcpu_id; + + rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op); + + if (rc < 0) { + ERRNO_TO_STATUS(-rc, status); + goto fail1; + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} diff --git a/src/xen/hvm.c b/src/xen/hvm.c index 8135e97..3e3e12c 100644 --- a/src/xen/hvm.c +++ b/src/xen/hvm.c @@ -166,3 +166,31 @@ HvmPagetableDying( fail1: return status; } + +__checkReturn +XEN_API +NTSTATUS +HvmSetEvtchnUpcallVector( + IN unsigned int vcpu_id, + IN UCHAR Vector + ) +{ + struct xen_hvm_set_evtchn_upcall_vector op; + LONG_PTR rc; + NTSTATUS status; + + op.vcpu = vcpu_id; + op.vector = Vector; + + rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op); + + if (rc < 0) { + ERRNO_TO_STATUS(-rc, status); + goto fail1; + } + + return STATUS_SUCCESS; + +fail1: + return status; +} diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c index 44043d4..c6ac30d 100644 --- a/src/xenbus/evtchn.c +++ b/src/xenbus/evtchn.c @@ -73,6 +73,7 @@ typedef struct _XENBUS_EVTCHN_PARAMETERS { struct _XENBUS_EVTCHN_CHANNEL { ULONG Magic; + KSPIN_LOCK Lock; LIST_ENTRY ListEntry; PVOID Caller; PKSERVICE_ROUTINE Callback; @@ -82,13 +83,17 @@ struct _XENBUS_EVTCHN_CHANNEL { XENBUS_EVTCHN_PARAMETERS Parameters; BOOLEAN Mask; ULONG LocalPort; + ULONG Cpu; + PXENBUS_INTERRUPT Interrupt; }; struct _XENBUS_EVTCHN_CONTEXT { PXENBUS_FDO Fdo; KSPIN_LOCK Lock; LONG References; - PXENBUS_INTERRUPT Interrupt; + PXENBUS_INTERRUPT LevelSensitiveInterrupt; + PXENBUS_INTERRUPT LatchedInterrupt[MAXIMUM_PROCESSORS]; + KAFFINITY Affinity; BOOLEAN Enabled; XENBUS_SUSPEND_INTERFACE SuspendInterface; PXENBUS_SUSPEND_CALLBACK SuspendCallbackEarly; @@ -102,6 +107,7 @@ struct _XENBUS_EVTCHN_CONTEXT { BOOLEAN UseEvtchnFifoAbi; PXENBUS_HASH_TABLE Table; LIST_ENTRY List; + KDPC Dpc; }; #define XENBUS_EVTCHN_TAG 'CTVE' @@ -127,15 +133,39 @@ EvtchnInterruptEnable( IN PXENBUS_EVTCHN_CONTEXT Context ) { + LONG Cpu; ULONG Line; NTSTATUS status; - Trace("<===>\n"); + Trace("====>\n"); + + ASSERT3U(Context->Affinity, ==, 0); + + Cpu = 0; + while (Cpu < KeNumberProcessors) { + unsigned int vcpu_id; + UCHAR Vector; + + vcpu_id = SystemVirtualCpuIndex(Cpu); + Vector = FdoGetInterruptVector(Context->Fdo, + Context->LatchedInterrupt[Cpu]); + + status = HvmSetEvtchnUpcallVector(vcpu_id, Vector); + if (NT_SUCCESS(status)) { + Info("CPU %u\n", Cpu); + Context->Affinity |= (KAFFINITY)1 << Cpu; + } + + Cpu++; + } - Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt); + Line = FdoGetInterruptLine(Context->Fdo, + Context->LevelSensitiveInterrupt); status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line); ASSERT(NT_SUCCESS(status)); + + Trace("<====\n"); } static VOID @@ -143,14 +173,29 @@ EvtchnInterruptDisable( IN PXENBUS_EVTCHN_CONTEXT Context ) { + LONG Cpu; NTSTATUS status; UNREFERENCED_PARAMETER(Context); - Trace("<===>\n"); + Trace("====>\n"); status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0); ASSERT(NT_SUCCESS(status)); + + Cpu = KeNumberProcessors; + while (--Cpu >= 0) { + unsigned int vcpu_id; + + vcpu_id = SystemVirtualCpuIndex(Cpu); + + (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0); + Context->Affinity &= ~((KAFFINITY)1 << Cpu); + } + + ASSERT3U(Context->Affinity, ==, 0); + + Trace("<====\n"); } static FORCEINLINE @@ -159,10 +204,11 @@ _IRQL_saves_ _IRQL_raises_(HIGH_LEVEL) KIRQL __EvtchnAcquireInterruptLock( - IN PXENBUS_EVTCHN_CONTEXT Context + IN PXENBUS_EVTCHN_CONTEXT Context, + IN PXENBUS_EVTCHN_CHANNEL Channel ) { - return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt); + return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt); } static FORCEINLINE @@ -170,10 +216,11 @@ __drv_requiresIRQL(HIGH_LEVEL) VOID __EvtchnReleaseInterruptLock( IN PXENBUS_EVTCHN_CONTEXT Context, + IN PXENBUS_EVTCHN_CHANNEL Channel, IN __drv_restoresIRQL KIRQL Irql ) { - FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql); + FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql); } static NTSTATUS @@ -358,6 +405,11 @@ EvtchnOpen( LocalPort = Channel->LocalPort; + Channel->Cpu = 0; + Channel->Interrupt = (Context->Affinity != 0) ? // Latched available + Context->LatchedInterrupt[0] : + Context->LevelSensitiveInterrupt; + status = XENBUS_EVTCHN_ABI(PortEnable, &Context->EvtchnAbi, LocalPort); @@ -385,6 +437,8 @@ EvtchnOpen( KeLowerIrql(Irql); + KeInitializeSpinLock(&Channel->Lock); + return Channel; fail4: @@ -422,6 +476,150 @@ fail1: return NULL; } +#define EVTCHN_SWAP_POINTER(_X, _Y) \ + do { \ + (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y)); \ + (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y)); \ + (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y)); \ + } while (FALSE) + +static NTSTATUS +EvtchnBind( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Cpu + ) +{ + PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; + PXENBUS_INTERRUPT Interrupt; + ULONG LocalPort; + unsigned int vcpu_id; + KIRQL Irql; + NTSTATUS status; + + status = STATUS_INVALID_PARAMETER; + if (Cpu >= (ULONG)KeNumberProcessors) + goto fail1; + + ASSERT(Context->Enabled); + + status = STATUS_NOT_SUPPORTED; + if (~Context->Affinity & ((KAFFINITY)1 << Cpu)) + goto fail2; + + KeAcquireSpinLock(&Channel->Lock, &Irql); + + if (Channel->Cpu == Cpu) + goto done; + + Interrupt = Context->LatchedInterrupt[Cpu]; + + (VOID) KfRaiseIrql(HIGH_LEVEL); + + // Make sure we always lock in a consistent order + if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) { + (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt); + (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt); + } else { + (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt); + (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt); + } + + LocalPort = Channel->LocalPort; + vcpu_id = SystemVirtualCpuIndex(Cpu); + + status = EventChannelBindVirtualCpu(LocalPort, vcpu_id); + if (!NT_SUCCESS(status)) + goto fail3; + + EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt); + Channel->Cpu = Cpu; + + FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL); + FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL); + +#pragma prefast(suppress:28138) // Use constant rather than variable + KeLowerIrql(DISPATCH_LEVEL); + + Info("[%u]: CPU %u\n", LocalPort, Cpu); + +done: + KeReleaseSpinLock(&Channel->Lock, Irql); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + + FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL); + FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL); + +#pragma prefast(suppress:28138) // Use constant rather than variable + KeLowerIrql(DISPATCH_LEVEL); + + KeReleaseSpinLock(&Channel->Lock, Irql); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static +_Function_class_(KDEFERRED_ROUTINE) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_min_(DISPATCH_LEVEL) +_IRQL_requires_(DISPATCH_LEVEL) +_IRQL_requires_same_ +VOID +EvtchnCallback( + IN PKDPC Dpc, + IN PVOID _Context, + IN PVOID Argument1, + IN PVOID Argument2 + ) +{ + PXENBUS_EVTCHN_CONTEXT Context = _Context; + PXENBUS_EVTCHN_CHANNEL Channel = Argument1; + KIRQL Irql; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(Argument2); + + if (!Channel->Active) + return; + + Irql = __EvtchnAcquireInterruptLock(Context, Channel); + +#pragma warning(suppress:6387) // NULL argument + (VOID) Channel->Callback(NULL, Channel->Argument); + + __EvtchnReleaseInterruptLock(Context, Channel, Irql); +} + +static VOID +EvtchnTrigger( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ) +{ + PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; + PKDPC Dpc = &Context->Dpc; + KIRQL Irql; + + ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); + + KeAcquireSpinLock(&Channel->Lock, &Irql); + + KeSetTargetProcessorDpc(Dpc, (CCHAR)Channel->Cpu); + KeInsertQueueDpc(Dpc, Channel, NULL); + + KeReleaseSpinLock(&Channel->Lock, Irql); +} + static BOOLEAN EvtchnUnmask( IN PINTERFACE Interface, @@ -432,27 +630,55 @@ EvtchnUnmask( PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; KIRQL Irql = PASSIVE_LEVEL; BOOLEAN Pending = FALSE; + ULONG Cpu; + PXENBUS_INTERRUPT Interrupt; ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); if (!InCallback) - KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend + KeAcquireSpinLock(&Channel->Lock, &Irql); ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); - if (Channel->Active) { - Pending = XENBUS_EVTCHN_ABI(PortUnmask, - &Context->EvtchnAbi, - Channel->LocalPort); - - if (Pending && Channel->Mask) - XENBUS_EVTCHN_ABI(PortMask, - &Context->EvtchnAbi, - Channel->LocalPort); - } + if (!Channel->Active) + goto done; + + Pending = XENBUS_EVTCHN_ABI(PortUnmask, + &Context->EvtchnAbi, + Channel->LocalPort); + + if (!Pending) + goto done; + + if (InCallback) + goto mask; + + ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); + Cpu = KeGetCurrentProcessorNumber(); + + Interrupt = Context->LatchedInterrupt[Cpu]; + + if (Channel->Interrupt == Interrupt) + goto mask; + // + // We are not on the CPU to which the event is bound so + // we must trigger. + // + EvtchnTrigger(Interface, Channel); + + Pending = FALSE; + goto done; + +mask: + if (Channel->Mask) + XENBUS_EVTCHN_ABI(PortMask, + &Context->EvtchnAbi, + Channel->LocalPort); + +done: if (!InCallback) - KeLowerIrql(Irql); + KeReleaseSpinLock(&Channel->Lock, Irql); return Pending; } @@ -485,53 +711,6 @@ done: return status; } -static BOOLEAN -EvtchnCallback( - IN PXENBUS_EVTCHN_CONTEXT Context, - IN PXENBUS_EVTCHN_CHANNEL Channel - ) -{ - BOOLEAN DoneSomething; - - UNREFERENCED_PARAMETER(Context); - - ASSERT(Channel != NULL); - ASSERT(Channel->Active); - -#pragma warning(suppress:6387) // NULL argument - DoneSomething = Channel->Callback(NULL, Channel->Argument); - - return DoneSomething; -} - -static BOOLEAN -EvtchnTrigger( - IN PINTERFACE Interface, - IN PXENBUS_EVTCHN_CHANNEL Channel - ) -{ - PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; - KIRQL Irql; - BOOLEAN DoneSomething; - - ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); - - Irql = __EvtchnAcquireInterruptLock(Context); - - ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); - - if (Channel->Active) { - DoneSomething = EvtchnCallback(Context, Channel); - } else { - Warning("[%d]: INVALID PORT\n", Channel->LocalPort); - DoneSomething = FALSE; - } - - __EvtchnReleaseInterruptLock(Context, Irql); - - return DoneSomething; -} - static VOID EvtchnClose( IN PINTERFACE Interface, @@ -543,6 +722,8 @@ EvtchnClose( ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); + RtlZeroMemory(&Channel->Lock, sizeof (KSPIN_LOCK)); + KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend KeAcquireSpinLockAtDpcLevel(&Context->Lock); @@ -575,6 +756,9 @@ EvtchnClose( ASSERT(NT_SUCCESS(status)); } + Channel->Interrupt = NULL; + Channel->Cpu = 0; + Channel->LocalPort = 0; RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS)); @@ -617,6 +801,8 @@ EvtchnPollCallback( BOOLEAN DoneSomething; NTSTATUS status; + DoneSomething = FALSE; + status = HashTableLookup(Context->Table, LocalPort, (PULONG_PTR)&Channel); @@ -628,10 +814,20 @@ EvtchnPollCallback( &Context->EvtchnAbi, LocalPort); - DoneSomething = FALSE; goto done; } + if (Context->Affinity != 0) { + ULONG Cpu; + + ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); + Cpu = KeGetCurrentProcessorNumber(); + + // Only handle events on the correct CPU + if (Channel->Interrupt != Context->LatchedInterrupt[Cpu]) + goto done; + } + if (Channel->Mask) XENBUS_EVTCHN_ABI(PortMask, &Context->EvtchnAbi, @@ -641,7 +837,8 @@ EvtchnPollCallback( &Context->EvtchnAbi, LocalPort); - DoneSomething = EvtchnCallback(Context, Channel); +#pragma warning(suppress:6387) // NULL argument + DoneSomething = Channel->Callback(NULL, Channel->Argument); done: return DoneSomething; @@ -767,8 +964,10 @@ EvtchnSuspendCallbackLate( status = EvtchnAbiAcquire(Context); ASSERT(NT_SUCCESS(status)); - if (Context->Enabled) + if (Context->Enabled) { + EvtchnInterruptDisable(Context); EvtchnInterruptEnable(Context); + } } static VOID @@ -862,6 +1061,7 @@ EvtchnAcquire( PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; PXENBUS_FDO Fdo = Context->Fdo; KIRQL Irql; + LONG Cpu; NTSTATUS status; KeAcquireSpinLock(&Context->Lock, &Irql); @@ -919,10 +1119,24 @@ EvtchnAcquire( 0, EvtchnInterruptCallback, Context, - &Context->Interrupt); + &Context->LevelSensitiveInterrupt); if (!NT_SUCCESS(status)) goto fail8; + Cpu = 0; + while (Cpu < KeNumberProcessors) { + status = FdoAllocateInterrupt(Fdo, + Latched, + Cpu, + EvtchnInterruptCallback, + Context, + &Context->LatchedInterrupt[Cpu]); + if (!NT_SUCCESS(status)) + goto fail9; + + Cpu++; + } + Trace("<====\n"); done: @@ -930,6 +1144,17 @@ done: return STATUS_SUCCESS; +fail9: + Error("fail9\n"); + + while (--Cpu >= 0) { + FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]); + Context->LatchedInterrupt[Cpu] = NULL; + } + + FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt); + Context->LevelSensitiveInterrupt = NULL; + fail8: Error("fail8\n"); @@ -990,7 +1215,9 @@ EvtchnRelease( ) { PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; + PXENBUS_FDO Fdo = Context->Fdo; KIRQL Irql; + LONG Cpu; KeAcquireSpinLock(&Context->Lock, &Irql); @@ -1002,8 +1229,14 @@ EvtchnRelease( if (!IsListEmpty(&Context->List)) BUG("OUTSTANDING EVENT CHANNELS"); - FdoFreeInterrupt(Context->Fdo, Context->Interrupt); - Context->Interrupt = NULL; + Cpu = KeNumberProcessors; + while (--Cpu >= 0) { + FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]); + Context->LatchedInterrupt[Cpu] = NULL; + } + + FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt); + Context->LevelSensitiveInterrupt = NULL; EvtchnAbiRelease(Context); @@ -1046,6 +1279,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = { EvtchnClose }; +static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = { + { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL }, + EvtchnAcquire, + EvtchnRelease, + EvtchnOpen, + EvtchnBind, + EvtchnUnmask, + EvtchnSend, + EvtchnTrigger, + EvtchnGetPort, + EvtchnClose +}; + NTSTATUS EvtchnInitialize( IN PXENBUS_FDO Fdo, @@ -1110,6 +1356,7 @@ EvtchnInitialize( InitializeListHead(&(*Context)->List); KeInitializeSpinLock(&(*Context)->Lock); + KeInitializeDpc(&(*Context)->Dpc, EvtchnCallback, Context); (*Context)->Fdo = Fdo; @@ -1171,6 +1418,23 @@ EvtchnGetInterface( status = STATUS_SUCCESS; break; } + case 2: { + struct _XENBUS_EVTCHN_INTERFACE_V2 *EvtchnInterface; + + EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface; + + status = STATUS_BUFFER_OVERFLOW; + if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2)) + break; + + *EvtchnInterface = EvtchnInterfaceVersion2; + + ASSERT3U(Interface->Version, ==, Version); + Interface->Context = Context; + + status = STATUS_SUCCESS; + break; + } default: status = STATUS_NOT_SUPPORTED; break; @@ -1188,6 +1452,7 @@ EvtchnTeardown( Context->Fdo = NULL; + RtlZeroMemory(&Context->Dpc, sizeof (KDPC)); RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK)); RtlZeroMemory(&Context->List, sizeof (LIST_ENTRY)); diff --git a/src/xenbus/store.c b/src/xenbus/store.c index 22c2a12..04fce3a 100644 --- a/src/xenbus/store.c +++ b/src/xenbus/store.c @@ -1848,6 +1848,15 @@ StoreEnable( FALSE); ASSERT(Context->Channel != NULL); + // + // Attempt to use some CPU other than 0 for events from + // xenstored. + // + (VOID) XENBUS_EVTCHN(Bind, + &Context->EvtchnInterface, + Context->Channel, + KeNumberProcessors - 1); + Pending = XENBUS_EVTCHN(Unmask, &Context->EvtchnInterface, Context->Channel, -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |