[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH xenbus 4/4] Don't restrict event channels to vCPU 0...
From: Paul Durrant <pdurrant@xxxxxxxxxx> ... when using the 2-level event channel ABI. With a small modification to track port numbers per-vcpu, the 2-level polling code will happily deal with event channels bound to any vCPU up to XEN_LEGACY_MAX_VCPUS. We just need to be careful to only process events on the correct vCPU, to avoid list corruption. Hence, the newly introduced 'Pending' flag needs to be set atomically in case we re-bind an event channel whilst a poll is in progress. The XEN_LEGACY_MAX_VCPUS limit is because the 2-level poll currently relies on using the vcpu_info array embedded in the shared_info. This limit will be removed in a subsequent patch. Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx> --- src/xenbus/evtchn.c | 51 ++++++++++++++++++++++++++-------------- src/xenbus/evtchn_2l.c | 16 ++++--------- src/xenbus/shared_info.c | 8 +++---- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c index e32cb629a101..662ca038fc31 100644 --- a/src/xenbus/evtchn.c +++ b/src/xenbus/evtchn.c @@ -77,6 +77,7 @@ struct _XENBUS_EVTCHN_CHANNEL { KSPIN_LOCK Lock; LIST_ENTRY ListEntry; LIST_ENTRY PendingListEntry; + LONG Pending; PVOID Caller; PKSERVICE_ROUTINE Callback; PVOID Argument; @@ -378,8 +379,6 @@ EvtchnOpen( Trace("%u\n", LocalPort); - InitializeListHead(&Channel->PendingListEntry); - status = XENBUS_EVTCHN_ABI(PortEnable, &Context->EvtchnAbi, LocalPort); @@ -414,9 +413,6 @@ fail4: fail3: Error("fail3\n"); - ASSERT(IsListEmpty(&Channel->PendingListEntry)); - RtlZeroMemory(&Channel->PendingListEntry, sizeof (LIST_ENTRY)); - Channel->LocalPort = 0; Channel->Mask = FALSE; RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS)); @@ -471,9 +467,6 @@ EvtchnReap( Channel->Cpu = 0; - ASSERT(IsListEmpty(&Channel->PendingListEntry)); - RtlZeroMemory(&Channel->PendingListEntry, sizeof (LIST_ENTRY)); - Channel->LocalPort = 0; Channel->Mask = FALSE; RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS)); @@ -501,8 +494,8 @@ EvtchnPollCallback( { PXENBUS_EVTCHN_PROCESSOR Processor = Argument; PXENBUS_EVTCHN_CONTEXT Context = Processor->Context; + ULONG Cpu = Processor->Cpu; PXENBUS_EVTCHN_CHANNEL Channel; - BOOLEAN Pending; NTSTATUS status; status = HashTableLookup(Context->Table, @@ -513,11 +506,15 @@ EvtchnPollCallback( ASSERT3U(Channel->LocalPort, ==, LocalPort); - Pending = !IsListEmpty(&Channel->PendingListEntry); + if (Channel->Cpu != Cpu) + goto done; + + if (InterlockedBitTestAndSet(&Channel->Pending, 0) == 0) { + ASSERT(IsZeroMemory(&Channel->PendingListEntry, sizeof (LIST_ENTRY))); - if (!Pending) InsertTailList(&Processor->PendingList, &Channel->PendingListEntry); + } done: return FALSE; @@ -558,8 +555,18 @@ EvtchnPoll( KeMemoryBarrier(); if (!Channel->Closed) { + ASSERT(Channel->Pending != 0); + RemoveEntryList(&Channel->PendingListEntry); - InitializeListHead(&Channel->PendingListEntry); + RtlZeroMemory(&Channel->PendingListEntry, sizeof (LIST_ENTRY)); + + // + // Make sure the list removal is complete before we allow the + // channel to be queued again. + // + KeMemoryBarrier(); + + Channel->Pending = 0; if (Channel->Mask) XENBUS_EVTCHN_ABI(PortMask, @@ -583,6 +590,8 @@ EvtchnPoll( #pragma warning(suppress:6387) // NULL argument DoneSomething |= Channel->Callback(NULL, Channel->Argument); } else if (List != NULL) { + ASSERT(Channel->Pending != 0); + RemoveEntryList(&Channel->PendingListEntry); InsertTailList(List, &Channel->PendingListEntry); } @@ -630,7 +639,12 @@ EvtchnFlush( ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); - InitializeListHead(&Channel->PendingListEntry); + ASSERT(Channel->Pending != 0); + + RtlZeroMemory(&Channel->PendingListEntry, sizeof (LIST_ENTRY)); + + // No need to barrier as the event will not be queued again + Channel->Pending = 0; EvtchnReap(Context, Channel, TRUE); } @@ -680,7 +694,7 @@ EvtchnTrigger( ULONG Cpu; PXENBUS_EVTCHN_PROCESSOR Processor; PXENBUS_INTERRUPT Interrupt; - BOOLEAN Pending; + BOOLEAN Queued; ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); @@ -697,15 +711,16 @@ EvtchnTrigger( Irql = FdoAcquireInterruptLock(Context->Fdo, Interrupt); - Pending = !IsListEmpty(&Channel->PendingListEntry); - - if (!Pending) + Queued = FALSE; + if (InterlockedBitTestAndSet(&Channel->Pending, 0) == 0) { InsertTailList(&Processor->PendingList, &Channel->PendingListEntry); + Queued = TRUE; + } FdoReleaseInterruptLock(Context->Fdo, Interrupt, Irql); - if (Pending) + if (!Queued) return; KeInsertQueueDpc(&Processor->Dpc, NULL, NULL); diff --git a/src/xenbus/evtchn_2l.c b/src/xenbus/evtchn_2l.c index 0982b00c97c6..a869e150df29 100644 --- a/src/xenbus/evtchn_2l.c +++ b/src/xenbus/evtchn_2l.c @@ -71,19 +71,13 @@ EvtchnTwoLevelIsProcessorEnabled( IN ULONG Index ) { - unsigned int vcpu_id; - NTSTATUS status; - UNREFERENCED_PARAMETER(_Context); - status = SystemVirtualCpuIndex(Index, &vcpu_id); - if (!NT_SUCCESS(status)) - return FALSE; - - if (vcpu_id != 0) - return FALSE; - - return TRUE; + // + // We currently rely on using the vcpu_info array that is embedded + // in the shared_info. + // + return (Index < XEN_LEGACY_MAX_VCPUS) ? TRUE : FALSE; } static BOOLEAN diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c index aa97255cce95..473088c18c93 100644 --- a/src/xenbus/shared_info.c +++ b/src/xenbus/shared_info.c @@ -48,7 +48,7 @@ struct _XENBUS_SHARED_INFO_CONTEXT { LONG References; PHYSICAL_ADDRESS Address; shared_info_t *Shared; - ULONG Port; + ULONG Port[HVM_MAX_VCPUS]; XENBUS_SUSPEND_INTERFACE SuspendInterface; PXENBUS_SUSPEND_CALLBACK SuspendCallbackEarly; XENBUS_DEBUG_INTERFACE DebugInterface; @@ -204,7 +204,7 @@ SharedInfoEvtchnPoll( KeMemoryBarrier(); - Port = Context->Port; + Port = Context->Port[vcpu_id]; while (SelectorMask != 0) { ULONG SelectorBit; @@ -241,7 +241,7 @@ SharedInfoEvtchnPoll( Port = 0; } - Context->Port = Port; + Context->Port[vcpu_id] = Port; done: return DoneSomething; @@ -652,7 +652,7 @@ SharedInfoRelease ( Trace("====>\n"); - Context->Port = 0; + RtlZeroMemory(Context->Port, sizeof (ULONG) * HVM_MAX_VCPUS); XENBUS_DEBUG(Deregister, &Context->DebugInterface, -- 2.17.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |