From d1464e8eda059aedd37b9d01b8ae44deb0002334 Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Tue, 17 Nov 2020 12:51:34 +0000 Subject: [PATCH] extend evtchn api with virq cpu binding Signed-off-by: Paul Durrant --- include/evtchn_interface.h | 25 +++++++- include/revision.h | 3 +- include/xen.h | 9 +-- src/common/names.h | 22 +++++++ src/xen/event_channel.c | 5 +- src/xenbus/evtchn.c | 117 ++++++++++++++++++++++++++++++++----- src/xenbus/fdo.c | 25 ++++++-- 7 files changed, 176 insertions(+), 30 deletions(-) diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h index ade7259..fffde05 100644 --- a/include/evtchn_interface.h +++ b/include/evtchn_interface.h @@ -100,6 +100,8 @@ typedef VOID \b VIRQ: \param Index The index number of the VIRQ + \param Group The group number of the CPU that should handle the VIRQ + \param Number The relative number of the CPU that should handle the VIRQ \return Event channel handle */ @@ -340,7 +342,26 @@ struct _XENBUS_EVTCHN_INTERFACE_V8 { XENBUS_EVTCHN_CLOSE EvtchnClose; }; -typedef struct _XENBUS_EVTCHN_INTERFACE_V8 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; +/*! \struct _XENBUS_EVTCHN_INTERFACE_V9 + \brief EVTCHN interface version 9 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V9 { + 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_COUNT EvtchnGetCount; + XENBUS_EVTCHN_WAIT EvtchnWait; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +typedef struct _XENBUS_EVTCHN_INTERFACE_V9 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; /*! \def XENBUS_EVTCHN \brief Macro at assist in method invocation @@ -351,7 +372,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V8 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT #endif // _WINDLL #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 4 -#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 8 +#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 9 #endif // _XENBUS_EVTCHN_INTERFACE_H diff --git a/include/revision.h b/include/revision.h index 01b6737..3a6b398 100644 --- a/include/revision.h +++ b/include/revision.h @@ -57,6 +57,7 @@ DEFINE_REVISION(0x09000004, 1, 2, 8, 1, 2, 1, 1, 3, 1, 1, 1), \ DEFINE_REVISION(0x09000005, 1, 2, 8, 1, 2, 1, 2, 4, 1, 1, 1), \ DEFINE_REVISION(0x09000006, 1, 3, 8, 1, 2, 1, 2, 4, 1, 1, 1), \ - DEFINE_REVISION(0x09000007, 1, 3, 8, 1, 2, 1, 2, 4, 1, 1, 2) + DEFINE_REVISION(0x09000007, 1, 3, 8, 1, 2, 1, 2, 4, 1, 1, 2), \ + DEFINE_REVISION(0x09000008, 1, 3, 9, 1, 2, 1, 2, 4, 1, 1, 2) #endif // _REVISION_H diff --git a/include/xen.h b/include/xen.h index 171fa4e..a85c07b 100644 --- a/include/xen.h +++ b/include/xen.h @@ -178,6 +178,7 @@ XEN_API NTSTATUS EventChannelBindVirq( IN uint32_t Virq, + IN unsigned int vcpu_id, OUT evtchn_port_t *LocalPort ); @@ -208,8 +209,8 @@ __checkReturn XEN_API NTSTATUS EventChannelInitControl( - IN PFN_NUMBER Pfn, - IN unsigned int vcpu_id + IN PFN_NUMBER Pfn, + IN unsigned int vcpu_id ); __checkReturn @@ -223,8 +224,8 @@ __checkReturn XEN_API NTSTATUS EventChannelBindVirtualCpu( - IN ULONG LocalPort, - IN unsigned int vcpu_id + IN evtchn_port_t LocalPort, + IN unsigned int vcpu_id ); __checkReturn diff --git a/src/common/names.h b/src/common/names.h index 90636bb..84267d1 100644 --- a/src/common/names.h +++ b/src/common/names.h @@ -33,6 +33,7 @@ #define _COMMON_NAMES_H_ #include +#include static FORCEINLINE const CHAR * PowerStateTypeName( @@ -472,4 +473,25 @@ ProcessorChangeName( #undef _PROCESSOR_CHANGE_NAME } +static FORCEINLINE const CHAR * +VirqName( + IN ULONG Type + ) +{ +#define _VIRQ_NAME(_Type) \ + case VIRQ_ ## _Type: \ + return #_Type; + + switch (Type) { + _VIRQ_NAME(DEBUG); + _VIRQ_NAME(TIMER); + default: + break; + } + + return "UNKNOWN"; + +#undef _VIRQ_NAME +} + #endif // _COMMON_NAMES_H_ diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c index aa9fb48..00d4e1c 100644 --- a/src/xen/event_channel.c +++ b/src/xen/event_channel.c @@ -145,6 +145,7 @@ XEN_API NTSTATUS EventChannelBindVirq( IN uint32_t Virq, + IN unsigned int vcpu_id, OUT evtchn_port_t *LocalPort ) { @@ -153,7 +154,7 @@ EventChannelBindVirq( NTSTATUS status; op.virq = Virq; - op.vcpu = 0; + op.vcpu = vcpu_id; rc = EventChannelOp(EVTCHNOP_bind_virq, &op); @@ -332,7 +333,7 @@ __checkReturn XEN_API NTSTATUS EventChannelBindVirtualCpu( - IN ULONG LocalPort, + IN evtchn_port_t LocalPort, IN unsigned int vcpu_id ) { diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c index 8a819f3..4d185c4 100644 --- a/src/xenbus/evtchn.c +++ b/src/xenbus/evtchn.c @@ -138,13 +138,18 @@ __EvtchnFree( static NTSTATUS EvtchnOpenFixed( + IN PXENBUS_EVTCHN_CONTEXT Context, IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Count, IN va_list Arguments ) { ULONG LocalPort; BOOLEAN Mask; + UNREFERENCED_PARAMETER(Context); + + ASSERT3U(Count, ==, 2); LocalPort = va_arg(Arguments, ULONG); Mask = va_arg(Arguments, BOOLEAN); @@ -156,7 +161,9 @@ EvtchnOpenFixed( static NTSTATUS EvtchnOpenUnbound( + IN PXENBUS_EVTCHN_CONTEXT Context, IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Count, IN va_list Arguments ) { @@ -165,6 +172,9 @@ EvtchnOpenUnbound( ULONG LocalPort; NTSTATUS status; + UNREFERENCED_PARAMETER(Context); + + ASSERT3U(Count, ==, 2); RemoteDomain = va_arg(Arguments, USHORT); Mask = va_arg(Arguments, BOOLEAN); @@ -187,7 +197,9 @@ fail1: static NTSTATUS EvtchnOpenInterDomain( + IN PXENBUS_EVTCHN_CONTEXT Context, IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Count, IN va_list Arguments ) { @@ -197,6 +209,9 @@ EvtchnOpenInterDomain( ULONG LocalPort; NTSTATUS status; + UNREFERENCED_PARAMETER(Context); + + ASSERT3U(Count, ==, 3); RemoteDomain = va_arg(Arguments, USHORT); RemotePort = va_arg(Arguments, ULONG); Mask = va_arg(Arguments, BOOLEAN); @@ -223,26 +238,63 @@ fail1: static NTSTATUS EvtchnOpenVirq( + IN PXENBUS_EVTCHN_CONTEXT Context, IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Count, IN va_list Arguments ) { ULONG Index; + USHORT Group; + UCHAR Number; + PROCESSOR_NUMBER ProcNumber; + ULONG Cpu; + PXENBUS_EVTCHN_PROCESSOR Processor; + unsigned int vcpu_id; ULONG LocalPort; NTSTATUS status; Index = va_arg(Arguments, ULONG); - status = EventChannelBindVirq(Index, &LocalPort); - if (!NT_SUCCESS(status)) + if (Count == 1) { + Group = 0; + Number = 0; + } else { + ASSERT3U(Count, ==, 3); + + Group = va_arg(Arguments, USHORT); + Number = va_arg(Arguments, UCHAR); + } + + RtlZeroMemory(&ProcNumber, sizeof (PROCESSOR_NUMBER)); + ProcNumber.Group = Group; + ProcNumber.Number = Number; + + Cpu = KeGetProcessorIndexFromNumber(&ProcNumber); + + ASSERT3U(Cpu, <, Context->ProcessorCount); + Processor = &Context->Processor[Cpu]; + + status = STATUS_NOT_SUPPORTED; + if (!Processor->UpcallEnabled) goto fail1; + status = SystemVirtualCpuIndex(Cpu, &vcpu_id); + ASSERT(NT_SUCCESS(status)); + + status = EventChannelBindVirq(Index, vcpu_id, &LocalPort); + if (!NT_SUCCESS(status)) + goto fail2; + Channel->Parameters.Virq.Index = Index; Channel->LocalPort = LocalPort; return STATUS_SUCCESS; +fail2: + Error("fail2\n"); + fail1: Error("fail1 (%08x)\n", status); @@ -292,19 +344,22 @@ EvtchnOpen( va_start(Arguments, Argument); switch (Type) { case XENBUS_EVTCHN_TYPE_FIXED: - status = EvtchnOpenFixed(Channel, Arguments); + status = EvtchnOpenFixed(Context, Channel, 2, Arguments); break; case XENBUS_EVTCHN_TYPE_UNBOUND: - status = EvtchnOpenUnbound(Channel, Arguments); + status = EvtchnOpenUnbound(Context, Channel, 2, Arguments); break; case XENBUS_EVTCHN_TYPE_INTER_DOMAIN: - status = EvtchnOpenInterDomain(Channel, Arguments); + status = EvtchnOpenInterDomain(Context, Channel, 3, Arguments); break; case XENBUS_EVTCHN_TYPE_VIRQ: - status = EvtchnOpenVirq(Channel, Arguments); + // Processor information only specified from version 9 onwards + status = EvtchnOpenVirq(Context, Channel, + (Interface->Version < 9) ? 1 : 3, + Arguments); break; default: @@ -629,7 +684,7 @@ EvtchnTrigger( PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; KIRQL Irql; PROCESSOR_NUMBER ProcNumber; - ULONG Index; + ULONG Cpu; PXENBUS_EVTCHN_PROCESSOR Processor; PXENBUS_INTERRUPT Interrupt; BOOLEAN Pending; @@ -640,10 +695,10 @@ EvtchnTrigger( ProcNumber = Channel->ProcNumber; KeReleaseSpinLock(&Channel->Lock, Irql); - Index = KeGetProcessorIndexFromNumber(&ProcNumber); + Cpu = KeGetProcessorIndexFromNumber(&ProcNumber); - ASSERT3U(Index, <, Context->ProcessorCount); - Processor = &Context->Processor[Index]; + ASSERT3U(Cpu, <, Context->ProcessorCount); + Processor = &Context->Processor[Cpu]; Interrupt = (Processor->UpcallEnabled) ? Processor->Interrupt : @@ -675,7 +730,7 @@ EvtchnBind( { PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; PROCESSOR_NUMBER ProcNumber; - ULONG Index; + ULONG Cpu; PXENBUS_EVTCHN_PROCESSOR Processor; ULONG LocalPort; unsigned int vcpu_id; @@ -688,10 +743,10 @@ EvtchnBind( ProcNumber.Group = Group; ProcNumber.Number = Number; - Index = KeGetProcessorIndexFromNumber(&ProcNumber); + Cpu = KeGetProcessorIndexFromNumber(&ProcNumber); - ASSERT3U(Index, <, Context->ProcessorCount); - Processor = &Context->Processor[Index]; + ASSERT3U(Cpu, <, Context->ProcessorCount); + Processor = &Context->Processor[Cpu]; status = STATUS_NOT_SUPPORTED; if (!Processor->UpcallEnabled) @@ -708,7 +763,7 @@ EvtchnBind( LocalPort = Channel->LocalPort; - status = SystemVirtualCpuIndex(Index, &vcpu_id); + status = SystemVirtualCpuIndex(Cpu, &vcpu_id); ASSERT(NT_SUCCESS(status)); status = EventChannelBindVirtualCpu(LocalPort, vcpu_id); @@ -1762,6 +1817,21 @@ static struct _XENBUS_EVTCHN_INTERFACE_V8 EvtchnInterfaceVersion8 = { EvtchnClose, }; +static struct _XENBUS_EVTCHN_INTERFACE_V9 EvtchnInterfaceVersion9 = { + { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V9), 9, NULL, NULL, NULL }, + EvtchnAcquire, + EvtchnRelease, + EvtchnOpen, + EvtchnBind, + EvtchnUnmask, + EvtchnSend, + EvtchnTrigger, + EvtchnGetCount, + EvtchnWait, + EvtchnGetPort, + EvtchnClose, +}; + NTSTATUS EvtchnInitialize( IN PXENBUS_FDO Fdo, @@ -1955,6 +2025,23 @@ EvtchnGetInterface( status = STATUS_SUCCESS; break; } + case 9: { + struct _XENBUS_EVTCHN_INTERFACE_V9 *EvtchnInterface; + + EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V9 *)Interface; + + status = STATUS_BUFFER_OVERFLOW; + if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V9)) + break; + + *EvtchnInterface = EvtchnInterfaceVersion9; + + ASSERT3U(Interface->Version, ==, Version); + Interface->Context = Context; + + status = STATUS_SUCCESS; + break; + } default: status = STATUS_NOT_SUPPORTED; break; diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c index 1ef6606..10ad424 100644 --- a/src/xenbus/fdo.c +++ b/src/xenbus/fdo.c @@ -2781,6 +2781,8 @@ static FORCEINLINE NTSTATUS __FdoVirqCreate( IN PXENBUS_FDO Fdo, IN ULONG Type, + IN USHORT Group, + IN UCHAR Number, OUT PXENBUS_VIRQ *Virq ) { @@ -2789,7 +2791,7 @@ __FdoVirqCreate( *Virq = __FdoAllocate(sizeof (XENBUS_VIRQ)); status = STATUS_NO_MEMORY; - if ( Virq == NULL ) + if (*Virq == NULL) goto fail1; (*Virq)->Fdo = Fdo; @@ -2799,12 +2801,16 @@ __FdoVirqCreate( XENBUS_EVTCHN_TYPE_VIRQ, FdoVirqCallback, *Virq, - Type); + Type, + Group, + Number); status = STATUS_UNSUCCESSFUL; if ((*Virq)->Channel == NULL) goto fail2; + Info("%s: CPU %u:%u\n", VirqName(Type), Group, Number); + (VOID) XENBUS_EVTCHN(Unmask, &Fdo->EvtchnInterface, (*Virq)->Channel, @@ -2831,6 +2837,8 @@ __FdoVirqDestroy( { PXENBUS_FDO Fdo = Virq->Fdo; + Info("%s\n", VirqName(Virq->Type)); + XENBUS_EVTCHN(Close, &Fdo->EvtchnInterface, Virq->Channel); @@ -2840,15 +2848,20 @@ __FdoVirqDestroy( static NTSTATUS FdoVirqInitialize( - IN PXENBUS_FDO Fdo + IN PXENBUS_FDO Fdo ) { - PXENBUS_VIRQ Virq; - NTSTATUS status; + PROCESSOR_NUMBER ProcNumber; + PXENBUS_VIRQ Virq; + NTSTATUS status; InitializeListHead(&Fdo->VirqList); - status = __FdoVirqCreate(Fdo, VIRQ_DEBUG, &Virq); + status = KeGetProcessorNumberFromIndex(0, &ProcNumber); + ASSERT(NT_SUCCESS(status)); + + status = __FdoVirqCreate(Fdo, VIRQ_DEBUG, ProcNumber.Group, + ProcNumber.Number, &Virq); if (!NT_SUCCESS(status)) goto fail1; -- 2.39.5