]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/XhciDxe: Add boundary check for TRB ring allocation
authorjdzhang <jdzhang@kunluntech.com.cn>
Tue, 18 Oct 2022 02:56:02 +0000 (10:56 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 20 Oct 2022 03:23:51 +0000 (03:23 +0000)
According the Xhci Spec, TRB Rings may be larger than a Page, however they
shall not cross a 64K byte boundary, so add a parameter to indicate
whether the memory allocation is for TRB Rings or not. It will ensure the
allocation not crossing 64K boundary in UsbHcAllocMemFromBlock if the
memory is allocated for TRB Rings.

Signed-off-by: jdzhang <jdzhang@kunluntech.com.cn>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h
MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c

index 99fb3521d56be80bd0ae827061042ee8560c734c..d0ad1582e4ea81a482bd90ed8c75d50e6b381ff7 100644 (file)
@@ -132,8 +132,9 @@ UsbHcFreeMemBlock (
 /**\r
   Alloc some memory from the block.\r
 \r
-  @param  Block          The memory block to allocate memory from.\r
-  @param  Units          Number of memory units to allocate.\r
+  @param  Block                The memory block to allocate memory from.\r
+  @param  Units                Number of memory units to allocate.\r
+  @param  AllocationForRing    The allocated memory is for Ring or not.\r
 \r
   @return The pointer to the allocated memory. If couldn't allocate the needed memory,\r
           the return value is NULL.\r
@@ -142,7 +143,8 @@ UsbHcFreeMemBlock (
 VOID *\r
 UsbHcAllocMemFromBlock (\r
   IN  USBHC_MEM_BLOCK  *Block,\r
-  IN  UINTN            Units\r
+  IN  UINTN            Units,\r
+  IN  BOOLEAN          AllocationForRing\r
   )\r
 {\r
   UINTN  Byte;\r
@@ -151,12 +153,15 @@ UsbHcAllocMemFromBlock (
   UINT8  StartBit;\r
   UINTN  Available;\r
   UINTN  Count;\r
+  UINTN  MemUnitAddr;\r
+  UINTN  AlignmentMask;\r
 \r
   ASSERT ((Block != 0) && (Units != 0));\r
 \r
-  StartByte = 0;\r
-  StartBit  = 0;\r
-  Available = 0;\r
+  StartByte     = 0;\r
+  StartBit      = 0;\r
+  Available     = 0;\r
+  AlignmentMask = ~((UINTN)USBHC_MEM_TRB_RINGS_BOUNDARY - 1);\r
 \r
   for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {\r
     //\r
@@ -165,6 +170,20 @@ UsbHcAllocMemFromBlock (
     // Available counts the consective number of zero bit.\r
     //\r
     if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {\r
+      if (AllocationForRing && (Available != 0)) {\r
+        MemUnitAddr = (UINTN)Block->BufHost + (Byte * 8 + Bit) * USBHC_MEM_UNIT;\r
+        if ((MemUnitAddr & AlignmentMask) != ((MemUnitAddr - USBHC_MEM_UNIT) & AlignmentMask)) {\r
+          //\r
+          // If the TRB Ring memory cross 64K-byte boundary, then restart the\r
+          // search starting at current memory unit.\r
+          // Doing so is to meet the TRB Ring boundary requirement in XHCI spec.\r
+          //\r
+          Available = 0;\r
+          StartByte = Byte;\r
+          StartBit  = Bit;\r
+        }\r
+      }\r
+\r
       Available++;\r
 \r
       if (Available >= Units) {\r
@@ -438,8 +457,9 @@ UsbHcFreeMemPool (
   Allocate some memory from the host controller's memory pool\r
   which can be used to communicate with host controller.\r
 \r
-  @param  Pool           The host controller's memory pool.\r
-  @param  Size           Size of the memory to allocate.\r
+  @param  Pool                 The host controller's memory pool.\r
+  @param  Size                 Size of the memory to allocate.\r
+  @param  AllocationForRing    The allocated memory is for Ring or not.\r
 \r
   @return The allocated memory or NULL.\r
 \r
@@ -447,7 +467,8 @@ UsbHcFreeMemPool (
 VOID *\r
 UsbHcAllocateMem (\r
   IN  USBHC_MEM_POOL  *Pool,\r
-  IN  UINTN           Size\r
+  IN  UINTN           Size,\r
+  IN  BOOLEAN         AllocationForRing\r
   )\r
 {\r
   USBHC_MEM_BLOCK  *Head;\r
@@ -466,7 +487,7 @@ UsbHcAllocateMem (
   // First check whether current memory blocks can satisfy the allocation.\r
   //\r
   for (Block = Head; Block != NULL; Block = Block->Next) {\r
-    Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);\r
+    Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT, AllocationForRing);\r
 \r
     if (Mem != NULL) {\r
       ZeroMem (Mem, Size);\r
@@ -501,7 +522,7 @@ UsbHcAllocateMem (
   // Add the new memory block to the pool, then allocate memory from it\r
   //\r
   UsbHcInsertMemBlockToPool (Head, NewBlock);\r
-  Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);\r
+  Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT, AllocationForRing);\r
 \r
   if (Mem != NULL) {\r
     ZeroMem (Mem, Size);\r
index 48ae86141ca2df9fca4c9552a9230eb865c1b478..c85b0b919f56116674d47d894380ad25f85544e8 100644 (file)
@@ -48,6 +48,8 @@ typedef struct _USBHC_MEM_POOL {
 \r
 #define USBHC_MEM_ROUND(Len)  (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))\r
 \r
+#define USBHC_MEM_TRB_RINGS_BOUNDARY  SIZE_64KB\r
+\r
 //\r
 // Advance the byte and bit to the next bit, adjust byte accordingly.\r
 //\r
@@ -92,8 +94,9 @@ UsbHcFreeMemPool (
   Allocate some memory from the host controller's memory pool\r
   which can be used to communicate with host controller.\r
 \r
-  @param  Pool  The host controller's memory pool.\r
-  @param  Size  Size of the memory to allocate.\r
+  @param  Pool                 The host controller's memory pool.\r
+  @param  Size                 Size of the memory to allocate.\r
+  @param  AllocationForRing    The allocated memory is for Ring or not.\r
 \r
   @return The allocated memory or NULL.\r
 \r
@@ -101,7 +104,8 @@ UsbHcFreeMemPool (
 VOID *\r
 UsbHcAllocateMem (\r
   IN  USBHC_MEM_POOL  *Pool,\r
-  IN  UINTN           Size\r
+  IN  UINTN           Size,\r
+  IN  BOOLEAN         AllocationForRing\r
   );\r
 \r
 /**\r
index 4ae02976079b6af01cbf3f1a1718dca9a73e9cf4..13b0400e83d7f711bd42d3a017da8f0c7d994f99 100644 (file)
@@ -506,7 +506,7 @@ XhcInitSched (
   // Software shall set Device Context Base Address Array entries for unallocated Device Slots to '0'.\r
   //\r
   Entries = (Xhc->MaxSlotsEn + 1) * sizeof (UINT64);\r
-  Dcbaa   = UsbHcAllocateMem (Xhc->MemPool, Entries);\r
+  Dcbaa   = UsbHcAllocateMem (Xhc->MemPool, Entries, FALSE);\r
   ASSERT (Dcbaa != NULL);\r
   ZeroMem (Dcbaa, Entries);\r
 \r
@@ -795,7 +795,7 @@ CreateEventRing (
   ASSERT (EventRing != NULL);\r
 \r
   Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER;\r
-  Buf  = UsbHcAllocateMem (Xhc->MemPool, Size);\r
+  Buf  = UsbHcAllocateMem (Xhc->MemPool, Size, TRUE);\r
   ASSERT (Buf != NULL);\r
   ASSERT (((UINTN)Buf & 0x3F) == 0);\r
   ZeroMem (Buf, Size);\r
@@ -814,7 +814,7 @@ CreateEventRing (
   EventRing->EventRingCCS = 1;\r
 \r
   Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER;\r
-  Buf  = UsbHcAllocateMem (Xhc->MemPool, Size);\r
+  Buf  = UsbHcAllocateMem (Xhc->MemPool, Size, FALSE);\r
   ASSERT (Buf != NULL);\r
   ASSERT (((UINTN)Buf & 0x3F) == 0);\r
   ZeroMem (Buf, Size);\r
@@ -892,7 +892,7 @@ CreateTransferRing (
   LINK_TRB              *EndTrb;\r
   EFI_PHYSICAL_ADDRESS  PhyAddr;\r
 \r
-  Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum);\r
+  Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum, TRUE);\r
   ASSERT (Buf != NULL);\r
   ASSERT (((UINTN)Buf & 0x3F) == 0);\r
   ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);\r
@@ -2182,7 +2182,7 @@ XhcInitializeDeviceSlot (
   // 4.3.3 Device Slot Initialization\r
   // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.\r
   //\r
-  InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT));\r
+  InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT), FALSE);\r
   ASSERT (InputContext != NULL);\r
   ASSERT (((UINTN)InputContext & 0x3F) == 0);\r
   ZeroMem (InputContext, sizeof (INPUT_CONTEXT));\r
@@ -2284,7 +2284,7 @@ XhcInitializeDeviceSlot (
   //\r
   // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
   //\r
-  OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT));\r
+  OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT), FALSE);\r
   ASSERT (OutputContext != NULL);\r
   ASSERT (((UINTN)OutputContext & 0x3F) == 0);\r
   ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT));\r
@@ -2398,7 +2398,7 @@ XhcInitializeDeviceSlot64 (
   // 4.3.3 Device Slot Initialization\r
   // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.\r
   //\r
-  InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64));\r
+  InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64), FALSE);\r
   ASSERT (InputContext != NULL);\r
   ASSERT (((UINTN)InputContext & 0x3F) == 0);\r
   ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));\r
@@ -2500,7 +2500,7 @@ XhcInitializeDeviceSlot64 (
   //\r
   // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.\r
   //\r
-  OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64));\r
+  OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64), FALSE);\r
   ASSERT (OutputContext != NULL);\r
   ASSERT (((UINTN)OutputContext & 0x3F) == 0);\r
   ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));\r