AcpiPlatformVTDHooks.c 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  1. /** @file
  2. ACPI Platform Driver VT-D Hooks
  3. @copyright
  4. Copyright 2012 - 2021 Intel Corporation. <BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "AcpiPlatform.h"
  8. #include "AcpiPlatformHooks.h"
  9. #include <Protocol/PciRootBridgeIo.h>
  10. #include <UncoreCommonIncludes.h>
  11. #include <IioSetupDefinitions.h>
  12. #include <PchInfoHob.h>
  13. extern EFI_PLATFORM_INFO *mPlatformInfo;
  14. extern BIOS_ACPI_PARAM *mAcpiParameter;
  15. extern EFI_IIO_UDS_PROTOCOL *mIioUds2;
  16. extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
  17. extern SYSTEM_CONFIGURATION mSystemConfiguration;
  18. extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
  19. extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration;
  20. extern EFI_GUID mSystemConfigurationGuid;
  21. extern BOOLEAN mX2ApicEnabled;
  22. #define EFI_PCI_CAPABILITY_PTR 0x34
  23. #define EFI_PCIE_CAPABILITY_BASE_OFFSET 0x100
  24. #define EFI_PCIE_CAPABILITY_ID_ACS 0x000D
  25. #define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10
  26. #define EFI_PCI_EXPRESS_CAPABILITY_REGISTER 0x02
  27. #define ACS_CAPABILITY_REGISTER 0x04
  28. #define ACS_SOURCE_VALIDATION BIT0
  29. #define ACS_P2P_REQUEST_REDIRECT BIT2
  30. #define ACS_P2P_COMPLETION_REDIRECT BIT3
  31. #define ACS_UPSTREAM_FORWARDING BIT4
  32. #define ACS_CONTROL_REGISTER 0x06
  33. #define ACS_SOURCE_VALIDATION_ENABLE BIT0
  34. #define ACS_P2P_REQUEST_REDIRECT_ENABLE BIT2
  35. #define ACS_P2P_COMPLETION_REDIRECT_ENABLE BIT3
  36. #define ACS_UPSTREAM_FORWARDING_ENABLE BIT4
  37. #define R_VTD_GCMD_REG 0x18
  38. #define R_VTD_GSTS_REG 0x1C
  39. #define R_VTD_IQT_REG 0x88
  40. #define R_VTD_IQA_REG 0x90
  41. #define R_VTD_IRTA_REG 0xB8
  42. #define VTD_ISOCH_ENGINE_OFFSET 0x1000
  43. //
  44. // a flag to indicate if we should disable Vt-d for ACS WA
  45. //
  46. BOOLEAN mDisableVtd = FALSE;
  47. DMA_REMAP_PROTOCOL DmaRemapProt;
  48. #define VTD_SUPPORT_INSTANCE_FROM_THIS(a) CR(a, VTD_SUPPORT_INSTANCE, DmaRemapProt, EFI_ACPI_6_2_DMA_REMAPPING_TABLE_SIGNATURE)
  49. #define EFI_PCI_CAPABILITY_ID_ATS 0x0F
  50. #define SEGMENT0 0x00
  51. #define MEM_BLK_COUNT 0x140
  52. #define INTRREMAP BIT3
  53. #define MEMORY_SIZE (MaxIIO * NUMBER_PORTS_PER_SOCKET)
  54. #define R_VTD_EXT_CAP_LOW 0x10
  55. #define R_VTD_EXT_CAP_HIGH 0x14
  56. #define IIO_STACK0 0
  57. #define IOAT_DEVICE_NUM_10NM 0x01
  58. PCI_NODE mPciPath0_1[] = {
  59. {PCI_DEVICE_NUMBER_PCH_HDA, PCI_FUNCTION_NUMBER_PCH_HDA},
  60. {(UINT8) -1, (UINT8) -1},
  61. };
  62. //
  63. // IOAPIC2 - IIO IoApic
  64. //
  65. PCI_NODE mPciPath2_0_10nm[] = {
  66. { PCIE_PORT_0_DEV_0, PCIE_PORT_0_FUNC_0 },
  67. { (UINT8)-1, (UINT8)-1 },
  68. };
  69. PCI_NODE mPciPath2_1_10nm[] = {
  70. { PCIE_PORT_1A_DEV_1, PCIE_PORT_1A_FUNC_1 },
  71. { (UINT8)-1, (UINT8)-1 },
  72. };
  73. PCI_NODE mPciPath2_2_10nm[] = {
  74. { PCIE_PORT_1B_DEV_1, PCIE_PORT_1B_FUNC_1 },
  75. { (UINT8)-1, (UINT8)-1 },
  76. };
  77. PCI_NODE mPciPath2_3_10nm[] = {
  78. { PCIE_PORT_1C_DEV_1, PCIE_PORT_1C_FUNC_1 },
  79. { (UINT8)-1, (UINT8)-1 },
  80. };
  81. PCI_NODE mPciPath2_4_10nm[] = {
  82. { PCIE_PORT_1D_DEV_1, PCIE_PORT_1D_FUNC_1 },
  83. { (UINT8)-1, (UINT8)-1 },
  84. };
  85. PCI_NODE mPciPath2_5_10nm[] = {
  86. { PCIE_PORT_2A_DEV_2, PCIE_PORT_2A_FUNC_2 },
  87. { (UINT8)-1, (UINT8)-1 },
  88. };
  89. PCI_NODE mPciPath2_6_10nm[] = {
  90. { PCIE_PORT_2B_DEV_2, PCIE_PORT_2B_FUNC_2 },
  91. { (UINT8)-1, (UINT8)-1 },
  92. };
  93. PCI_NODE mPciPath2_7_10nm[] = {
  94. { PCIE_PORT_2C_DEV_2, PCIE_PORT_2C_FUNC_2 },
  95. { (UINT8)-1, (UINT8)-1 },
  96. };
  97. PCI_NODE mPciPath2_8_10nm[] = {
  98. { PCIE_PORT_2D_DEV_2, PCIE_PORT_2D_FUNC_2 },
  99. { (UINT8)-1, (UINT8)-1 },
  100. };
  101. PCI_NODE mPciPath2_9_10nm[] = {
  102. { PCIE_PORT_3A_DEV_3, PCIE_PORT_3A_FUNC_3 },
  103. { (UINT8)-1, (UINT8)-1 },
  104. };
  105. PCI_NODE mPciPath2_10_10nm[] = {
  106. { PCIE_PORT_3B_DEV_3, PCIE_PORT_3B_FUNC_3 },
  107. { (UINT8)-1, (UINT8)-1 },
  108. };
  109. PCI_NODE mPciPath2_11_10nm[] = {
  110. { PCIE_PORT_3C_DEV_3, PCIE_PORT_3C_FUNC_3 },
  111. { (UINT8)-1, (UINT8)-1 },
  112. };
  113. PCI_NODE mPciPath2_12_10nm[] = {
  114. { PCIE_PORT_3D_DEV_3, PCIE_PORT_3D_FUNC_3 },
  115. { (UINT8)-1, (UINT8)-1 },
  116. };
  117. PCI_NODE mPciPath2_13_10nm[] = {
  118. { PCIE_PORT_4A_DEV_4, PCIE_PORT_4A_FUNC_4 },
  119. { (UINT8)-1, (UINT8)-1 },
  120. };
  121. PCI_NODE mPciPath2_14_10nm[] = {
  122. { PCIE_PORT_4B_DEV_4, PCIE_PORT_4B_FUNC_4 },
  123. { (UINT8)-1, (UINT8)-1 },
  124. };
  125. PCI_NODE mPciPath2_15_10nm[] = {
  126. { PCIE_PORT_4C_DEV_4, PCIE_PORT_4C_FUNC_4 },
  127. { (UINT8)-1, (UINT8)-1 },
  128. };
  129. PCI_NODE mPciPath2_16_10nm[] = {
  130. { PCIE_PORT_4D_DEV_4, PCIE_PORT_4D_FUNC_4 },
  131. { (UINT8)-1, (UINT8)-1 },
  132. };
  133. PCI_NODE mPciPath2_17_10nm[] = {
  134. { PCIE_PORT_5A_DEV_5, PCIE_PORT_5A_FUNC_5 },
  135. { (UINT8)-1, (UINT8)-1 },
  136. };
  137. PCI_NODE mPciPath2_18_10nm[] = {
  138. { PCIE_PORT_5B_DEV_5, PCIE_PORT_5B_FUNC_5 },
  139. { (UINT8)-1, (UINT8)-1 },
  140. };
  141. PCI_NODE mPciPath2_19_10nm[] = {
  142. { PCIE_PORT_5C_DEV_5, PCIE_PORT_5C_FUNC_5 },
  143. { (UINT8)-1, (UINT8)-1 },
  144. };
  145. PCI_NODE mPciPath2_20_10nm[] = {
  146. { PCIE_PORT_5D_DEV_5, PCIE_PORT_5D_FUNC_5 },
  147. { (UINT8)-1, (UINT8)-1 },
  148. };
  149. DEVICE_SCOPE mDevScopeDRHD[] = {
  150. {
  151. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT, // Device type - HD Audio
  152. 00, // Enumeration ID
  153. DEFAULT_PCI_BUS_NUMBER_PCH, // Start Bus Number
  154. &mPciPath0_1[0]
  155. },
  156. };
  157. DEVICE_SCOPE mDevScopeATSR10nm[] = {
  158. {
  159. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port1
  160. 00, // Enumeration ID
  161. DMI_BUS_NUM,
  162. &mPciPath2_0_10nm[0]
  163. },
  164. {
  165. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port2
  166. 00, // Enumeration ID
  167. DMI_BUS_NUM,
  168. &mPciPath2_1_10nm[0]
  169. },
  170. {
  171. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port3
  172. 00, // Enumeration ID
  173. DMI_BUS_NUM,
  174. &mPciPath2_2_10nm[0]
  175. },
  176. {
  177. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port4
  178. 00, // Enumeration ID
  179. DMI_BUS_NUM,
  180. &mPciPath2_3_10nm[0]
  181. },
  182. {
  183. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port5
  184. 00, // Enumeration ID
  185. DMI_BUS_NUM,
  186. &mPciPath2_4_10nm[0]
  187. },
  188. {
  189. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port6
  190. 00, // Enumeration ID
  191. DMI_BUS_NUM,
  192. &mPciPath2_5_10nm[0]
  193. },
  194. {
  195. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port7
  196. 00, // Enumeration ID
  197. DMI_BUS_NUM,
  198. &mPciPath2_6_10nm[0]
  199. },
  200. {
  201. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port8
  202. 00, // Enumeration ID
  203. DMI_BUS_NUM,
  204. &mPciPath2_7_10nm[0]
  205. },
  206. {
  207. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port9
  208. 00, // Enumeration ID
  209. DMI_BUS_NUM,
  210. &mPciPath2_8_10nm[0]
  211. },
  212. {
  213. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port10
  214. 00, // Enumeration ID
  215. DMI_BUS_NUM,
  216. &mPciPath2_9_10nm[0]
  217. },
  218. {
  219. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port11
  220. 00, // Enumeration ID
  221. DMI_BUS_NUM,
  222. &mPciPath2_10_10nm[0]
  223. },
  224. {
  225. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port12
  226. 00, // Enumeration ID
  227. DMI_BUS_NUM,
  228. &mPciPath2_11_10nm[0]
  229. },
  230. {
  231. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port13
  232. 00, // Enumeration ID
  233. DMI_BUS_NUM,
  234. &mPciPath2_12_10nm[0]
  235. },
  236. {
  237. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port14
  238. 00, // Enumeration ID
  239. DMI_BUS_NUM,
  240. &mPciPath2_13_10nm[0]
  241. },
  242. {
  243. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port15
  244. 00, // Enumeration ID
  245. DMI_BUS_NUM,
  246. &mPciPath2_14_10nm[0]
  247. },
  248. {
  249. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port16
  250. 00, // Enumeration ID
  251. DMI_BUS_NUM,
  252. &mPciPath2_15_10nm[0]
  253. },
  254. {
  255. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port17
  256. 00, // Enumeration ID
  257. DMI_BUS_NUM,
  258. &mPciPath2_16_10nm[0]
  259. },
  260. {
  261. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port18
  262. 00, // Enumeration ID
  263. DMI_BUS_NUM,
  264. &mPciPath2_17_10nm[0]
  265. },
  266. {
  267. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port19
  268. 00, // Enumeration ID
  269. DMI_BUS_NUM,
  270. &mPciPath2_18_10nm[0]
  271. },
  272. {
  273. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port20
  274. 00, // Enumeration ID
  275. DMI_BUS_NUM,
  276. &mPciPath2_19_10nm[0]
  277. },
  278. {
  279. EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port21
  280. 00, // Enumeration ID
  281. DMI_BUS_NUM,
  282. &mPciPath2_20_10nm[0]
  283. }
  284. };
  285. DMAR_DRHD mDrhd = {
  286. DRHD_SIGNATURE,
  287. 00, // Flags
  288. SEGMENT0, // Segment number
  289. 00, // Base Address
  290. 00, // Number of dev scope structures
  291. &mDevScopeDRHD[0]
  292. };
  293. DMAR_DRHD mDrhdIsoc = {
  294. DRHD_SIGNATURE,
  295. 00, // Flags
  296. SEGMENT0, // Segment number
  297. 00, // Base Address
  298. 00, // Number of dev scope structures
  299. &mDevScopeDRHD[0]
  300. };
  301. DMAR_ATSR mAtsr10nm = {
  302. ATSR_SIGNATURE,
  303. SEGMENT0, // Segment number
  304. 00,
  305. NUMBER_PORTS_PER_SOCKET - 1,
  306. 00,
  307. &mDevScopeATSR10nm[0]
  308. };
  309. PCI_NODE mPciPath[] = {
  310. { 00, 00},
  311. { (UINT8)-1, (UINT8)-1},
  312. };
  313. UINT8 IoApicID[] = { PCH_IOAPIC_ID, //PCH
  314. PC00_IOAPIC_ID, PC01_IOAPIC_ID, PC02_IOAPIC_ID, PC03_IOAPIC_ID, PC04_IOAPIC_ID, PC05_IOAPIC_ID, //Socket0
  315. PC06_IOAPIC_ID, PC07_IOAPIC_ID, PC08_IOAPIC_ID, PC09_IOAPIC_ID, PC10_IOAPIC_ID, PC11_IOAPIC_ID, //Socket1
  316. PC12_IOAPIC_ID, PC13_IOAPIC_ID, PC14_IOAPIC_ID, PC15_IOAPIC_ID, PC16_IOAPIC_ID, PC17_IOAPIC_ID, //Socket2
  317. PC18_IOAPIC_ID, PC19_IOAPIC_ID, PC20_IOAPIC_ID, PC21_IOAPIC_ID, PC22_IOAPIC_ID, PC23_IOAPIC_ID, //Socket3
  318. PC24_IOAPIC_ID, PC25_IOAPIC_ID, PC26_IOAPIC_ID, PC27_IOAPIC_ID, PC28_IOAPIC_ID, PC29_IOAPIC_ID, //Socket4
  319. PC30_IOAPIC_ID, PC31_IOAPIC_ID, PC32_IOAPIC_ID, PC33_IOAPIC_ID, PC34_IOAPIC_ID, PC35_IOAPIC_ID, //Socket5
  320. PC36_IOAPIC_ID, PC37_IOAPIC_ID, PC38_IOAPIC_ID, PC39_IOAPIC_ID, PC40_IOAPIC_ID, PC41_IOAPIC_ID, //Socket6
  321. PC42_IOAPIC_ID, PC43_IOAPIC_ID, PC44_IOAPIC_ID, PC45_IOAPIC_ID, PC46_IOAPIC_ID, PC47_IOAPIC_ID, //Socket7
  322. };
  323. PCI_NODE mPciPath7[] = {
  324. { PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI },
  325. { (UINT8)-1, (UINT8)-1},
  326. };
  327. DEVICE_SCOPE DevScopeRmrr[] = {
  328. {
  329. 1, // RMRR dev Scope - XHCI
  330. 0, // Enumeration ID
  331. 0, // Start Bus Number
  332. &mPciPath7[0]
  333. },
  334. };
  335. DMAR_RMRR mRmrr = {
  336. RMRR_SIGNATURE, // Signature
  337. SEGMENT0, // Segment number
  338. ' ', // Reserved Memory RegionBase Address
  339. ' ', // Reserved Memory RegionLimit Address
  340. ' ', // Number of Dev Scope structures
  341. &DevScopeRmrr[0]
  342. };
  343. typedef struct {
  344. UINT8 aBuf[32];
  345. } MEM_BLK;
  346. DMAR_RHSA mRhsa;
  347. typedef struct {
  348. UINT8 Bus;
  349. UINT8 Dev;
  350. UINT8 Func;
  351. } DMAR_DEVICE;
  352. EFI_STATUS
  353. LocateCapRegBlock(
  354. IN EFI_PCI_IO_PROTOCOL *PciIo,
  355. IN UINT8 CapID,
  356. OUT UINT8 *PciExpressOffset,
  357. OUT UINT8 *NextRegBlock
  358. );
  359. EFI_STATUS
  360. LocatePciExpressCapRegBlock (
  361. IN EFI_PCI_IO_PROTOCOL *PciIo,
  362. IN UINT16 CapID,
  363. OUT UINT32 *Offset,
  364. OUT UINT32 *NextRegBlock
  365. );
  366. DMAR_DRHD mDrhd;
  367. DMAR_RHSA mRhsa;
  368. DMAR_ATSR* GetDmarAtsrTablePointer (
  369. VOID
  370. )
  371. {
  372. DMAR_ATSR* pAtsr = NULL;
  373. pAtsr = &mAtsr10nm;
  374. return pAtsr;
  375. }
  376. /**
  377. Enable VT-d interrupt remapping.
  378. This function should be called late at ReadyToBoot event. If called in AcpiVtdTablesInstall()
  379. would hang in CpuDeadLoop() because of timeout when waiting for invalidation commands complete.
  380. **/
  381. VOID
  382. AcpiVtdIntRemappingEnable (
  383. VOID
  384. )
  385. {
  386. EFI_STATUS Status;
  387. UINT64 *xApicAddr;
  388. UINT64 *IRTA;
  389. UINT64 *Addr;
  390. UINT64 Value=0;
  391. UINT16 IRTECount;
  392. UINT16 Count;
  393. UINT64 IRTEValue;
  394. UINT8 RemapEng;
  395. UINT8 RemapEngCount;
  396. EFI_CPUID_REGISTER CpuidRegisters;
  397. UINT32 VtdBarAddress;
  398. UINT8 Stack;
  399. VTD_SUPPORT_INSTANCE *DmarPrivateData;
  400. DMA_REMAP_PROTOCOL *DmaRemap = NULL;
  401. static volatile UINT64 TempQWord[MaxIIO] = {0};
  402. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  403. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  404. if (EFI_ERROR (Status)) {
  405. ASSERT_EFI_ERROR (Status);
  406. return;
  407. }
  408. Status = gBS->LocateProtocol (&gDmaRemapProtocolGuid, NULL, (VOID **) &DmaRemap);
  409. if (EFI_ERROR (Status) || !DmaRemap->VTdSupport || !DmaRemap->InterruptRemap) {
  410. DEBUG ((DEBUG_INFO, "[VTD] %a disabled\n",
  411. (DmaRemap != NULL && DmaRemap->VTdSupport) ? "Interrupt remapping" : "Virtualization Technology for Directed I/O"));
  412. return;
  413. }
  414. ASSERT (mIioUds2);
  415. IRTEValue = 00;
  416. RemapEng = 0;
  417. RemapEngCount = mIioUds2->IioUdsPtr->PlatformData.numofIIO;
  418. DmarPrivateData = VTD_SUPPORT_INSTANCE_FROM_THIS (DmaRemap);
  419. if (RemapEngCount > NELEMENTS (TempQWord)) {
  420. DEBUG ((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Number of IIO exceed internal table (%d > %d)\n", RemapEngCount, NELEMENTS (TempQWord)));
  421. RemapEngCount = NELEMENTS (TempQWord);
  422. }
  423. //
  424. // Xapic tables update
  425. //
  426. IRTECount = 16 * 24; // Total 24 IRTE entries with 128 bits each.
  427. //
  428. // Allocate 4K alligned space for IRTE entries Added extra space of 500 bytes.
  429. //
  430. Status = gBS->AllocatePool (EfiACPIReclaimMemory, IRTECount + 0x1500, (VOID **) &xApicAddr);
  431. ASSERT_EFI_ERROR (Status);
  432. //
  433. // Allocate IRT - Allocate zero-initialized, 4KB aligned, 4KB memory for interrupt-remap-table and mark this memory as "ACPI Reclaim Memory"
  434. //
  435. xApicAddr = (UINT64 *)((UINT64)xApicAddr & (~0xFFF));
  436. ZeroMem (xApicAddr, IRTECount +0x1500);
  437. //
  438. // 1. Program IRTE - Initialize the interrupt-remap-table as follows: (this table will be shared by all VT-d units)
  439. //
  440. for (Count = 0; Count < 24; Count++) {
  441. IRTEValue = 00;
  442. if (Count == 0) {
  443. IRTEValue = (7 << 05) + 03; // Preset flag set, Ext int enabled, FPD set
  444. }
  445. AsmCpuid (
  446. CPUID_EXTENDED_TOPOLOGY,
  447. &CpuidRegisters.RegEax,
  448. &CpuidRegisters.RegEbx,
  449. &CpuidRegisters.RegEcx,
  450. &CpuidRegisters.RegEdx
  451. );
  452. IRTEValue |= (UINT64)CpuidRegisters.RegEdx << 32; // Destination Processor Apic ID
  453. *(volatile UINT64 *)((UINT64)xApicAddr + (Count * 16))= IRTEValue;
  454. //
  455. // Perform a CLFLUSH instruction for each cachline in this 4KB memory to ensure that updates to the interrupt-remap-table are visible in memory
  456. //
  457. AsmFlushCacheLine ((VOID *)((UINT64)xApicAddr + (Count * 16)));
  458. }
  459. //
  460. // 3. Program the VT-D remap engines
  461. //
  462. for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) {
  463. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  464. //
  465. // Check for valid stack
  466. //
  467. if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) {
  468. continue;
  469. }
  470. VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack);
  471. if (VtdBarAddress) {
  472. //
  473. // 2. For each VT-d unit in the platform, allocate and initialize the invalidation queue/commands as follows
  474. //
  475. //
  476. // Allocate memory for the queued invalidation.
  477. //
  478. Status = gBS->AllocatePool (EfiACPIReclaimMemory, 0x1000 + 0x1000, (VOID **) &Addr);
  479. if (EFI_ERROR (Status)) {
  480. ASSERT (FALSE);
  481. return;
  482. }
  483. ZeroMem (Addr, 0x1000 + 0x1000);
  484. Addr = (UINT64 *)((UINT64)Addr & (~0xFFF));
  485. //
  486. // Submit two descriptors to the respective VT-d unit's invalidation queue as follows:
  487. // Program 1st descriptor in invalidation-queue as Interrupt-Entry-Cache Invalidation Descriptor
  488. // with G (Granularity) field Clear
  489. //
  490. Addr[0] = 0x04; // Interrupt Entry Cache Invalidate Descriptor
  491. Addr[1] = 0x00;
  492. //
  493. // Program 2nd descriptor in invalidation-queue as Invalidation-Wait-Descriptor as follows: +Status-Data=1
  494. // +Status-Address=address of variable tmp[unit +SW=1 +FN=1 +IF=0
  495. //
  496. Addr[2] = ((UINT64)1 << 32) + (06 << 04) + 05; // Invalidation Wait Descriptor
  497. TempQWord[RemapEng] = 00;
  498. Addr[3] = (UINTN)&TempQWord[RemapEng]; // Status Address [63:2] bits[127:65]
  499. //
  500. // 3. Program the IRTA register to point to the IRT table.
  501. // For each VT-d unit in the platform, program interrupt-remap-table address and enable extended-interrupt-mode as follows
  502. //
  503. IRTA = (UINT64 *)((UINT64)VtdBarAddress + R_VTD_IRTA_REG);
  504. Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG);
  505. //
  506. // *(volatile UINT64*)IRTA = 04 + 0x800 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] address
  507. //
  508. if (DmarPrivateData->Dmar->Flags && EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT) {
  509. *(volatile UINT64*)IRTA = 07 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] address
  510. *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GCMD_REG) = (UINT32)(Value | BIT23);
  511. } else {
  512. *(volatile UINT64*)IRTA = 07 + 0x800 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] addrerss
  513. }
  514. //
  515. // b. Set SIRTP in the command register.
  516. //
  517. Count = 0x1000;
  518. *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GCMD_REG) = (UINT32)(Value | BIT24);
  519. //
  520. // Wait till the status bit is set indicating the completion of the SIRTP.
  521. //
  522. while (Count) {
  523. Count--;
  524. Value = *(volatile UINT32 *)((UINT64)VtdBarAddress + R_VTD_GSTS_REG);
  525. if (Value & BIT24) {
  526. break;
  527. }
  528. }
  529. if (Count == 0) {
  530. ASSERT(FALSE);
  531. CpuDeadLoop ();
  532. }
  533. *(volatile UINT64 *)((UINT64)VtdBarAddress+ R_VTD_IQA_REG) = (UINT64)Addr;
  534. } // End of if (VtdBarAddress)
  535. } // End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++)
  536. }
  537. for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) {
  538. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  539. //
  540. // Check for valid stack
  541. //
  542. if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) {
  543. continue;
  544. }
  545. VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack);
  546. if (VtdBarAddress) {
  547. //
  548. // 4. For each VT-d unit in the platform, setup invalidation-queue base registers and enable invalidation as follows
  549. // Initialize a single descriptor which invalidates all the interrupt entries.
  550. // IQA register write (zeros IQH and IQT)
  551. //
  552. //
  553. // Enable queued invalidation in the command register.
  554. //
  555. Count = 0x1000;
  556. Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG);
  557. *(volatile UINT32 *)((UINT64)VtdBarAddress + R_VTD_GCMD_REG) = (UINT32)(Value | BIT26);
  558. while (Count) {
  559. Count--;
  560. Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG);
  561. if( Value & BIT26) {
  562. break;
  563. }
  564. }
  565. if (Count == 0) {
  566. ASSERT(FALSE);
  567. CpuDeadLoop ();
  568. }
  569. //
  570. // Start invalidations, program the IQT register
  571. // Write the invalidation queue tail (IQT_REG) register as follows to indicate to hardware two descriptors are submitted:
  572. // +Bits 63:19 are 0 +Bits 18:4 gets value of 2h +Bits 3:0 are 0
  573. //
  574. *(volatile UINT64 *)((UINT64)VtdBarAddress + R_VTD_IQT_REG) = (02 << 04); // Set tail to 02
  575. } // End of if (VtdAddress)
  576. } //End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++)
  577. }
  578. for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) {
  579. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  580. if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) {
  581. continue; // Skip invalid stacks
  582. }
  583. VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack);
  584. if (VtdBarAddress) {
  585. //
  586. // 5. For each VT-d unit in the platform, wait for invalidation completion, and enable interrupt remapping as follows
  587. // Wait till the previously submitted invalidation commands are completed as follows
  588. // Poll on the variable tmp[unit] in memory, until its value is 1h.
  589. //
  590. Count = 0x1000;
  591. while (Count) {
  592. Count--;
  593. Value = TempQWord[RemapEng];
  594. if (Value & 01) {
  595. break;
  596. }
  597. }
  598. if (Count == 0) {
  599. ASSERT(FALSE);
  600. CpuDeadLoop ();
  601. }
  602. } // End of if VtdBarAddress
  603. } //End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++)
  604. }
  605. //
  606. // 5. Enable external interrupts in the IOAPIC RTE entry 0
  607. //
  608. *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS) = 0x10;
  609. *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS + 0x10) = 0x00; // Set index to the IRTE0
  610. *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS) = 0x10+1;
  611. *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS + 0x10) = 0x10000;// Set Remap enable bit
  612. }
  613. /**
  614. Build DRHD entry into ACPI DMAR table for specific stack.
  615. Include IOxAPIC, PCIExpress ports, and CBDMA if C-STACK.
  616. @param DmaRemap - pointer to DMA remapping protocol
  617. @param IioIndex - IIO index to be processed
  618. @param Stack - stack index to be processed
  619. @param DevScope - buffer for device scope data structure
  620. @param PciNode - buffer for PCI node data structure
  621. @param PciRootBridgePtr- pointer to PciRootBridgeIo protocol for PCI access
  622. @retval EFI_SUCCESS - DRHD entry built successfully
  623. **/
  624. EFI_STATUS
  625. BuildDRHDForStack (
  626. DMA_REMAP_PROTOCOL *DmaRemap,
  627. UINT8 IioIndex,
  628. UINT8 Stack,
  629. DEVICE_SCOPE *DevScope,
  630. PCI_NODE *PciNode,
  631. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgePtr,
  632. UINT8 ApicIndex
  633. )
  634. {
  635. EFI_STATUS Status = EFI_SUCCESS;
  636. UINT8 Bus;
  637. UINT8 Dev;
  638. UINT8 Func;
  639. UINT8 DevIndex;
  640. UINT8 PciNodeIndex;
  641. UINT8 PortIndex;
  642. UINT8 MaxPortNumberPerSocket;
  643. UINT8 CBIndex;
  644. UINT64 VtdMmioExtCap;
  645. UINT32 VtdBase;
  646. UINT32 VidDid;
  647. DMAR_ATSR *pAtsr = NULL;
  648. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  649. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  650. if (EFI_ERROR (Status)) {
  651. ASSERT_EFI_ERROR (Status);
  652. return EFI_NOT_FOUND;
  653. }
  654. ASSERT (mIioUds2);
  655. if (Stack > MAX_IIO_STACK){
  656. return EFI_UNSUPPORTED;
  657. }
  658. if (PciRootBridgePtr == NULL) {
  659. ASSERT (!(PciRootBridgePtr == NULL));
  660. return EFI_INVALID_PARAMETER;
  661. }
  662. mDrhd.Flags = 0; // all non-legacy stack has INCLUDE_ALL flag cleared
  663. VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (IioIndex, Stack);
  664. if (VtdBase == 0) {
  665. return EFI_UNSUPPORTED;
  666. }
  667. VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW);
  668. mDrhd.RegisterBase = VtdBase;
  669. DevIndex = 00;
  670. PciNodeIndex = 00;
  671. mDrhd.DeviceScopeNumber = 00;
  672. ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
  673. ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
  674. //
  675. // DRHD - CBDMA entry
  676. //
  677. if (Stack == IIO_STACK0) {
  678. for (CBIndex = 0; CBIndex <= 7; CBIndex++) {
  679. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
  680. DevScope[DevIndex].EnumerationID = 00;
  681. DevScope[DevIndex].StartBusNumber = mCpuCsrAccessVarPtr ->StackBus[IioIndex][IIO_STACK0];
  682. DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
  683. PciNode[PciNodeIndex].Device = IOAT_DEVICE_NUM_10NM;
  684. PciNode[PciNodeIndex].Function = CBIndex;
  685. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD CBDMA: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
  686. IioIndex, Stack,
  687. DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
  688. DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
  689. DevIndex++;
  690. PciNodeIndex++;
  691. PciNode[PciNodeIndex].Device = (UINT8) -1;
  692. PciNode[PciNodeIndex].Function = (UINT8) -1;
  693. PciNodeIndex++;
  694. mDrhd.DeviceScopeNumber++;
  695. } // End of for for(CBIndex = 0; CBIndex <= 07; CBIndex++)
  696. }
  697. //
  698. // DRHD - PCI-Ex ports
  699. //
  700. pAtsr = GetDmarAtsrTablePointer ();
  701. MaxPortNumberPerSocket = DynamicSiLibraryProtocol2->GetMaxPortPerSocket (IioIndex);
  702. for (PortIndex = 1; PortIndex < MaxPortNumberPerSocket; PortIndex++) {
  703. if (DynamicSiLibraryProtocol2->GetStackPerPort (IioIndex, PortIndex) != Stack) {
  704. continue;
  705. }
  706. Bus = DynamicSiLibraryProtocol2->GetSocketPortBusNum (IioIndex, PortIndex);
  707. Dev = 0;
  708. Func = 0;
  709. if (pAtsr != NULL) {
  710. Dev = pAtsr->DeviceScope[PortIndex].PciNode->Device;
  711. Func = pAtsr->DeviceScope[PortIndex].PciNode->Function;
  712. }
  713. if (DynamicSiLibraryProtocol2->IioNtbIsEnabled (IioIndex, PortIndex, &Dev, &Func)) {
  714. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
  715. } else {
  716. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;
  717. }
  718. //
  719. // Skip root ports which do not respond to PCI configuration cycles.
  720. //
  721. VidDid = 0;
  722. Status = PciRootBridgePtr->Pci.Read (
  723. PciRootBridgePtr,
  724. EfiPciWidthUint32,
  725. EFI_PCI_ADDRESS (Bus, Dev, Func, 0),
  726. 1,
  727. &VidDid);
  728. if (EFI_ERROR (Status) || VidDid == 0xffffffff) {
  729. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %02X:%02X:%02X.%d Hidden (%X) - skip\n",
  730. IioIndex, Stack, PortIndex,
  731. mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[IioIndex].PcieSegment,
  732. Bus, Dev, Func, VidDid));
  733. continue;
  734. }
  735. if (DynamicSiLibraryProtocol2->IioVmdPortIsEnabled (IioIndex, PortIndex) || DynamicSiLibraryProtocol2->GetCurrentPXPMap (IioIndex, PortIndex) == 0) {
  736. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %a - skip\n", IioIndex, Stack, PortIndex,
  737. (DynamicSiLibraryProtocol2->GetCurrentPXPMap (IioIndex, PortIndex) == 0) ? "Link width not set" : "Dummy VMD function"));
  738. continue;
  739. }
  740. DevScope[DevIndex].EnumerationID = 00;
  741. DevScope[DevIndex].StartBusNumber = Bus;
  742. DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
  743. PciNode[PciNodeIndex].Device = Dev;
  744. PciNode[PciNodeIndex].Function = Func;
  745. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] Build DRHD PCI: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
  746. IioIndex, Stack, PortIndex,
  747. DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
  748. DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
  749. DevIndex++;
  750. PciNodeIndex++;
  751. PciNode[PciNodeIndex].Device = (UINT8) -1;
  752. PciNode[PciNodeIndex].Function = (UINT8) -1;
  753. PciNodeIndex++;
  754. mDrhd.DeviceScopeNumber++;
  755. } // for (PortIndex...)
  756. Status = DynamicSiLibraryProtocol2->IioVmdGetPciLocation (IioIndex, Stack,
  757. &PciNode[PciNodeIndex].Device, &PciNode[PciNodeIndex].Function);
  758. if (!EFI_ERROR (Status)) {
  759. //
  760. // VMD is enabled in this stack, expose VMD PCI device in DMAR for DMA remapping.
  761. //
  762. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
  763. DevScope[DevIndex].EnumerationID = 00;
  764. DevScope[DevIndex].StartBusNumber = mCpuCsrAccessVarPtr->StackBus[IioIndex][Stack];
  765. DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
  766. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD VMD: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
  767. IioIndex, Stack,
  768. DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
  769. DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
  770. DevIndex++;
  771. PciNodeIndex++;
  772. PciNode[PciNodeIndex].Device = (UINT8)-1;
  773. PciNode[PciNodeIndex].Function = (UINT8)-1;
  774. PciNodeIndex++;
  775. mDrhd.DeviceScopeNumber++;
  776. }
  777. DmaRemap->InsertDmaRemap (DmaRemap, DrhdType, &mDrhd);
  778. return EFI_SUCCESS;
  779. }
  780. EFI_STATUS
  781. ReportDmar (
  782. IN DMA_REMAP_PROTOCOL *DmaRemap
  783. )
  784. {
  785. EFI_STATUS Status = EFI_SUCCESS;
  786. UINT8 SocketIndex, IioBusBase, Bus;
  787. UINT8 Dev, Func;
  788. UINT8 DevIndex;
  789. UINT8 PciNodeIndex;
  790. UINT8 PciPortIndex;
  791. UINT8 MaxPortNumberPerSocket;
  792. UINT64 VtdMmioExtCap;
  793. UINT32 VtdBase;
  794. VTD_SUPPORT_INSTANCE *DmarPrivateData;
  795. UINT16 NumberOfHpets;
  796. UINT16 HpetCapIdValue;
  797. DEVICE_SCOPE *DevScope;
  798. PCI_NODE *PciNode;
  799. EFI_PHYSICAL_ADDRESS Pointer;
  800. UINT32 AlignedSize;
  801. UINT32 NumberofPages;
  802. BOOLEAN IntrRemapSupport;
  803. EFI_CPUID_REGISTER CpuidRegisters;
  804. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgePtr;
  805. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeTab[MAX_SOCKET];
  806. UINT32 VidDid;
  807. UINT8 Index;
  808. UINT8 Stack = 0;
  809. UINT8 FirstRun = 0;
  810. VOID *HobPtr;
  811. PCH_INFO_HOB *PchInfoHob;
  812. DMAR_ATSR *pAtsr = NULL;
  813. UINT8 ApicIndex = 1;
  814. UINTN HandleCount;
  815. EFI_HANDLE *HandleBuffer;
  816. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  817. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  818. if (EFI_ERROR (Status)) {
  819. ASSERT_EFI_ERROR (Status);
  820. return FALSE;
  821. }
  822. HobPtr = GetFirstGuidHob (&gPchInfoHobGuid);
  823. if (HobPtr == NULL) {
  824. ASSERT (HobPtr != NULL);
  825. return EFI_INVALID_PARAMETER;
  826. }
  827. PchInfoHob = (PCH_INFO_HOB*) GET_GUID_HOB_DATA (HobPtr);
  828. if (PchInfoHob == NULL) {
  829. ASSERT (PchInfoHob != NULL);
  830. return EFI_INVALID_PARAMETER;
  831. }
  832. ASSERT (mIioUds2);
  833. DmarPrivateData = VTD_SUPPORT_INSTANCE_FROM_THIS (DmaRemap);
  834. //
  835. // Get DMAR_HOST_ADDRESS_WIDTH from CPUID.(EAX=80000008h) return the Phyical Address
  836. // Size in the EAX register. EAX[7:0]
  837. // Sync with Brickland code DMAR_HOST_ADDRESS_WIDTH 45 = 46 - 1
  838. //
  839. AsmCpuid (
  840. CPUID_VIR_PHY_ADDRESS_SIZE,
  841. &CpuidRegisters.RegEax,
  842. &CpuidRegisters.RegEbx,
  843. &CpuidRegisters.RegEcx,
  844. &CpuidRegisters.RegEdx
  845. );
  846. DmarPrivateData->Dmar->HostAddressWidth = (UINT8)((CpuidRegisters.RegEax & 0xFF)-1);
  847. DmarPrivateData->Dmar->Flags = 0; // INTR_REMAP
  848. //
  849. // Locate PCI root bridge I/O protocol, for confirming PCI functions respond
  850. // to PCI configuration cycles.
  851. //
  852. ZeroMem (&PciRootBridgeTab[0], sizeof(PciRootBridgeTab));
  853. Status = gBS->LocateHandleBuffer (
  854. ByProtocol,
  855. &gEfiPciRootBridgeIoProtocolGuid,
  856. NULL,
  857. &HandleCount,
  858. &HandleBuffer
  859. );
  860. ASSERT_EFI_ERROR (Status);
  861. for (Index = 0; Index < HandleCount; Index ++) {
  862. Status = gBS->HandleProtocol (
  863. HandleBuffer[Index],
  864. &gEfiPciRootBridgeIoProtocolGuid,
  865. (VOID **) &PciRootBridgePtr
  866. );
  867. ASSERT_EFI_ERROR (Status);
  868. PciRootBridgeTab[PciRootBridgePtr->SegmentNumber] = PciRootBridgePtr;
  869. }
  870. FreePool (HandleBuffer);
  871. //
  872. // Allocate memory to DevScope structures
  873. //
  874. Status = gBS->AllocatePool (EfiACPIMemoryNVS, MEMORY_SIZE * sizeof (DEVICE_SCOPE), (VOID **) &DevScope);
  875. ASSERT_EFI_ERROR (Status);
  876. Status = gBS->AllocatePool (EfiACPIMemoryNVS, MEMORY_SIZE * sizeof (PCI_NODE), (VOID **) &PciNode);
  877. ASSERT_EFI_ERROR (Status);
  878. for (Index = 1; Index <= MAX_SOCKET; Index++) {
  879. //
  880. // VT-d specification request that DHRD entry 0 should be the latest entry of the DMAR table.
  881. // To accomplish this, the following check will ensure that latest entry will be the one related to Socket 0.
  882. //
  883. if (Index == MAX_SOCKET) {
  884. SocketIndex = 0;
  885. } else {
  886. SocketIndex = Index;
  887. }
  888. if (SocketIndex >= MAX_SOCKET) {
  889. return EFI_INVALID_PARAMETER;
  890. }
  891. if (!DynamicSiLibraryProtocol2->SocketPresent (SocketIndex)) {
  892. continue;
  893. }
  894. if (mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment >= MAX_SOCKET) {
  895. return EFI_INVALID_PARAMETER;
  896. }
  897. PciRootBridgePtr = PciRootBridgeTab[mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment];
  898. Stack = IIO_STACK0;
  899. VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack);
  900. DevIndex = 00;
  901. PciNodeIndex = 00;
  902. mDrhd.Signature = DRHD_SIGNATURE;
  903. mDrhd.SegmentNumber = mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment;
  904. mDrhd.DeviceScopeNumber = 00;
  905. mDrhd.DeviceScope = DevScope;
  906. mDrhd.RegisterBase = VtdBase;
  907. ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
  908. ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
  909. VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW);
  910. //
  911. // Check Interrupt Remap support.
  912. //
  913. IntrRemapSupport = FALSE;
  914. if (VtdMmioExtCap & INTRREMAP) {
  915. IntrRemapSupport = TRUE;
  916. }
  917. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] VT-d base 0x%X, ExtCap=0x%X\n",
  918. SocketIndex, Stack, VtdBase, VtdMmioExtCap));
  919. if (SocketIndex == 0) {
  920. ApicIndex = 1;
  921. //
  922. // DRHD - Legacy IOH
  923. //
  924. // Build DRHD on IIO0 - Stack1 to Stack5, not include C-STACK
  925. //
  926. for (Stack = 1; Stack < MAX_IIO_STACK; Stack++) {
  927. if (!DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex, Stack)) { // Skip invalid stack
  928. continue;
  929. }
  930. BuildDRHDForStack (DmaRemap, SocketIndex, Stack, DevScope, PciNode, PciRootBridgePtr, ApicIndex);
  931. ApicIndex++;
  932. }
  933. Stack = IIO_STACK0;
  934. //
  935. // Re-initialize DRHD template for DRHD entry in legacy socket C-STACK
  936. //
  937. DevIndex = 00;
  938. PciNodeIndex = 00;
  939. mDrhd.DeviceScopeNumber = 00;
  940. mDrhd.RegisterBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack);
  941. ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
  942. ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
  943. IioBusBase = mCpuCsrAccessVarPtr ->StackBus[SocketIndex][Stack]; // Stack 0
  944. mDrhd.Flags = 1;
  945. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) InterruptRemap is %aabled (%d & %d)\n",
  946. (DmaRemap->InterruptRemap && IntrRemapSupport) ? "en" : "dis", DmaRemap->InterruptRemap, IntrRemapSupport));
  947. if (DmaRemap->InterruptRemap && IntrRemapSupport) {
  948. DmarPrivateData->Dmar->Flags = 0x01; // INTR_REMAP
  949. if (DmaRemap->X2ApicOptOut) {
  950. DmarPrivateData->Dmar->Flags |= 0x02; // X2APIC_OPT_OUT
  951. }
  952. //
  953. // PCH - IOAPIC
  954. // This information will be provided by PCH side
  955. // Currently is a hard-coded temporal solution to set:
  956. // Bus = 0; Device and Function (together) = 0xF7;
  957. // This is the value that is stored in IBDF register:
  958. //#define V_P2SB_CFG_IBDF_BUS 0
  959. //#define V_P2SB_CFG_IBDF_DEV 30
  960. //#define V_P2SB_CFG_IBDF_FUNC 7
  961. //
  962. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC;
  963. DevScope[DevIndex].EnumerationID = PCH_IOAPIC_ID; // PCH team needs confirm this value. (This value affects VTd functionality?)
  964. DevScope[DevIndex].StartBusNumber = (UINT8)PchInfoHob->IoApicBusNum;
  965. DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
  966. PciNode[PciNodeIndex].Device = (UINT8)PchInfoHob->IoApicDevNum;
  967. PciNode[PciNodeIndex].Function = (UINT8)PchInfoHob->IoApicFuncNum;
  968. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD PCH IOAPIC: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
  969. SocketIndex, Stack,
  970. DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
  971. DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
  972. DevIndex++;
  973. PciNodeIndex++;
  974. PciNode[PciNodeIndex].Device = (UINT8)-1;
  975. PciNode[PciNodeIndex].Function = (UINT8)-1;
  976. PciNodeIndex++;
  977. mDrhd.DeviceScopeNumber++;
  978. HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BLOCK_ADDRESS);
  979. NumberOfHpets = (HpetCapIdValue >> 0x08) & 0x1F; // Bits [8:12] contains the number of Hpets
  980. if (NumberOfHpets && (NumberOfHpets != 0x1f) &&
  981. (*((volatile UINT32 *)(UINTN)(HPET_BLOCK_ADDRESS + 0x100)) & BIT15)) {
  982. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET;
  983. DevScope[DevIndex].EnumerationID = 00; //Hard-coded
  984. DevScope[DevIndex].StartBusNumber = (UINT8)PchInfoHob->HpetBusNum;
  985. DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
  986. PciNode[PciNodeIndex].Device = (UINT8)PchInfoHob->HpetDevNum;
  987. PciNode[PciNodeIndex].Function = (UINT8)PchInfoHob->HpetFuncNum;
  988. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD HPET: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
  989. SocketIndex, Stack,
  990. DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
  991. DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
  992. DevIndex++;
  993. PciNodeIndex++;
  994. PciNode[PciNodeIndex].Device = (UINT8)-1;
  995. PciNode[PciNodeIndex].Function = (UINT8)-1;
  996. PciNodeIndex++;
  997. mDrhd.DeviceScopeNumber++;
  998. }
  999. } // DmaRemap->InterruptRemap
  1000. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) DMA_CTRL_PLATFORM_OPT_IN_FLAG is %aabled\n", (DmaRemap->DmaCtrlOptIn) ? "En" : "Dis"));
  1001. if (DmaRemap->DmaCtrlOptIn) {
  1002. DmarPrivateData->Dmar->Flags |= 0x04; // DMA_CTRL_PLATFORM_OPT_IN_FLAG
  1003. }
  1004. DmaRemap->InsertDmaRemap (DmaRemap, DrhdType, &mDrhd);
  1005. } else { // End of if (IioSocketId == 0)
  1006. if (FirstRun == 0) {
  1007. ApicIndex = 0;
  1008. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  1009. //
  1010. // Skip not valid stack
  1011. //
  1012. if (!DynamicSiLibraryProtocol2->IfStackPresent (0 ,Stack)) {
  1013. continue;
  1014. }
  1015. ApicIndex++;
  1016. }
  1017. FirstRun = 1;
  1018. }
  1019. //
  1020. // Build DRHD on IIO1 - Stack0 to Stack5
  1021. //
  1022. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  1023. //
  1024. // Skip not valid stack
  1025. //
  1026. if (!DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex,Stack)) {
  1027. continue;
  1028. }
  1029. BuildDRHDForStack (DmaRemap, SocketIndex, Stack, DevScope, PciNode, PciRootBridgePtr, ApicIndex);
  1030. ApicIndex++;
  1031. } //for( StackIndex=0; StackIndex<MAX_IIO_STACK ; StackIndex++) {
  1032. } // End of if (IioSocketId == 0)
  1033. } // End of for ( Index = 1; Index <= MAX_SOCKET; Index++)
  1034. //
  1035. // ATSR
  1036. //
  1037. pAtsr = GetDmarAtsrTablePointer ();
  1038. if (DmaRemap->ATS) {
  1039. for (SocketIndex = 0; SocketIndex < MAX_SOCKET; SocketIndex++) {
  1040. DEBUG((DEBUG_ERROR, "T_TEST: Build ATSR SocketIndex=%d.\n", SocketIndex));
  1041. DEBUG((DEBUG_ERROR, " IIO_resource.valid=%d.\n", mIioUds2->IioUdsPtr->PlatformData.IIO_resource[SocketIndex].Valid));
  1042. if (SocketIndex >= MAX_SOCKET) {
  1043. return EFI_INVALID_PARAMETER;
  1044. }
  1045. if (!DynamicSiLibraryProtocol2->SocketPresent (SocketIndex)) {
  1046. continue;
  1047. }
  1048. IioBusBase = mIioUds2->IioUdsPtr->PlatformData.IIO_resource[SocketIndex].BusBase;
  1049. if (mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment >= MAX_SOCKET) {
  1050. return EFI_INVALID_PARAMETER;
  1051. }
  1052. PciRootBridgePtr = PciRootBridgeTab[mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment];
  1053. PciNodeIndex = 00;
  1054. DevIndex = 00;
  1055. ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
  1056. ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
  1057. if (pAtsr != NULL) {
  1058. pAtsr->Signature = ATSR_SIGNATURE;
  1059. pAtsr->Flags = 00;
  1060. pAtsr->SegmentNumber = mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment;
  1061. pAtsr->DeviceScopeNumber = 00;
  1062. pAtsr->DeviceScope = DevScope;
  1063. pAtsr->ATSRPresentBit = (UINT32)-1; // Not useful really Backwards project compatability (remove it later)
  1064. }
  1065. //
  1066. // Loop From Port 1 to 15 for Legacy IOH and 0 to 15 for Non-Legacy IOH
  1067. //
  1068. MaxPortNumberPerSocket = DynamicSiLibraryProtocol2->GetMaxPortPerSocket (SocketIndex);
  1069. for (PciPortIndex = 1; PciPortIndex < MaxPortNumberPerSocket; PciPortIndex++) {
  1070. //
  1071. // Check device IOTLBs supported or not in VT-d Extended capability register
  1072. //
  1073. Stack = DynamicSiLibraryProtocol2->GetStackPerPort (SocketIndex, PciPortIndex);
  1074. //
  1075. // Check for a valid stack
  1076. //
  1077. if (!(DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex, Stack))) {
  1078. DEBUG ((DEBUG_WARN, "[ACPI](DMAR) [%d.%d p%d] Stack not present\n", SocketIndex, Stack, PciPortIndex));
  1079. continue;
  1080. }
  1081. VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack);
  1082. if (VtdBase != 0) {
  1083. VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW);
  1084. //
  1085. // ATSR is applicable only for platform supporting device IOTLBs through the VT-d extended capability register
  1086. //
  1087. if ((VtdMmioExtCap & BIT2) != 0) {
  1088. Bus = DynamicSiLibraryProtocol2->GetSocketPortBusNum (SocketIndex,PciPortIndex);
  1089. Dev = 0;
  1090. Func = 0;
  1091. Dev = mDevScopeATSR10nm[PciPortIndex].PciNode->Device;
  1092. Func = mDevScopeATSR10nm[PciPortIndex].PciNode->Function;
  1093. if (DynamicSiLibraryProtocol2->IioNtbIsEnabled (SocketIndex, PciPortIndex, &Dev, &Func)) {
  1094. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
  1095. } else {
  1096. DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;
  1097. }
  1098. //
  1099. // Skip root ports which do not respond to PCI configuration cycles.
  1100. //
  1101. VidDid = 0;
  1102. Status = PciRootBridgePtr->Pci.Read (
  1103. PciRootBridgePtr,
  1104. EfiPciWidthUint32,
  1105. EFI_PCI_ADDRESS (Bus, Dev, Func, 0),
  1106. 1,
  1107. &VidDid);
  1108. if (EFI_ERROR (Status) || VidDid == 0xffffffff) {
  1109. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %02X:%02X:%02X.%d Hidden (%X) - skip\n",
  1110. SocketIndex, Stack, PciPortIndex,
  1111. mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment,
  1112. Bus, Dev, Func, VidDid));
  1113. continue;
  1114. }
  1115. if (DynamicSiLibraryProtocol2->IioVmdPortIsEnabled (SocketIndex, PciPortIndex) || DynamicSiLibraryProtocol2->GetCurrentPXPMap (SocketIndex, PciPortIndex) == 0) {
  1116. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %a - skip\n", SocketIndex, Stack, PciPortIndex,
  1117. (DynamicSiLibraryProtocol2->GetCurrentPXPMap (SocketIndex, PciPortIndex) == 0) ? "Link width not set" : "Dummy VMD function"));
  1118. continue;
  1119. }
  1120. DevScope[DevIndex].EnumerationID = 00;
  1121. DevScope[DevIndex].StartBusNumber = Bus;
  1122. DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
  1123. PciNode[PciNodeIndex].Device = Dev;
  1124. PciNode[PciNodeIndex].Function = Func;
  1125. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] Build DRHD PCI: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
  1126. SocketIndex, Stack, PciPortIndex,
  1127. DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
  1128. DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
  1129. DevIndex++;
  1130. PciNodeIndex++;
  1131. PciNode[PciNodeIndex].Device = (UINT8) -1;
  1132. PciNode[PciNodeIndex].Function = (UINT8) -1;
  1133. PciNodeIndex++;
  1134. if(pAtsr != NULL){
  1135. pAtsr->DeviceScopeNumber++;
  1136. }
  1137. } // End of if ((VtdMmioExtCap & BIT2) != 0)
  1138. } // End of if VtdBase
  1139. } // for (PciPortIndex...)
  1140. if (pAtsr != NULL){
  1141. if (pAtsr->DeviceScopeNumber) {
  1142. DmaRemap->InsertDmaRemap(DmaRemap, AtsrType, pAtsr);
  1143. }
  1144. }
  1145. } // End of for (RootBridgeLoop = 0; RootBridgeLoop < mIioUds2->IioUdsPtr->PlatformData.numofIIO; RootBridgeLoop++)
  1146. } // End of if (ATS) {
  1147. //
  1148. // RMRR
  1149. //
  1150. AlignedSize = (MEM_BLK_COUNT * sizeof(MEM_BLK));
  1151. if (AlignedSize % 0x1000) {
  1152. AlignedSize = ( (MEM_BLK_COUNT * sizeof(MEM_BLK)) & (~0xfff) ) + 0x1000;
  1153. } // aligend to 4k Boundary
  1154. NumberofPages = AlignedSize/0x1000;
  1155. //
  1156. // Allocate memory (below 4GB)
  1157. //
  1158. Pointer = 0xffffffff;
  1159. Status = gBS->AllocatePages (
  1160. AllocateMaxAddress,
  1161. EfiReservedMemoryType,
  1162. NumberofPages,
  1163. &Pointer // Base address need to be 4K aligned for VT-d RMRR
  1164. );
  1165. ASSERT_EFI_ERROR (Status);
  1166. if (DmaRemap->VTdSupport) {
  1167. //
  1168. // RMRR
  1169. //
  1170. mRmrr.DeviceScope = &DevScopeRmrr[0];
  1171. //
  1172. // Calculate the right size of DevScope for mRmrr entry
  1173. //
  1174. mRmrr.DeviceScopeNumber = sizeof(DevScopeRmrr) / sizeof(DEVICE_SCOPE);
  1175. mRmrr.RsvdMemBase = (UINT64)Pointer;
  1176. mRmrr.RsvdMemLimit = mRmrr.RsvdMemBase + AlignedSize - 1;
  1177. DEBUG ((DEBUG_INFO, "[ACPI](DMAR) RMRR Base 0x%llX, Limit 0x%llX\n", mRmrr.RsvdMemBase, mRmrr.RsvdMemLimit));
  1178. DmaRemap->InsertDmaRemap (DmaRemap, RmrrType, &mRmrr);
  1179. }
  1180. gBS->FreePool (PciNode);
  1181. gBS->FreePool (DevScope);
  1182. return EFI_SUCCESS;
  1183. }
  1184. /**
  1185. Install ACPI DMAR table for VT-d.
  1186. This function needs gEfiPciIoProtocolGuid so it can run only after PCI Enumeraion is complete.
  1187. @retval EFI_SUCCESS DMAR installed successfuly.
  1188. @retval EFI_NOT_FOUND gEfiPciIoProtocolGuid or gDmaRemapProtocolGuid not found.
  1189. @retval EFI_OUT_OF_RESOURCES Could not allocate resources.
  1190. **/
  1191. EFI_STATUS
  1192. AcpiVtdTablesInstall (
  1193. VOID
  1194. )
  1195. {
  1196. EFI_STATUS Status;
  1197. EFI_ACPI_TABLE_VERSION TableVersion;
  1198. DMA_REMAP_PROTOCOL *DmaRemap;
  1199. UINTN TableHandle;
  1200. EFI_ACPI_COMMON_HEADER *CurrentTable;
  1201. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  1202. UINTN HandleCount;
  1203. EFI_HANDLE *HandleBuffer;
  1204. UINTN Index;
  1205. EFI_PCI_IO_PROTOCOL *PciIo;
  1206. PCI_TYPE01 PciConfigHeader;
  1207. UINTN Segment;
  1208. UINTN Bus;
  1209. UINTN Device;
  1210. UINTN Function;
  1211. UINT8 PciExpressOffset;
  1212. UINT32 AcsOffset;
  1213. UINT16 PciExpressCapabilityReg;
  1214. UINT8 AcsCapCount;
  1215. UINT16 RequiredAcsCap;
  1216. UINT32 AcsCapRegValue;
  1217. UINT16 AcsConRegValue;
  1218. USRA_PCIE_ADDR_TYPE *AcsDevArray;
  1219. USRA_ADDRESS Address;
  1220. DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
  1221. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, (VOID **) &DynamicSiLibraryProtocol);
  1222. if (EFI_ERROR (Status)) {
  1223. ASSERT_EFI_ERROR (Status);
  1224. return EFI_NOT_FOUND;
  1225. }
  1226. PciExpressOffset = 0;
  1227. AcsOffset = 0;
  1228. AcsCapCount = 0;
  1229. AcsCapRegValue = 0;
  1230. AcsConRegValue = 0;
  1231. RequiredAcsCap = ACS_SOURCE_VALIDATION | ACS_P2P_REQUEST_REDIRECT | ACS_P2P_COMPLETION_REDIRECT | ACS_UPSTREAM_FORWARDING;
  1232. //
  1233. // Locate all PciIo protocols
  1234. //
  1235. Status = gBS->LocateHandleBuffer (
  1236. ByProtocol,
  1237. &gEfiPciIoProtocolGuid,
  1238. NULL,
  1239. &HandleCount,
  1240. &HandleBuffer
  1241. );
  1242. if (EFI_ERROR (Status)) {
  1243. DEBUG((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Cannot locate gEfiPciIoProtocolGuid (%r)\n", Status));
  1244. ASSERT (FALSE);
  1245. return Status;
  1246. }
  1247. AcsDevArray = AllocateZeroPool (sizeof (USRA_PCIE_ADDR_TYPE) * HandleCount);
  1248. if (AcsDevArray == NULL) {
  1249. ASSERT (AcsDevArray != NULL);
  1250. return EFI_OUT_OF_RESOURCES;
  1251. }
  1252. for (Index = 0; Index < HandleCount; Index ++) {
  1253. gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
  1254. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof(PciConfigHeader) / sizeof(UINT32), &PciConfigHeader);
  1255. if ((PciConfigHeader.Hdr.ClassCode[0] == 0x00 || PciConfigHeader.Hdr.ClassCode[0] == 0x01) && PciConfigHeader.Hdr.ClassCode[1] == 0x04 && PciConfigHeader.Hdr.ClassCode[2] == 0x06) {
  1256. //
  1257. // 060400h or 060401h indicates it's PCI-PCI bridge, get its bus number, device number and function number
  1258. //
  1259. PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
  1260. USRA_PCIE_SEG_ADDRESS(Address, UsraWidth16, Segment, Bus, Device, Function, 0);
  1261. if (PciConfigHeader.Hdr.Status == EFI_PCI_STATUS_CAPABILITY) {
  1262. //
  1263. // the bridge support Capability list and offset 0x34 is the pointer to the data structure
  1264. //
  1265. // Detect if PCI Express Device
  1266. //
  1267. Status = LocateCapRegBlock (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &PciExpressOffset, NULL);
  1268. if (Status == EFI_SUCCESS) {
  1269. //
  1270. // this bridge device is a PCI Express bridge
  1271. // Check if it is downstream port of PCIE switch
  1272. //
  1273. Address.Pcie.Offset = PciExpressOffset + EFI_PCI_EXPRESS_CAPABILITY_REGISTER;
  1274. DynamicSiLibraryProtocol->RegisterRead(&Address, &PciExpressCapabilityReg);
  1275. //
  1276. // BIT 7:4 indicate Device/port type, 0110b indicates downstream port of PCI express switch
  1277. //
  1278. if ((PciExpressCapabilityReg & 0x00F0) == 0x60) {
  1279. //
  1280. // it is downstream port of PCI Express switch
  1281. // Look for ACS capability register in PCI express configuration space
  1282. //
  1283. Status = LocatePciExpressCapRegBlock (PciIo, EFI_PCIE_CAPABILITY_ID_ACS, &AcsOffset, NULL);
  1284. DEBUG((DEBUG_ERROR, "ACS capable port is B%x.D%x.F%x - ACS Cap offset - 0x%x\n", Bus, Device, Function, AcsOffset));
  1285. if (Status == EFI_SUCCESS) {
  1286. //
  1287. // Read ACS capability register
  1288. //
  1289. Address.Pcie.Offset = AcsOffset + ACS_CAPABILITY_REGISTER;
  1290. Address.Attribute.AccessWidth = UsraWidth32;
  1291. DynamicSiLibraryProtocol->RegisterRead(&Address, &AcsCapRegValue);
  1292. DEBUG((DEBUG_INFO, "Bus =%x, Device=%x, Function=%x, AcsCapRegValue = %x \n", Bus, Device, Function, AcsCapRegValue));
  1293. if ((AcsCapRegValue & RequiredAcsCap) == RequiredAcsCap) {
  1294. //
  1295. // The PCI express downstream port support ACS, record this port
  1296. //
  1297. AcsDevArray[AcsCapCount].Bus = (UINT32)Bus;
  1298. AcsDevArray[AcsCapCount].Dev = (UINT32)Device;
  1299. AcsDevArray[AcsCapCount].Func = (UINT32)Function;
  1300. AcsDevArray[AcsCapCount].Offset = AcsOffset;
  1301. AcsDevArray[AcsCapCount].Seg = (UINT32)Segment;
  1302. AcsCapCount++;
  1303. }
  1304. }
  1305. }
  1306. }
  1307. }
  1308. }
  1309. } /// End for
  1310. //
  1311. // Free the Handle buffer
  1312. //
  1313. if (HandleBuffer != NULL) {
  1314. gBS->FreePool (HandleBuffer);
  1315. }
  1316. ASSERT (AcsCapCount <= HandleCount);
  1317. //
  1318. // all PCI express switch downstream ports support ACS and meet the required ACS capabilities
  1319. // for each downstream ports, enable the required Capabilities in ACS control register
  1320. //
  1321. Address.Attribute.AccessWidth = UsraWidth16;
  1322. for (Index = 0; Index < AcsCapCount; Index ++) {
  1323. //
  1324. // Program the corresponding bits in ACS control register
  1325. //
  1326. Address.Pcie = AcsDevArray[Index];
  1327. Address.Pcie.Offset += ACS_CONTROL_REGISTER;
  1328. DynamicSiLibraryProtocol->RegisterRead (&Address, &AcsConRegValue);
  1329. DEBUG ((DEBUG_ERROR, "AcsConRegValue is 0x%x\n", AcsConRegValue));
  1330. AcsConRegValue |= (ACS_SOURCE_VALIDATION_ENABLE | ACS_P2P_REQUEST_REDIRECT_ENABLE | ACS_P2P_COMPLETION_REDIRECT_ENABLE | ACS_UPSTREAM_FORWARDING_ENABLE);
  1331. DEBUG ((DEBUG_ERROR, "After Enable BITs AcsConRegValue is 0x%x\n", AcsConRegValue));
  1332. DynamicSiLibraryProtocol->RegisterWrite (&Address, &AcsConRegValue);
  1333. //
  1334. // report VT-d and other features to OS/VMM, report DMAR and remapping engine to OS/VMM
  1335. //
  1336. }
  1337. //
  1338. // Find the AcpiSupport protocol
  1339. //
  1340. Status = LocateSupportProtocol (&gEfiAcpiTableProtocolGuid, gEfiAcpiTableStorageGuid, (VOID **) &AcpiTable, FALSE);
  1341. ASSERT_EFI_ERROR (Status);
  1342. TableVersion = EFI_ACPI_TABLE_VERSION_2_0;
  1343. Status = gBS->LocateProtocol (&gDmaRemapProtocolGuid, NULL, (VOID **) &DmaRemap);
  1344. if (EFI_ERROR (Status)) {
  1345. DEBUG ((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Cannot locate gDmaRemapProtocolGuid (%r)\n", Status));
  1346. } else {
  1347. if (DmaRemap->VTdSupport) {
  1348. ReportDmar (DmaRemap);
  1349. Status = DmaRemap->GetDmarTable (DmaRemap, (VOID **) &CurrentTable);
  1350. if (EFI_ERROR (Status)) {
  1351. ASSERT_EFI_ERROR (Status);
  1352. } else {
  1353. //
  1354. // Perform any table specific updates.
  1355. //
  1356. Status = PlatformUpdateTables (CurrentTable, &TableVersion);
  1357. ASSERT_EFI_ERROR (Status);
  1358. TableHandle = 0;
  1359. Status = AcpiTable->InstallAcpiTable (
  1360. AcpiTable,
  1361. CurrentTable,
  1362. CurrentTable->Length,
  1363. &TableHandle
  1364. );
  1365. ASSERT_EFI_ERROR (Status);
  1366. }
  1367. }
  1368. }
  1369. FreePool (AcsDevArray);
  1370. return EFI_SUCCESS;
  1371. }
  1372. EFI_STATUS
  1373. LocateCapRegBlock (
  1374. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1375. IN UINT8 CapID,
  1376. OUT UINT8 *PciExpressOffset,
  1377. OUT UINT8 *NextRegBlock
  1378. )
  1379. {
  1380. UINT16 CapabilityID;
  1381. UINT32 Temp;
  1382. UINT8 CapabilityPtr;
  1383. UINT16 CapabilityEntry;
  1384. PciIo->Pci.Read (
  1385. PciIo,
  1386. EfiPciIoWidthUint32,
  1387. PCI_CAPBILITY_POINTER_OFFSET,
  1388. 1,
  1389. &Temp
  1390. );
  1391. CapabilityPtr = (UINT8)Temp;
  1392. //
  1393. // According to the PCI spec a value of 0x00
  1394. // is the end of the list
  1395. //
  1396. while (CapabilityPtr >= 0x40) {
  1397. //
  1398. // Mask it to DWORD alignment per PCI spec
  1399. //
  1400. CapabilityPtr &= 0xFC;
  1401. PciIo->Pci.Read (
  1402. PciIo,
  1403. EfiPciIoWidthUint16,
  1404. CapabilityPtr,
  1405. 1,
  1406. &CapabilityEntry
  1407. );
  1408. CapabilityID = (UINT8) CapabilityEntry;
  1409. if (CapabilityID == CapID) {
  1410. *PciExpressOffset = CapabilityPtr;
  1411. if (NextRegBlock != NULL) {
  1412. *NextRegBlock = (UINT8) ((CapabilityEntry >> 8) & 0xFC);
  1413. }
  1414. return EFI_SUCCESS;
  1415. }
  1416. CapabilityPtr = (UINT8) ((CapabilityEntry >> 8) & 0xFC);
  1417. }
  1418. return EFI_NOT_FOUND;
  1419. }
  1420. EFI_STATUS
  1421. LocatePciExpressCapRegBlock (
  1422. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1423. IN UINT16 CapID,
  1424. OUT UINT32 *Offset,
  1425. OUT UINT32 *NextRegBlock
  1426. )
  1427. {
  1428. UINT32 CapabilityPtr;
  1429. UINT32 CapabilityEntry;
  1430. UINT16 CapabilityID;
  1431. CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
  1432. while ((CapabilityPtr != 0) && (CapabilityPtr < 0x1000)) {
  1433. //
  1434. // Mask it to DWORD alignment per PCI spec
  1435. //
  1436. CapabilityPtr &= 0xFFC;
  1437. PciIo->Pci.Read (
  1438. PciIo,
  1439. EfiPciIoWidthUint32,
  1440. CapabilityPtr,
  1441. 1,
  1442. &CapabilityEntry
  1443. );
  1444. CapabilityID = (UINT16) CapabilityEntry;
  1445. if (CapabilityID == CapID) {
  1446. *Offset = CapabilityPtr;
  1447. if (NextRegBlock != NULL) {
  1448. *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;
  1449. }
  1450. return EFI_SUCCESS;
  1451. }
  1452. CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
  1453. }
  1454. return EFI_NOT_FOUND;
  1455. }
  1456. VOID
  1457. DisableAriForwarding (
  1458. VOID
  1459. )
  1460. {
  1461. EFI_STATUS Status;
  1462. UINTN HandleCount;
  1463. EFI_HANDLE *HandleBuffer;
  1464. UINTN Index;
  1465. EFI_PCI_IO_PROTOCOL *PciIo;
  1466. PCI_TYPE01 PciConfigHeader;
  1467. UINTN Segment;
  1468. UINTN Bus;
  1469. UINTN Device;
  1470. UINTN Function;
  1471. UINT8 PciExpressOffset;
  1472. PCI_REG_PCIE_DEVICE_CONTROL2 DevCtl2;
  1473. //
  1474. // Disable ARI forwarding before handoff to OS, as it may not be ARI-aware
  1475. //
  1476. //
  1477. // ARI forwarding exist in bridge
  1478. //
  1479. //
  1480. // Locate all PciIo protocol
  1481. //
  1482. Status = gBS->LocateHandleBuffer (
  1483. ByProtocol,
  1484. &gEfiPciIoProtocolGuid,
  1485. NULL,
  1486. &HandleCount,
  1487. &HandleBuffer
  1488. );
  1489. for (Index = 0; Index < HandleCount; Index ++) {
  1490. gBS->HandleProtocol (
  1491. HandleBuffer[Index],
  1492. &gEfiPciIoProtocolGuid,
  1493. (VOID **) &PciIo
  1494. );
  1495. PciIo->Pci.Read (
  1496. PciIo,
  1497. EfiPciIoWidthUint32,
  1498. 0,
  1499. sizeof (PciConfigHeader) / sizeof (UINT32),
  1500. &PciConfigHeader
  1501. );
  1502. if ((PciConfigHeader.Hdr.ClassCode[0] == 0x00 || PciConfigHeader.Hdr.ClassCode[0] == 0x01) && PciConfigHeader.Hdr.ClassCode[1] == 0x04 && PciConfigHeader.Hdr.ClassCode[2] == 0x06) {
  1503. //
  1504. // 060400h or 060401h indicates it's PCI-PCI bridge, get its bus number, device number and function number
  1505. //
  1506. PciIo->GetLocation (
  1507. PciIo,
  1508. &Segment,
  1509. &Bus,
  1510. &Device,
  1511. &Function
  1512. );
  1513. if (PciConfigHeader.Hdr.Status == EFI_PCI_STATUS_CAPABILITY) {
  1514. //
  1515. // the bridge support Capability list and offset 0x34 is the pointer to the data structure
  1516. //
  1517. //
  1518. // Detect if PCI Express Device
  1519. //
  1520. Status = LocateCapRegBlock (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &PciExpressOffset, NULL);
  1521. if (Status == EFI_SUCCESS) {
  1522. //
  1523. // this bridge device is a PCI Express bridge, Check ARI forwarding bit in Device Control 2 register
  1524. //
  1525. PciIo->Pci.Read (
  1526. PciIo,
  1527. EfiPciIoWidthUint16,
  1528. PciExpressOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2),
  1529. 1,
  1530. &DevCtl2
  1531. );
  1532. if (DevCtl2.Bits.AriForwarding) {
  1533. //
  1534. // ARI forwarding enable bit is set, we need to clear this bit before handing off control to OS
  1535. // because OS may not ARI aware
  1536. //
  1537. DEBUG((DEBUG_INFO, "[VTD] %02X:%02X:%02X.%X: ARI forwarding disable before booting OS, DevCtl2 0x%02X -> 0x%02X\n",
  1538. Segment, Bus, Device, Function, DevCtl2.Uint16, DevCtl2.Uint16 & ~BIT5));
  1539. DevCtl2.Bits.AriForwarding = 0;
  1540. PciIo->Pci.Write (
  1541. PciIo,
  1542. EfiPciIoWidthUint16,
  1543. PciExpressOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2),
  1544. 1,
  1545. &DevCtl2
  1546. );
  1547. }
  1548. }
  1549. }
  1550. }
  1551. }
  1552. } // DisableAriForwarding()