[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [win-pv-devel] [PATCH 07/14 v2] Enumerate non-default consoles



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of owen.smith@xxxxxxxxxx
> Sent: 23 February 2018 14:22
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith <owen.smith@xxxxxxxxxx>
> Subject: [win-pv-devel] [PATCH 07/14 v2] Enumerate non-default consoles
> 
> From: Owen Smith <owen.smith@xxxxxxxxxx>
> 
> * Add enumeration thread and watch
> * Non-default consoles will fail any read/write/iocontrol IRPs
> 
> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>

Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx>

> ---
>  src/xencons/fdo.c | 316
> +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/xencons/pdo.c |  64 +++++++++--
>  src/xencons/pdo.h |   5 +
>  3 files changed, 376 insertions(+), 9 deletions(-)
> 
> diff --git a/src/xencons/fdo.c b/src/xencons/fdo.c
> index 45a1fdd..4046acf 100644
> --- a/src/xencons/fdo.c
> +++ b/src/xencons/fdo.c
> @@ -85,6 +85,9 @@ struct _XENCONS_FDO {
> 
>      CHAR                        VendorName[MAXNAMELEN];
> 
> +    PXENCONS_THREAD             ScanThread;
> +    KEVENT                      ScanEvent;
> +    PXENBUS_STORE_WATCH         ScanWatch;
>      MUTEX                       Mutex;
>      ULONG                       References;
> 
> @@ -653,6 +656,9 @@ done:
>      RemoveEntryList(&Dx->ListEntry);
>      ASSERT3U(Fdo->References, != , 0);
>      --Fdo->References;
> +
> +    if (Fdo->ScanThread)
> +        ThreadWake(Fdo->ScanThread);
>  }
> 
>  static FORCEINLINE VOID
> @@ -690,6 +696,112 @@ FdoReleaseMutex(
>          FdoDestroy(Fdo);
>  }
> 
> +static FORCEINLINE BOOLEAN
> +__FdoEnumerate(
> +    IN  PXENCONS_FDO    Fdo,
> +    IN  PANSI_STRING    Devices
> +    )
> +{
> +    BOOLEAN             NeedInvalidate;
> +    HANDLE              ParametersKey;
> +    ULONG               Enumerate;
> +    PLIST_ENTRY         ListEntry;
> +    ULONG               Index;
> +    NTSTATUS            status;
> +
> +    Trace("====>\n");
> +
> +    NeedInvalidate = FALSE;
> +
> +    ParametersKey = DriverGetParametersKey();
> +
> +    status = RegistryQueryDwordValue(ParametersKey,
> +                                     "Enumerate",
> +                                     &Enumerate);
> +    if (!NT_SUCCESS(status))
> +        Enumerate = 1;
> +
> +    if (Enumerate == 0)
> +        goto done;
> +
> +    __FdoAcquireMutex(Fdo);
> +
> +    ListEntry = Fdo->Dx->ListEntry.Flink;
> +    while (ListEntry != &Fdo->Dx->ListEntry) {
> +        PLIST_ENTRY     Next = ListEntry->Flink;
> +        PXENCONS_DX     Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX,
> ListEntry);
> +        PXENCONS_PDO    Pdo = Dx->Pdo;
> +
> +        // If the PDO is the default console, it wont exist in the
> +        // the device list, as its statically created
> +        if (PdoIsDefault(Pdo))
> +            continue;
> +
> +        if (PdoGetDevicePnpState(Pdo) != Deleted) {
> +            PCHAR           Name;
> +            BOOLEAN         Missing;
> +
> +            Name = PdoGetName(Pdo);
> +            Missing = TRUE;
> +
> +            // If the PDO already exists and its name is in the device list
> +            // then we don't want to remove it.
> +            for (Index = 0; Devices[Index].Buffer != NULL; Index++) {
> +                PANSI_STRING Device = &Devices[Index];
> +
> +                if (Device->Length == 0)
> +                    continue;
> +
> +                if (strcmp(Name, Device->Buffer) == 0) {
> +                    Missing = FALSE;
> +                    Device->Length = 0;  // avoid duplication
> +                    break;
> +                }
> +            }
> +
> +            if (!PdoIsMissing(Pdo)) {
> +                if (PdoIsEjectRequested(Pdo)) {
> +                    IoRequestDeviceEject(PdoGetDeviceObject(Pdo));
> +                } else if (Missing) {
> +                    PdoSetMissing(Pdo, "device disappeared");
> +
> +                    // If the PDO has not yet been enumerated then we can
> +                    // go ahead and mark it as deleted, otherwise we need
> +                    // to notify PnP manager and wait for the REMOVE_DEVICE
> +                    // IRP.
> +                    if (PdoGetDevicePnpState(Pdo) == Present) {
> +                        PdoSetDevicePnpState(Pdo, Deleted);
> +                        PdoDestroy(Pdo);
> +                    } else {
> +                        NeedInvalidate = TRUE;
> +                    }
> +                }
> +            }
> +        }
> +
> +        ListEntry = Next;
> +    }
> +
> +    // Walk the class list and create PDOs for any new device
> +    for (Index = 0; Devices[Index].Buffer != NULL; Index++) {
> +        PANSI_STRING Device = &Devices[Index];
> +
> +        if (Device->Length == 0)
> +            continue;
> +
> +        status = PdoCreate(Fdo, Device);
> +        if (NT_SUCCESS(status))
> +            NeedInvalidate = TRUE;
> +    }
> +
> +    __FdoReleaseMutex(Fdo);
> +
> +done:
> +    Trace("<====\n");
> +
> +    return NeedInvalidate;
> +}
> +
>  static FORCEINLINE PANSI_STRING
>  __FdoMultiSzToUpcaseAnsi(
>      IN  PCHAR       Buffer
> @@ -768,6 +880,125 @@ __FdoFreeAnsi(
>      __FdoFree(Ansi);
>  }
> 
> +static NTSTATUS
> +FdoScan(
> +    PXENCONS_THREAD     Self,
> +    PVOID               Context
> +    )
> +{
> +    PXENCONS_FDO        Fdo = Context;
> +    PKEVENT             Event;
> +    HANDLE              ParametersKey;
> +    NTSTATUS            status;
> +
> +    Trace("====>\n");
> +
> +    Event = ThreadGetEvent(Self);
> +
> +    ParametersKey = DriverGetParametersKey();
> +
> +    for (;;) {
> +        PCHAR           Buffer;
> +        PANSI_STRING    Devices;
> +        PANSI_STRING    UnsupportedDevices;
> +        ULONG           Index;
> +        BOOLEAN         NeedInvalidate;
> +
> +        Trace("waiting...\n");
> +
> +        (VOID)KeWaitForSingleObject(Event,
> +                                    Executive,
> +                                    KernelMode,
> +                                    FALSE,
> +                                    NULL);
> +        KeClearEvent(Event);
> +
> +        if (ThreadIsAlerted(Self))
> +            break;
> +
> +        // It is not safe to use interfaces before this point
> +        if (__FdoGetDevicePnpState(Fdo) != Started) {
> +            KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
> +            continue;
> +        }
> +
> +        status = XENBUS_STORE(Directory,
> +                              &Fdo->StoreInterface,
> +                              NULL,
> +                              "device",
> +                              "console",
> +                              &Buffer);
> +        if (NT_SUCCESS(status)) {
> +            Devices = __FdoMultiSzToUpcaseAnsi(Buffer);
> +
> +            XENBUS_STORE(Free,
> +                         &Fdo->StoreInterface,
> +                         Buffer);
> +        } else {
> +            Devices = NULL;
> +        }
> +
> +        if (Devices == NULL)
> +            goto loop;
> +
> +        if (ParametersKey != NULL) {
> +            status = RegistryQuerySzValue(ParametersKey,
> +                                          "UnsupportedDevices",
> +                                          NULL,
> +                                          &UnsupportedDevices);
> +            if (!NT_SUCCESS(status))
> +                UnsupportedDevices = NULL;
> +        } else {
> +            UnsupportedDevices = NULL;
> +        }
> +
> +        // NULL out anything in the Devices list that is in the
> +        // UnsupportedDevices list
> +        for (Index = 0; Devices[Index].Buffer != NULL; Index++) {
> +            PANSI_STRING    Device = &Devices[Index];
> +            ULONG           Entry;
> +            BOOLEAN         Supported;
> +
> +            Supported = TRUE;
> +
> +            for (Entry = 0;
> +                 UnsupportedDevices != NULL &&
> UnsupportedDevices[Entry].Buffer != NULL;
> +                 Entry++) {
> +                if (strncmp(Device->Buffer,
> +                            UnsupportedDevices[Entry].Buffer,
> +                            Device->Length) == 0) {
> +                    Supported = FALSE;
> +                    break;
> +                }
> +            }
> +
> +            if (!Supported)
> +                Device->Length = 0;
> +        }
> +
> +        if (UnsupportedDevices != NULL)
> +            RegistryFreeSzValue(UnsupportedDevices);
> +
> +        NeedInvalidate = __FdoEnumerate(Fdo, Devices);
> +
> +        __FdoFreeAnsi(Devices);
> +
> +        if (NeedInvalidate) {
> +            NeedInvalidate = FALSE;
> +            IoInvalidateDeviceRelations(__FdoGetPhysicalDeviceObject(Fdo),
> +                                        BusRelations);
> +        }
> +
> +    loop:
> +        KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
> +    }
> +
> +    KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
> +
> +    Trace("<====\n");
> +    return STATUS_SUCCESS;
> +}
> +
>  static FORCEINLINE BOOLEAN
>  __FdoMatchDistribution(
>      IN  PXENCONS_FDO    Fdo,
> @@ -989,15 +1220,39 @@ __FdoD3ToD0(
>      IN  PXENCONS_FDO    Fdo
>      )
>  {
> +    NTSTATUS        status;
> +
>      Trace("====>\n");
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
> 
>      (VOID) FdoSetDistribution(Fdo);
> 
> +    status = XENBUS_STORE(WatchAdd,
> +                          &Fdo->StoreInterface,
> +                          "device",
> +                          "console",
> +                          ThreadGetEvent(Fdo->ScanThread),
> +                          &Fdo->ScanWatch);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    (VOID)XENBUS_STORE(Printf,
> +                       &Fdo->StoreInterface,
> +                       NULL,
> +                       "feature/hotplug",
> +                       "console",
> +                       "%u",
> +                       TRUE);
> +
>      Trace("<====\n");
> 
>      return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
>  }
> 
>  static FORCEINLINE VOID
> @@ -1009,6 +1264,17 @@ __FdoD0ToD3(
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
> 
> +    (VOID)XENBUS_STORE(Remove,
> +                       &Fdo->StoreInterface,
> +                       NULL,
> +                       "feature/hotplug",
> +                       "console");
> +
> +    (VOID)XENBUS_STORE(WatchRemove,
> +                       &Fdo->StoreInterface,
> +                       Fdo->ScanWatch);
> +    Fdo->ScanWatch = NULL;
> +
>      FdoClearDistribution(Fdo);
> 
>      Trace("<====\n");
> @@ -1221,17 +1487,31 @@ FdoStartDevice(
>                        
> StackLocation->Parameters.StartDevice.AllocatedResources,
>                        StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated);
> 
> -    status = FdoD3ToD0(Fdo);
> +    KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
> +
> +    status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
>      if (!NT_SUCCESS(status))
>          goto fail2;
> 
> +    status = FdoD3ToD0(Fdo);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
>      __FdoSetDevicePnpState(Fdo, Started);
> +    ThreadWake(Fdo->ScanThread);
> 
>      status = Irp->IoStatus.Status;
>      IoCompleteRequest(Irp, IO_NO_INCREMENT);
> 
>      return status;
> 
> +fail3:
> +    Error("fail3\n");
> +
> +    ThreadAlert(Fdo->ScanThread);
> +    ThreadJoin(Fdo->ScanThread);
> +    Fdo->ScanThread = NULL;
> +
>  fail2:
>      Error("fail2\n");
> 
> @@ -1292,6 +1572,12 @@ FdoStopDevice(
>      if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
>          FdoD0ToD3(Fdo);
> 
> +    ThreadAlert(Fdo->ScanThread);
> +    ThreadJoin(Fdo->ScanThread);
> +    Fdo->ScanThread = NULL;
> +
> +    RtlZeroMemory(&Fdo->ScanEvent, sizeof(KEVENT));
> +
>      RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) *
> RESOURCE_COUNT);
> 
>      __FdoSetDevicePnpState(Fdo, Stopped);
> @@ -1387,6 +1673,17 @@ FdoRemoveDevice(
>      if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
>          goto done;
> 
> +    KeClearEvent(&Fdo->ScanEvent);
> +    ThreadWake(Fdo->ScanThread);
> +
> +    Trace("waiting for scan thread\n");
> +
> +    (VOID)KeWaitForSingleObject(&Fdo->ScanEvent,
> +                                Executive,
> +                                KernelMode,
> +                                FALSE,
> +                                NULL);
> +
>      __FdoAcquireMutex(Fdo);
> 
>      ListEntry = Fdo->Dx->ListEntry.Flink;
> @@ -1414,6 +1711,12 @@ FdoRemoveDevice(
>      if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
>          FdoD0ToD3(Fdo);
> 
> +    ThreadAlert(Fdo->ScanThread);
> +    ThreadJoin(Fdo->ScanThread);
> +    Fdo->ScanThread = NULL;
> +
> +    RtlZeroMemory(&Fdo->ScanEvent, sizeof(KEVENT));
> +
>      RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) *
> RESOURCE_COUNT);
> 
>  done:
> @@ -1463,6 +1766,17 @@ FdoQueryDeviceRelations(
>          goto done;
>      }
> 
> +    KeClearEvent(&Fdo->ScanEvent);
> +    ThreadWake(Fdo->ScanThread);
> +
> +    Trace("waiting for scan thread\n");
> +
> +    (VOID)KeWaitForSingleObject(&Fdo->ScanEvent,
> +                                Executive,
> +                                KernelMode,
> +                                FALSE,
> +                                NULL);
> +
>      __FdoAcquireMutex(Fdo);
> 
>      Count = 0;
> diff --git a/src/xencons/pdo.c b/src/xencons/pdo.c
> index 62f366c..2acd86a 100755
> --- a/src/xencons/pdo.c
> +++ b/src/xencons/pdo.c
> @@ -71,6 +71,7 @@ struct _XENCONS_PDO {
>      XENBUS_SUSPEND_INTERFACE    SuspendInterface;
>      PXENBUS_SUSPEND_CALLBACK    SuspendCallbackLate;
> 
> +    BOOLEAN                     IsDefault;
>      PXENCONS_CONSOLE            Console;
>  };
> 
> @@ -286,6 +287,14 @@ __PdoGetName(
>      return Dx->Name;
>  }
> 
> +PCHAR
> +PdoGetName(
> +    IN  PXENCONS_PDO    Pdo
> +    )
> +{
> +    return __PdoGetName(Pdo);
> +}
> +
>  static FORCEINLINE PCHAR
>  __PdoGetVendorName(
>      IN  PXENCONS_PDO    Pdo
> @@ -295,6 +304,22 @@ __PdoGetVendorName(
>  }
> 
>  static FORCEINLINE BOOLEAN
> +__PdoIsDefault(
> +    IN  PXENCONS_PDO    Pdo
> +    )
> +{
> +    return Pdo->IsDefault;
> +}
> +
> +BOOLEAN
> +PdoIsDefault(
> +    IN  PXENCONS_PDO    Pdo
> +    )
> +{
> +    return __PdoIsDefault(Pdo);
> +}
> +
> +static FORCEINLINE BOOLEAN
>  __PdoSetEjectRequested(
>      IN  PXENCONS_PDO    Pdo
>      )
> @@ -441,7 +466,10 @@ PdoD3ToD0(
> 
>      KeLowerIrql(Irql);
> 
> -    status = ConsoleD3ToD0(Pdo->Console);
> +    if (__PdoIsDefault(Pdo))
> +        status = ConsoleD3ToD0(Pdo->Console);
> +    else
> +        status = STATUS_SUCCESS;
>      if (!NT_SUCCESS(status))
>          goto fail4;
> 
> @@ -495,7 +523,8 @@ PdoD0ToD3(
>  #pragma prefast(suppress:28123)
>      (VOID) IoSetDeviceInterfaceState(&Pdo->Dx->Link, FALSE);
> 
> -    ConsoleD0ToD3(Pdo->Console);
> +    if (__PdoIsDefault(Pdo))
> +        ConsoleD0ToD3(Pdo->Console);
> 
>      KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> 
> @@ -1689,7 +1718,10 @@ PdoDispatchCreate(
> 
>      StackLocation = IoGetCurrentIrpStackLocation(Irp);
> 
> -    status = ConsoleOpen(Pdo->Console, StackLocation->FileObject);
> +    if (__PdoIsDefault(Pdo))
> +        status = ConsoleOpen(Pdo->Console, StackLocation->FileObject);
> +    else
> +        status = STATUS_SUCCESS;
> 
>      Irp->IoStatus.Status = status;
>      IoCompleteRequest(Irp, IO_NO_INCREMENT);
> @@ -1708,7 +1740,10 @@ PdoDispatchCleanup(
> 
>      StackLocation = IoGetCurrentIrpStackLocation(Irp);
> 
> -    status = ConsoleClose(Pdo->Console, StackLocation->FileObject);
> +    if (__PdoIsDefault(Pdo))
> +        status = ConsoleClose(Pdo->Console, StackLocation->FileObject);
> +    else
> +        status = STATUS_SUCCESS;
> 
>      Irp->IoStatus.Status = status;
>      IoCompleteRequest(Irp, IO_NO_INCREMENT);
> @@ -1742,7 +1777,10 @@ PdoDispatchReadWriteControl(
>  {
>      NTSTATUS            status;
> 
> -    status = ConsolePutQueue(Pdo->Console, Irp);
> +    if (__PdoIsDefault(Pdo))
> +        status = ConsolePutQueue(Pdo->Console, Irp);
> +    else
> +        status = STATUS_DEVICE_NOT_READY;
>      if (status == STATUS_SUCCESS)
>          goto done;
>      if (status != STATUS_PENDING)
> @@ -1895,7 +1933,11 @@ PdoCreate(
> 
>      Dx->Pdo = Pdo;
> 
> -    status = ConsoleCreate(Fdo, &Pdo->Console);
> +    Pdo->IsDefault = (Device == NULL);
> +    if (Pdo->IsDefault)
> +        status = ConsoleCreate(Fdo, &Pdo->Console);
> +    else
> +        status = STATUS_SUCCESS;
>      if (!NT_SUCCESS(status))
>          goto fail5;
> 
> @@ -1925,9 +1967,12 @@ fail6:
> 
>      (VOID)__PdoClearEjectRequested(Pdo);
> 
> -    ConsoleDestroy(Pdo->Console);
> +    if (__PdoIsDefault(Pdo))
> +        ConsoleDestroy(Pdo->Console);
>      Pdo->Console = NULL;
> 
> +    Pdo->IsDefault = FALSE;
> +
>  fail5:
>      Error("fail5\n");
> 
> @@ -1994,9 +2039,12 @@ PdoDestroy(
> 
>      Dx->Pdo = NULL;
> 
> -    ConsoleDestroy(Pdo->Console);
> +    if (__PdoIsDefault(Pdo))
> +        ConsoleDestroy(Pdo->Console);
>      Pdo->Console = NULL;
> 
> +    Pdo->IsDefault = FALSE;
> +
>      RtlFreeUnicodeString(&Pdo->Dx->Link);
> 
>      RtlZeroMemory(&Pdo->SuspendInterface,
> diff --git a/src/xencons/pdo.h b/src/xencons/pdo.h
> index 0605483..85f73a3 100755
> --- a/src/xencons/pdo.h
> +++ b/src/xencons/pdo.h
> @@ -83,6 +83,11 @@ PdoGetDeviceObject(
>      IN  PXENCONS_PDO    Pdo
>      );
> 
> +extern BOOLEAN
> +PdoIsDefault(
> +    IN  PXENCONS_PDO    Pdo
> +    );
> +
>  extern NTSTATUS
>  PdoCreate(
>      IN  PXENCONS_FDO    Fdo,
> --
> 2.8.3
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.