From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.8008.1668812071939985828 for ; Fri, 18 Nov 2022 14:54:32 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: jeremy.linton@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 90D9D23A; Fri, 18 Nov 2022 14:54:37 -0800 (PST) Received: from [192.168.122.164] (U203867.austin.arm.com [10.118.30.40]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1828F3F73B; Fri, 18 Nov 2022 14:54:30 -0800 (PST) Message-ID: Date: Fri, 18 Nov 2022 16:54:26 -0600 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.0 Subject: [STILL CRASHING] Re: [edk2-devel] [PATCH v3 1/1] MdeModulePkg/UsbBusDxe: Rebuild the description table after Reset Device To: devel@edk2.groups.io, srikumar-subramanian@hpe.com, Guomin Jiang References: <18532.1607517516172259087@groups.io> From: "Jeremy Linton" In-Reply-To: <18532.1607517516172259087@groups.io> Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Hi, Dead thread poke, but, its been > 2 years since this problem was pointed=20 out. Multiple patches have been proposed, including one by me: https://edk2.groups.io/g/devel/message/58193 and the USB/XHCI reset logic continues to be broken enough that a wide=20 range of USB issues can result in boot crashes. Those crashes are the=20 result of a null pointer in the TrsRing being dereferenced following=20 reset. In fact it is 100% reproducible on seemingly any edk2 platform=20 with a XHCI controller given the right USB device (like the really=20 common JMICRON I pointed out in one of the threads). I'm not sure this patch is right, because the USB descriptors shouldn't=20 be cached over reset, but something has to be done to fix this problem. Thanks, On 12/9/20 06:38, Srikumar Subramanian via groups.io wrote: > Hi Jiang, >=20 > Is it the responsibility of the reset routine to know what is wrong with = the device? And on this topic I would like to know your thoughts on another= alternative which is saving the config in XhcPollPortStatusChange before d= isabling the slot and restoring it after initializing the device slot again= . My rationale for doing this is that, the reset device state diagram accor= ding to the specs moves the device from the configured to the default state= and does not completely remove device information. > In this regard is it safe to assume that meta-data such as descriptors sh= ould be restored. Since in this case a port reset is triggering a device re= set but because we disable and later initialize a new slot for an existing = device we lose its configuration which we assume does not change. >=20 > Let me know your thoughts and inputs on this. And if I needed an immediat= e solution I would like to know the better option between the one I am prop= osing right now and the existing suggested solution (which is making a requ= est to the device again for the descriptors.) >=20 > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/= Pci/XhciDxe/XhciSched.c > index 1754a97..d330f21 100644 > --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c > +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c > @@ -1,5 +1,5 @@ > /** >=20 > **/ > /** @file >=20 > @@ -1587,6 +1587,65 @@ XhcMonitorAsyncRequests ( > gBS->RestoreTPL (OldTpl); > } >=20 > +/** > +=C2=A0 =C2=A0 Save the current configuration for the Slot in Host Contro= ller > + > +=C2=A0 =C2=A0 @param Xhc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The XHCI instance > +=C2=A0 =C2=A0 @param SlotId=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Slot ID > +=C2=A0 =C2=A0 @param ActiveAlternateSetting=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0The Alternate interface setting that is part of the device context > +=C2=A0 =C2=A0 @param ConfDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Configuration Descriptors of t= he device present in the slot > +=C2=A0 =C2=A0 @param DevDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The Device Descriptor of the devi= ce present in the slot > +**/ > +VOID > +XhcSaveConfig( > +=C2=A0 IN USB_XHCI_INSTANCE=C2=A0 =C2=A0 *Xhc, > +=C2=A0 IN UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0SlotId, > +=C2=A0 OUT UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*= *ActiveAlternateSetting, > +=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR ***ConfDesc, > +=C2=A0 OUT EFI_USB_DEVICE_DESCRIPTOR *DevDesc > +) > +{ > +=C2=A0 UINT8 Index; > +=C2=A0 UINT8 IfIndex; > +=C2=A0 UINT8 NumInterfaces; > +=C2=A0 UINT64 ConfSize; > +=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR *IfDesc; > + > +=C2=A0 *DevDesc =3D Xhc->UsbDevContext[SlotId].DevDesc; > + > +=C2=A0 if(DevDesc->NumConfigurations=3D=3D0){ > +=C2=A0 =C2=A0 return; > +=C2=A0 } > + > +=C2=A0 *ConfDesc =3D AllocateZeroPool(DevDesc->NumConfigurations * sizeo= f(EFI_USB_CONFIG_DESCRIPTOR*)); > + > +=C2=A0 for(Index =3D 0; Index < DevDesc->NumConfigurations; Index++){ > +=C2=A0 =C2=A0 NumInterfaces =3D Xhc->UsbDevContext[SlotId].ConfDesc[Inde= x]->NumInterfaces; > +=C2=A0 =C2=A0 IfDesc =3D (EFI_USB_INTERFACE_DESCRIPTOR *)(Xhc->UsbDevCon= text[SlotId].ConfDesc[Index] + 1); > + > +=C2=A0 =C2=A0 // Calculating the size of the configuration descriptor. > +=C2=A0 =C2=A0 // This is needed since the interface and enpoint descript= ors are nested within this. > +=C2=A0 =C2=A0 // See USB_CONFIG_DESCRIPTOR, USB_INTERFACE_DESCRIPTOR, US= B_ENDPOINT_DESCRIPTOR in MdePkg/Include/IndustryStandard/Usb.h > +=C2=A0 =C2=A0 // See USB_CONFIG_DESC, USB_INTERFACE_DESC, USB_ENDPOINT_D= ESC in MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h > +=C2=A0 =C2=A0 ConfSize =3D sizeof(Xhc->UsbDevContext[SlotId].ConfDesc[In= dex]); > +=C2=A0 =C2=A0 ConfSize +=3D (sizeof(EFI_USB_INTERFACE_DESCRIPTOR) * (Num= Interfaces)); > +=C2=A0 =C2=A0 for(IfIndex =3D 0; IfIndex < NumInterfaces; IfIndex++){ > +=C2=A0 =C2=A0 =C2=A0 ConfSize +=3D IfDesc->NumEndpoints * sizeof(EFI_USB= _ENDPOINT_DESCRIPTOR); > +=C2=A0 =C2=A0 =C2=A0 IfDesc =3D (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDe= sc + IfDesc->Length); > +=C2=A0 =C2=A0 } > + > +=C2=A0 =C2=A0 *ConfDesc[Index] =3D AllocateZeroPool(ConfSize); > +=C2=A0 =C2=A0 CopyMem (*ConfDesc[Index] ,Xhc->UsbDevContext[SlotId].Conf= Desc[Index], ConfSize); > +=C2=A0 } > + > +=C2=A0 *ActiveAlternateSetting =3D AllocateZeroPool(Xhc->UsbDevContext[S= lotId].ConfDesc[0]->NumInterfaces * sizeof(UINT8)); > + > +=C2=A0 CopyMem(*ActiveAlternateSetting, Xhc->UsbDevContext[SlotId].Activ= eAlternateSetting, Xhc->UsbDevContext[SlotId].ConfDesc[0]->NumInterfaces * = sizeof(UINT8)); > + > +} > + > /** > Monitor the port status change. Enable/Disable device slot if there is a = device attached/detached. >=20 > @@ -1613,6 +1672,15 @@ XhcPollPortStatusChange ( > UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0SlotId; > USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0RouteChart; >=20 > +=C2=A0 EFI_USB_CONFIG_DESCRIPTOR **ConfDescBuffer; > +=C2=A0 EFI_USB_DEVICE_DESCRIPTOR DevDescBuffer; > +=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*ActiveAlter= nateSettingBuffer; > + > +=C2=A0 ConfDescBuffer =3D NULL; > +=C2=A0 ActiveAlternateSettingBuffer =3D NULL; > + > Status =3D EFI_SUCCESS; >=20 > if ((PortState->PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT= _STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) =3D= =3D 0) { > @@ -1635,6 +1703,14 @@ XhcPollPortStatusChange ( >=20 > SlotId =3D XhcRouteStringToSlotId (Xhc, RouteChart); > if (SlotId !=3D 0) { > + > +=C2=A0 =C2=A0 // Saving the current host controller configuration for re= use after device reset > +=C2=A0 =C2=A0 if((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != =3D 0){ > +=C2=A0 =C2=A0 =C2=A0 XhcSaveConfig(Xhc, SlotId, &ActiveAlternateSettingB= uffer, &ConfDescBuffer, &DevDescBuffer); > +=C2=A0 =C2=A0 } > + > if (Xhc->HcCParams.Data.Csz =3D=3D 0) { > Status =3D XhcDisableSlotCmd (Xhc, SlotId); > } else { > @@ -1660,11 +1736,23 @@ XhcPollPortStatusChange ( > // > SlotId =3D XhcRouteStringToSlotId (Xhc, RouteChart); > if ((SlotId =3D=3D 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_= RESET) !=3D 0)) { > + > + > +=C2=A0 =C2=A0 =C2=A0 // Introducing the SlotId as a new parameter in Xhc= InitializeDeviceSlot in order to get the > +=C2=A0 =C2=A0 =C2=A0 // new slotId assigned. > if (Xhc->HcCParams.Data.Csz =3D=3D 0) { > -=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D XhcInitializeDeviceSlot (Xhc, Par= entRouteChart, Port, RouteChart, Speed); > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D XhcInitializeDeviceSlot (Xhc, Par= entRouteChart, Port, RouteChart, Speed, &SlotId); > } else { > -=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D XhcInitializeDeviceSlot64 (Xhc, P= arentRouteChart, Port, RouteChart, Speed); > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D XhcInitializeDeviceSlot64 (Xhc, P= arentRouteChart, Port, RouteChart, Speed, &SlotId); > } > + > +=C2=A0 =C2=A0 =C2=A0 if(!EFI_ERROR(Status) && ConfDescBuffer!=3DNULL && = SlotId!=3D0){ > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 Xhc->UsbDevContext[SlotId].DevDesc =3D DevDe= scBuffer; > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 Xhc->UsbDevContext[SlotId].ConfDesc =3D Conf= DescBuffer; > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 Xhc->UsbDevContext[SlotId].ActiveAlternateSe= tting =3D ActiveAlternateSettingBuffer; > +=C2=A0 =C2=A0 =C2=A0 } >=20 > + > } > } >=20 > @@ -1987,7 +2075,11 @@ XhcInitializeDeviceSlot ( > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Par= entRouteChart, > IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ParentPort, > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Rou= teChart, > -=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed > +=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed, >=20 > +=C2=A0 // OPTIONAL as this need not be used > +=C2=A0 OPTIONAL OUT UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Slot= IdStore >=20 > ) > { > EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = Status; > @@ -2175,6 +2267,12 @@ XhcInitializeDeviceSlot ( > Xhc->UsbDevContext[SlotId].XhciDevAddr =3D DeviceAddress; > } >=20 > +=C2=A0 if(SlotIdStore !=3D NULL){ > +=C2=A0 *SlotIdStore =3D SlotId; > +=C2=A0 } > + > return Status; > } >=20 > @@ -2197,7 +2295,11 @@ XhcInitializeDeviceSlot64 ( > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Par= entRouteChart, > IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ParentPort, > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Rou= teChart, > -=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed > +=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed, >=20 > +=C2=A0 // OPTIONAL as this need not be used > +=C2=A0 OPTIONAL OUT UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Slot= IdStore >=20 > ) > { > EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = Status; > @@ -2384,6 +2486,13 @@ XhcInitializeDeviceSlot64 ( > DEBUG ((EFI_D_INFO, "=C2=A0 =C2=A0 Address %d assigned successfully\n", D= eviceAddress)); > Xhc->UsbDevContext[SlotId].XhciDevAddr =3D DeviceAddress; > } > + >=20 > +=C2=A0 if(SlotIdStore !=3D NULL){ > +=C2=A0 *SlotIdStore =3D SlotId; > +=C2=A0 } >=20 > + > return Status; > } >=20 > diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h b/MdeModulePkg/Bus/= Pci/XhciDxe/XhciSched.h > index 4da9669..64ef878 100644 > --- a/PurleyPlatPkg/Override/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h > +++ b/PurleyPlatPkg/Override/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h > @@ -1,3 +1,6 @@ > +/** > +*=C2=A0 CONFIDENTIAL (C) Copyright 2020 Hewlett Packard Enterprise Devel= opment LP
> +**/ > /** @file >=20 > This file contains the definition for XHCI host controller schedule routi= nes. > @@ -1120,7 +1123,11 @@ XhcInitializeDeviceSlot ( > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Par= entRouteChart, > IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ParentPort, > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Rou= teChart, > -=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed > +=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed, > +=C2=A0 // HPE_EXL_SS_QXCR1001775642 > +=C2=A0 // OPTIONAL as this need not be used > +=C2=A0 OPTIONAL OUT UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Slot= IdStore > +=C2=A0 // HPE_EXL_SS_QXCR1001775642 > ); >=20 > /** > @@ -1142,7 +1149,11 @@ XhcInitializeDeviceSlot64 ( > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Par= entRouteChart, > IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ParentPort, > IN=C2=A0 USB_DEV_ROUTE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Rou= teChart, > -=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed > +=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0DeviceSpeed, >=20 > +=C2=A0 // OPTIONAL as this need not be used > +=C2=A0 OPTIONAL OUT UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Slot= IdStore >=20 > ); >=20 > /** > @@ -1458,4 +1469,24 @@ XhcCreateTransferTrb ( > IN URB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Urb > ); >=20 > +/** > +=C2=A0 =C2=A0 Save the current configuration for the Slot in Host Contro= ller > + > +=C2=A0 =C2=A0 @param Xhc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The XHCI instance > +=C2=A0 =C2=A0 @param SlotId=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Slot ID > +=C2=A0 =C2=A0 @param ActiveAlternateSetting=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0The Alternate interface setting that is part of the device context > +=C2=A0 =C2=A0 @param ConfDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Configuration Descriptors of t= he device present in the slot > +=C2=A0 =C2=A0 @param DevDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The Device Descriptor of the devi= ce present in the slot > +**/ > +VOID > +XhcSaveConfig( > +=C2=A0 IN USB_XHCI_INSTANCE=C2=A0 =C2=A0 *Xhc, > +=C2=A0 IN UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0SlotId, > +=C2=A0 OUT UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*= *ActiveAlternateSetting, > +=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR ***ConfDesc, > +=C2=A0 OUT EFI_USB_DEVICE_DESCRIPTOR *DevDesc > +); > + >=20 >=20 >=20 >=20 >=20 >=20