Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

944 lines
26 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pmsapic.c
  5. Abstract:
  6. Implements various SAPIC-ACPI functions.
  7. Author:
  8. Todd Kjos (Hewlett-Packard) 20-Apr-1998
  9. Based on I386 version of pmapic.c:
  10. Jake Oshins (jakeo) 19-May-1997
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "halp.h"
  16. #include "acpitabl.h"
  17. #include "iosapic.h"
  18. #include "xxacpi.h"
  19. #include "ixsleep.h"
  20. PMAPIC HalpApicTable;
  21. struct _IOAPIC_DEBUG_TABLE
  22. {
  23. PIO_INTR_CONTROL IoIntrControl;
  24. PIO_SAPIC_REGS IoSapicRegs;
  25. } *HalpApicDebugAddresses;
  26. ULONG
  27. DetectAcpiMP(
  28. OUT PBOOLEAN IsConfiguredMp,
  29. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  30. );
  31. VOID
  32. HalpInitMPInfo(
  33. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  34. IN PMAPIC ApicTable
  35. );
  36. BOOLEAN
  37. HalpVerifyIoSapic(
  38. IN PUCHAR BaseAddress
  39. );
  40. VOID
  41. HalpSaveInterruptControllerState(
  42. VOID
  43. );
  44. VOID
  45. HalpRestoreInterruptControllerState(
  46. VOID
  47. );
  48. VOID
  49. HalpSetInterruptControllerWakeupState(
  50. ULONG Context
  51. );
  52. VOID
  53. HalpSetCPEVectorState(
  54. IN ULONG GlobalInterrupt,
  55. IN UCHAR SapicVector,
  56. IN USHORT DestinationCPU,
  57. IN ULONG Flags
  58. );
  59. VOID
  60. HalpProcessLocalSapic(
  61. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  62. IN PPROCLOCALSAPIC ProcLocalSapic
  63. );
  64. VOID
  65. HalpProcessIoSapic(
  66. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  67. IN PIOSAPIC IoSapic
  68. );
  69. VOID
  70. HalpProcessIsaVector(
  71. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  72. IN PISA_VECTOR IsaVector
  73. );
  74. VOID
  75. HalpProcessPlatformInt(
  76. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  77. IN PPLATFORM_INTERRUPT PlatformInt
  78. );
  79. extern UCHAR rgzNoApicTable[];
  80. extern UCHAR rgzNoApic[];
  81. extern UCHAR rgzApicNotVerified[];
  82. extern ULONG HalpPicVectorRedirect[];
  83. struct _MPINFO HalpMpInfo;
  84. extern ULONG HalpPicVectorFlags[];
  85. extern ULONG HalpIpiClock;
  86. extern BOOLEAN HalpHiberInProgress;
  87. // from pmdata.c: CPE related.
  88. extern ULONG HalpCPEIntIn[];
  89. extern USHORT HalpCPEDestination[];
  90. extern ULONG HalpCPEVectorFlags[];
  91. extern UCHAR HalpCPEIoSapicVector[];
  92. extern ULONG HalpMaxCPEImplemented;
  93. BOOLEAN HalpPicStateIntact = TRUE;
  94. PIO_INTR_CONTROL HalpIoSapicList = NULL;
  95. #ifdef ALLOC_PRAGMA
  96. #pragma alloc_text(INIT, DetectAcpiMP)
  97. #pragma alloc_text(INIT, HalpInitMPInfo)
  98. #pragma alloc_text(INIT, HalpProcessLocalSapic)
  99. #pragma alloc_text(INIT, HalpProcessIoSapic)
  100. #pragma alloc_text(INIT, HalpProcessIsaVector)
  101. #pragma alloc_text(INIT, HalpProcessPlatformInt)
  102. #pragma alloc_text(PAGELK, HalpVerifyIoSapic)
  103. #pragma alloc_text(PAGELK, HalpSaveInterruptControllerState)
  104. #pragma alloc_text(PAGELK, HalpRestoreInterruptControllerState)
  105. #pragma alloc_text(PAGELK, HalpSetInterruptControllerWakeupState)
  106. #pragma alloc_text(PAGELK, HalpAcpiPicStateIntact)
  107. #endif
  108. ULONG
  109. DetectAcpiMP(
  110. OUT PBOOLEAN IsConfiguredMp,
  111. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  112. )
  113. {
  114. UCHAR ApicVersion, index, processorNumber;
  115. PUCHAR LocalApic;
  116. NTSTATUS status;
  117. //
  118. // Make sure there is an SAPIC Table
  119. //
  120. HalpApicTable = HalpGetAcpiTablePhase0(LoaderBlock, APIC_SIGNATURE);
  121. if (HalpApicTable == NULL) {
  122. HalDisplayString(rgzNoApicTable);
  123. KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 10, 0, 0);
  124. return(FALSE);
  125. }
  126. HalDebugPrint(( HAL_INFO, "HAL: Found a MADT table at %p\n", HalpApicTable ));
  127. HalDebugPrint(( HAL_INFO, "HAL: Signature: %x Length: %x\n",
  128. HalpApicTable->Header.Signature,
  129. HalpApicTable->Header.Length ));
  130. HalDebugPrint(( HAL_INFO, "HAL: OEMID: %s\n", HalpApicTable->Header.OEMID ));
  131. // We have a SAPIC table. Initialize the interrupt info structure
  132. HalpInitMPInfo(LoaderBlock, HalpApicTable);
  133. if (HalpMpInfo.IoSapicCount == 0) {
  134. //
  135. // There are no IO Sapics.
  136. //
  137. // Should we allow this case on the theory that
  138. // that all the interrupts are connected to LINTx pins on the CPU?
  139. //
  140. HalDebugPrint(( HAL_ERROR, rgzNoApic ));
  141. return (FALSE);
  142. }
  143. if (HalpMpInfo.ProcessorCount == 0) {
  144. KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 11, 0, 0);
  145. }
  146. //
  147. // Initialize NtProcessorNumber in the order that we are going to process
  148. // them in HalStartNextProcessor. The BSP is 0 and the rest are numbered
  149. // in the order the Local SAPICs appear in the MADT starting at 1.
  150. //
  151. processorNumber = 1;
  152. for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
  153. if (HalpProcessorInfo[index].LocalApicID == (USHORT)PCR->HalReserved[PROCESSOR_ID_INDEX]) {
  154. HalpProcessorInfo[index].NtProcessorNumber = 0;
  155. } else {
  156. HalpProcessorInfo[index].NtProcessorNumber = processorNumber++;
  157. }
  158. }
  159. *IsConfiguredMp = (HalpMpInfo.ProcessorCount > 1 ? TRUE : FALSE);
  160. return TRUE;
  161. }
  162. #define IO_SAPIC_REGS_SIZE 4096
  163. VOID
  164. HalpInitMPInfo(
  165. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  166. IN PMAPIC ApicTable
  167. )
  168. /*++
  169. Routine Description:
  170. This routine initializes a HAL specific data structure that is
  171. used by the HAL to simplify access to MP information.
  172. Arguments:
  173. SapicTable Pointer to the SAPIC table.
  174. Return Value:
  175. None
  176. */
  177. {
  178. PAPICTABLE TablePtr;
  179. ULONG i;
  180. HalpMpInfo.ProcessorCount = 0;
  181. HalpMpInfo.IoSapicCount = 0;
  182. // Walk the Multiple Apic table...
  183. TablePtr = (PAPICTABLE) ApicTable->APICTables;
  184. // Loop ends when TraversePtr is off the end of the table...
  185. while ((UINT_PTR)TablePtr <
  186. ((UINT_PTR)ApicTable + ApicTable->Header.Length)) {
  187. if (TablePtr->Type == LOCAL_SAPIC) {
  188. HalpProcessLocalSapic(LoaderBlock, (PPROCLOCALSAPIC)TablePtr);
  189. } else if (TablePtr->Type == IO_SAPIC) {
  190. HalpProcessIoSapic(LoaderBlock, (PIOSAPIC)TablePtr);
  191. } else if (TablePtr->Type == ISA_VECTOR_OVERRIDE) {
  192. HalpProcessIsaVector(LoaderBlock, (PISA_VECTOR)TablePtr);
  193. } else if (TablePtr->Type == PLATFORM_INTERRUPT_SOURCE) {
  194. HalpProcessPlatformInt(LoaderBlock, (PPLATFORM_INTERRUPT)TablePtr);
  195. } else {
  196. HalDebugPrint(( HAL_ERROR, "HAL: Processing MADT - Skip Table %p: Type = %d, Length = %d\n", TablePtr, TablePtr->Type, TablePtr->Length ));
  197. }
  198. (UINT_PTR)TablePtr += TablePtr->Length;
  199. }
  200. //
  201. // Check if there is Interrupt Source Override entry. If there is, force the
  202. // new flags into the SAPIC state. This is done now because of the possibility
  203. // the firmware can place the ISO Vector Override entry ahead of IOSAPIC entry.
  204. //
  205. for (i = 0; i < PIC_VECTORS; i++) {
  206. if (HalpPicVectorFlags[i]) {
  207. HaliSetVectorState( HalpPicVectorRedirect[i],
  208. HalpPicVectorFlags[i]
  209. );
  210. }
  211. }
  212. }
  213. VOID
  214. HalpProcessLocalSapic(
  215. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  216. IN PPROCLOCALSAPIC ProcLocalSapic
  217. )
  218. {
  219. USHORT LID;
  220. ULONG ProcessorNum;
  221. if (ProcLocalSapic->Length != PROCESSOR_LOCAL_SAPIC_LENGTH) {
  222. HalDebugPrint(( HAL_ERROR,
  223. "HAL: HalpProcessLocalSapic - Invalid Length %p: Expected %d, Found %d\n",
  224. ProcLocalSapic,
  225. PROCESSOR_LOCAL_SAPIC_LENGTH,
  226. ProcLocalSapic->Length ));
  227. return;
  228. }
  229. // Make sure processor is enabled...
  230. if (!(ProcLocalSapic->Flags & PLAF_ENABLED)) {
  231. return;
  232. }
  233. // It is. Bump the count and store the LID value for IPIs
  234. LID = (ProcLocalSapic->APICID << 8) | ProcLocalSapic->APICEID;
  235. HalpProcessorInfo[HalpMpInfo.ProcessorCount].AcpiProcessorID = ProcLocalSapic->ACPIProcessorID;
  236. HalpProcessorInfo[HalpMpInfo.ProcessorCount].LocalApicID = LID;
  237. HalpMpInfo.ProcessorCount++;
  238. HalDebugPrint(( HAL_INFO,
  239. "HAL: Found a processor-local SAPIC: %p LID=%x\n",
  240. ProcLocalSapic,
  241. LID ));
  242. }
  243. VOID
  244. HalpProcessIoSapic(
  245. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  246. IN PIOSAPIC IoSapic
  247. )
  248. {
  249. ULONG IntiBase,RedirEntries;
  250. PHYSICAL_ADDRESS IoSapicPhys;
  251. PVOID IoSapicBase;
  252. UINT_PTR IoSapicPhysBase;
  253. PIO_SAPIC_REGS SapicRegs;
  254. PIO_INTR_CONTROL IoIntrControl;
  255. ULONG i;
  256. union {
  257. ULONG raw;
  258. SAPIC_VERSION version;
  259. } versionUnion;
  260. if (IoSapic->Length != IO_SAPIC_LENGTH) {
  261. HalDebugPrint(( HAL_ERROR,
  262. "HAL: HalpProcessIoSapic - Invalid Length %p: Expected %d, Found %d\n",
  263. IoSapic,
  264. IO_SAPIC_LENGTH,
  265. IoSapic->Length ));
  266. return;
  267. }
  268. HalDebugPrint(( HAL_INFO, "HAL: Found an IO SAPIC: %p\n", IoSapic ));
  269. // Map IO Sapic Registers...
  270. IntiBase = IoSapic->SystemVectorBase;
  271. IoSapicPhysBase = IoSapic->IOSAPICAddress;
  272. IoSapicPhys.QuadPart = (UINT_PTR)IoSapicPhysBase;
  273. IoSapicBase = HalpMapPhysicalMemory( IoSapicPhys,
  274. ADDRESS_AND_SIZE_TO_SPAN_PAGES(IoSapicPhys.LowPart, IO_SAPIC_REGS_SIZE),
  275. MmNonCached);
  276. ASSERT(IoSapicBase);
  277. SapicRegs = (PIO_SAPIC_REGS)IoSapicBase;
  278. if (!SapicRegs) {
  279. HalDebugPrint(( HAL_ERROR, "HAL: Couldn't map the I/O Sapic\n" ));
  280. return;
  281. }
  282. // Read the IO Sapic version and extract the number of redirection table entries
  283. SapicRegs->RegisterSelect = IO_VERS_REGISTER;
  284. SapicRegs->RegisterWindow = 0;
  285. versionUnion.raw = SapicRegs->RegisterWindow;
  286. //
  287. // CPQMOD_JL001 - Incorrect count - hw provide max rte index not
  288. // count.
  289. //
  290. //RedirEntries = versionUnion.version.MaxRedirEntries;
  291. RedirEntries = versionUnion.version.MaxRedirEntries + 1;
  292. if (HalpVerifyIoSapic((PUCHAR)SapicRegs)) {
  293. // Allocate and fill out a IO Sapic structure
  294. PHYSICAL_ADDRESS physicalAddress;
  295. physicalAddress.QuadPart = (LONGLONG)HalpAllocPhysicalMemory(
  296. LoaderBlock,
  297. ~0,
  298. BYTES_TO_PAGES(sizeof(IO_INTR_CONTROL) + (RedirEntries*sizeof(IOSAPICINTI))),
  299. FALSE );
  300. if (physicalAddress.QuadPart == 0) {
  301. HalDebugPrint(( HAL_ERROR, "HAL: Couldn't allocate memory for the IO Sapic structures\n" ));
  302. return;
  303. }
  304. IoIntrControl = (PIO_INTR_CONTROL)HalpMapPhysicalMemory(
  305. physicalAddress,
  306. ADDRESS_AND_SIZE_TO_SPAN_PAGES(physicalAddress.LowPart, sizeof(IO_INTR_CONTROL) + (RedirEntries*sizeof(IOSAPICINTI))),
  307. MmCached );
  308. ASSERT(IoIntrControl);
  309. IoIntrControl->IntiBase = IntiBase;
  310. IoIntrControl->IntiMax = IntiBase + RedirEntries - 1;
  311. IoIntrControl->RegBaseVirtual = IoSapicBase;
  312. IoIntrControl->RegBasePhysical = IoSapicPhys;
  313. IoIntrControl->IntrMethods = &HalpIoSapicMethods;
  314. IoIntrControl->InterruptAffinity = ~0;
  315. IoIntrControl->flink = NULL;
  316. //
  317. // Mark all vectors as Free
  318. //
  319. RtlFillMemory(IoIntrControl->FreeVectors, sizeof(IoIntrControl->FreeVectors), 0xFF);
  320. for (i = 0; i < RedirEntries; i++) {
  321. IoIntrControl->Inti[i].Vector =
  322. DELIVER_FIXED | ACTIVE_LOW | LEVEL_TRIGGERED;
  323. IoIntrControl->Inti[i].Destination = 0;
  324. IoIntrControl->Inti[i].GlobalVector = 0;
  325. //
  326. // CPQMOD_JL002 - Fix for using the rte and not the
  327. // SystemVector.
  328. //
  329. //IoIntrControl->IntrMethods->MaskEntry(IoIntrControl,IntiBase+i);
  330. IoIntrControl->IntrMethods->MaskEntry(IoIntrControl,i);
  331. }
  332. // Insert structure into list. Since we are running on P0 at
  333. // Phase0 initialization, we can assume that no one else is
  334. // modifying this list therefore no synchronization is needed.
  335. if (HalpIoSapicList == NULL) {
  336. HalpIoSapicList = IoIntrControl;
  337. } else {
  338. PIO_INTR_CONTROL *LastLink;
  339. PIO_INTR_CONTROL IoSapicListEntry;
  340. LastLink = &HalpIoSapicList;
  341. IoSapicListEntry = HalpIoSapicList;
  342. while (IoSapicListEntry != NULL) {
  343. if (IoSapicListEntry->IntiBase > IoIntrControl->IntiMax) {
  344. // Insert new entry before current entry
  345. IoIntrControl->flink = *LastLink;
  346. *LastLink = IoIntrControl;
  347. break;
  348. } else {
  349. LastLink = &IoSapicListEntry->flink;
  350. IoSapicListEntry = IoSapicListEntry->flink;
  351. }
  352. }
  353. if (IoSapicListEntry == NULL) {
  354. // We got to the end of the list. The new entry goes
  355. // after the last entry...
  356. *LastLink = IoIntrControl;
  357. }
  358. }
  359. HalpMpInfo.IoSapicCount++;
  360. } else {
  361. // The Io Sapic is not there, ignore this entry in the table
  362. HalDebugPrint(( HAL_ERROR, rgzApicNotVerified ));
  363. HalpUnmapVirtualAddress(IoSapicBase, ADDRESS_AND_SIZE_TO_SPAN_PAGES(IoSapicBase, IO_SAPIC_REGS_SIZE));
  364. }
  365. }
  366. VOID
  367. HalpProcessIsaVector(
  368. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  369. IN PISA_VECTOR IsaVector
  370. )
  371. {
  372. if (IsaVector->Length != ISA_VECTOR_OVERRIDE_LENGTH) {
  373. HalDebugPrint(( HAL_ERROR,
  374. "HAL: HalpProcessIsaVector - Invalid Length %p: Expected %d, Found %d\n",
  375. IsaVector,
  376. ISA_VECTOR_OVERRIDE_LENGTH,
  377. IsaVector->Length ));
  378. return;
  379. }
  380. //
  381. // Found an ISA vector redirection entry.
  382. //
  383. HalpPicVectorRedirect[IsaVector->Source] =
  384. IsaVector->GlobalSystemInterruptVector;
  385. HalpPicVectorFlags[IsaVector->Source] = IsaVector->Flags;
  386. HalDebugPrint(( HAL_INFO, "HAL: Found an ISA VECTOR: %p, %x -> %x, flags: %x\n",
  387. IsaVector,
  388. IsaVector->Source,
  389. IsaVector->GlobalSystemInterruptVector,
  390. IsaVector->Flags ));
  391. }
  392. VOID
  393. HalpProcessPlatformInt(
  394. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  395. IN PPLATFORM_INTERRUPT PlatformInt
  396. )
  397. {
  398. if (PlatformInt->Length != PLATFORM_INTERRUPT_SOURCE_LENGTH) {
  399. HalDebugPrint(( HAL_ERROR,
  400. "HAL: HalpProcessPlatformInt - Invalid Length %p: Expected %d, Found %d\n",
  401. PlatformInt,
  402. PLATFORM_INTERRUPT_SOURCE_LENGTH,
  403. PlatformInt->Length ));
  404. return;
  405. }
  406. //
  407. // Process a Corrected Platform Error Interrupt Source structure.
  408. //
  409. if (PlatformInt->InterruptType == PLATFORM_INT_CPE) {
  410. //
  411. // Does this platform have more (than what we expected) number of CPE sources?
  412. //
  413. if ( HalpMaxCPEImplemented >= HALP_CPE_MAX_INTERRUPT_SOURCES ) {
  414. HalDebugPrint(( HAL_ERROR,
  415. "HAL: Platform Interrupt Source %p skipped due to overflow: %ld >= HALP_CPE_MAX_INTERRUPT_SOURCES\n", PlatformInt, HalpMaxCPEImplemented ));
  416. return;
  417. }
  418. //
  419. // Save the input pin number of SAPIC for this CPE source
  420. //
  421. HalpCPEIntIn[HalpMaxCPEImplemented] = (ULONG)PlatformInt->GlobalVector;
  422. //
  423. // Save the Flags for this CPE source
  424. //
  425. HalpCPEVectorFlags[HalpMaxCPEImplemented] = (ULONG)PlatformInt->Flags;
  426. //
  427. // Save the IO Sapic Vector (that BIOS expects OS to use) for this platform CMC source
  428. //
  429. HalpCPEIoSapicVector[HalpMaxCPEImplemented] = (UCHAR)PlatformInt->IOSAPICVector;
  430. // Thierry - WARNING - 09/19/2000
  431. // NT HAL ignores the IO SAPIC vector field for the platform interrupt sources.
  432. // NT imposes the CPEI_VECTOR value for Corrected Machine Errors interrupt vector, for all
  433. // the destination processors. Actually, the current default is to attach all the processors
  434. // IDT[CPEI_VECTOR] with the HAL default ISR - HalpCPEIHandler for the CPE interrupt model.
  435. // We will connect the ISR only for the destination processors after testing if judged valid.
  436. // The rationales are:
  437. // - IOSAPICVector was mostly added in the specs by Intel for IA64 PMI interrupt sources.
  438. // These PMI interrupts are not visible by NT.
  439. // - NT has no infrastructure at this time to support vector registration for FW/chipset
  440. // generated external interrupts visible to NT.
  441. // - Having the FW specifying the vector requires the HAL to control the specified
  442. // value with its current IDT[] related resources usage and defines actions in case
  443. // of conficts.
  444. //
  445. HalDebugPrint(( HAL_INFO, "HAL: CPE source VECTOR: %x. HAL imposes VECTOR: %x\n",
  446. HalpCPEIoSapicVector[HalpMaxCPEImplemented],
  447. CPEI_VECTOR ));
  448. HalpCPEIoSapicVector[HalpMaxCPEImplemented] = (UCHAR)(CPEI_VECTOR);
  449. //
  450. // Save the Destination Processor (that BIOS expects OS to use) for this CPE source)
  451. //
  452. HalpCPEDestination[HalpMaxCPEImplemented] = (USHORT)(
  453. (PlatformInt->APICID << 8) | PlatformInt->ACPIEID);
  454. HalDebugPrint(( HAL_INFO, "HAL: Found an Platform Interrupt VECTOR: %p, %x -> %x, flags: %x\n",
  455. PlatformInt,
  456. PlatformInt->IOSAPICVector,
  457. PlatformInt->GlobalVector,
  458. PlatformInt->Flags ));
  459. //
  460. // Keep track of how many CPE sources are implemented in the platform.
  461. //
  462. HalpMaxCPEImplemented++;
  463. }
  464. }
  465. VOID
  466. HalpInitPlatformInterrupts(
  467. VOID
  468. )
  469. {
  470. ULONG currentCPE;
  471. USHORT processorApicID;
  472. PAPICTABLE tablePtr;
  473. processorApicID = (USHORT)KeGetPcr()->HalReserved[PROCESSOR_ID_INDEX];
  474. for (currentCPE = 0; currentCPE < HalpMaxCPEImplemented; currentCPE++) {
  475. if (HalpCPEDestination[currentCPE] == processorApicID)
  476. {
  477. //
  478. // Force the flags into the SAPIC state
  479. //
  480. HalpSetCPEVectorState( HalpCPEIntIn[currentCPE],
  481. HalpCPEIoSapicVector[currentCPE],
  482. HalpCPEDestination[currentCPE],
  483. HalpCPEVectorFlags[currentCPE]
  484. );
  485. }
  486. }
  487. // Walk the Multiple Apic table...
  488. tablePtr = (PAPICTABLE) HalpApicTable->APICTables;
  489. // Loop ends when TraversePtr is off the end of the table...
  490. while ((UINT_PTR)tablePtr <
  491. ((UINT_PTR)HalpApicTable + HalpApicTable->Header.Length)) {
  492. if (tablePtr->Type == PLATFORM_INTERRUPT_SOURCE) {
  493. PPLATFORM_INTERRUPT platformInt = (PPLATFORM_INTERRUPT)tablePtr;
  494. if ((platformInt->InterruptType == PLATFORM_INT_PMI ||
  495. platformInt->InterruptType == PLATFORM_INT_INIT) &&
  496. (processorApicID == (USHORT)((platformInt->APICID << 8) | platformInt->ACPIEID))) {
  497. HalpWriteRedirEntry( platformInt->GlobalVector,
  498. platformInt->IOSAPICVector,
  499. processorApicID,
  500. platformInt->Flags,
  501. platformInt->InterruptType
  502. );
  503. }
  504. }
  505. (UINT_PTR)tablePtr += tablePtr->Length;
  506. }
  507. }
  508. BOOLEAN
  509. HalpVerifyIoSapic(
  510. IN PUCHAR BaseAddress
  511. )
  512. /*++
  513. Routine Description:
  514. Verify that an IO Sapic Unit exists at the specified address
  515. Arguments:
  516. BaseAddress - Virtual address of the IO Unit to test.
  517. Return Value:
  518. BOOLEAN - TRUE if a IO Unit was found at the passed address
  519. - FALSE otherwise
  520. --*/
  521. {
  522. union SapicUnion {
  523. ULONG Raw;
  524. struct SapicVersion Ver;
  525. } Temp1, Temp2;
  526. PIO_SAPIC_REGS IoUnitPtr = (PIO_SAPIC_REGS) BaseAddress;
  527. //
  528. // The documented detection mechanism is to write all zeros to
  529. // the Version register. Then read it back. The IO Unit exists if the
  530. // same result is read both times and the Version is valid.
  531. //
  532. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  533. IoUnitPtr->RegisterWindow = 0;
  534. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  535. Temp1.Raw = IoUnitPtr->RegisterWindow;
  536. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  537. IoUnitPtr->RegisterWindow = 0;
  538. IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
  539. Temp2.Raw = IoUnitPtr->RegisterWindow;
  540. if ( Temp1.Raw == 0 ||
  541. (Temp1.Ver.Version != Temp2.Ver.Version) ||
  542. (Temp1.Ver.MaxRedirEntries != Temp2.Ver.MaxRedirEntries)) {
  543. //
  544. // No IO Unit There
  545. //
  546. HalDebugPrint(( HAL_ERROR, "HAL: No IoSapic at %I64x\n", BaseAddress ));
  547. return (FALSE);
  548. }
  549. HalDebugPrint(( HAL_INFO, "HAL: IoSapic found at %I64x, Max Entries = %d\n", BaseAddress, Temp1.Ver.MaxRedirEntries ));
  550. return (TRUE);
  551. }
  552. VOID
  553. HalpInitApicDebugMappings(
  554. VOID
  555. )
  556. /*++
  557. Routine Description:
  558. This routine is called at the very beginning of phase 1 initialization.
  559. It creates mappings for the APICs using MmMapIoSpace. This will allow
  560. us to access their registers from the debugger.
  561. A much better solution would be to allow us to describe our memory usage to
  562. MM but ....
  563. Arguments:
  564. Return Value:
  565. --*/
  566. {
  567. PHYSICAL_ADDRESS physicalAddress;
  568. PIO_INTR_CONTROL IoIntrControl;
  569. ULONG index;
  570. if (HalpMpInfo.IoSapicCount == 0) {
  571. //
  572. // I doubt this machine is going to get very far without IOAPICs
  573. // but there is certainly nothing for this routine to do.
  574. return;
  575. }
  576. ASSERT(HalpApicDebugAddresses == NULL);
  577. HalpApicDebugAddresses = ExAllocatePool(NonPagedPool,
  578. HalpMpInfo.IoSapicCount * sizeof(*HalpApicDebugAddresses));
  579. if (HalpApicDebugAddresses == NULL) {
  580. return;
  581. }
  582. IoIntrControl = HalpIoSapicList;
  583. for (index = 0; index < HalpMpInfo.IoSapicCount; index++) {
  584. if (IoIntrControl != NULL) {
  585. if (HalpVirtualToPhysical((ULONG_PTR)IoIntrControl, &physicalAddress)) {
  586. HalpApicDebugAddresses[index].IoIntrControl =
  587. MmMapIoSpace(physicalAddress,
  588. sizeof(IO_INTR_CONTROL) +
  589. (IoIntrControl->IntiMax - IoIntrControl->IntiBase + 1) * sizeof(IOSAPICINTI),
  590. MmCached
  591. );
  592. }
  593. HalpApicDebugAddresses[index].IoSapicRegs =
  594. MmMapIoSpace(IoIntrControl->RegBasePhysical,
  595. IO_SAPIC_REGS_SIZE,
  596. MmNonCached
  597. );
  598. IoIntrControl = IoIntrControl->flink;
  599. } else {
  600. HalpApicDebugAddresses[index].IoIntrControl = NULL;
  601. HalpApicDebugAddresses[index].IoSapicRegs = NULL;
  602. }
  603. }
  604. }
  605. VOID
  606. HalpSaveInterruptControllerState(
  607. VOID
  608. )
  609. {
  610. HalDebugPrint(( HAL_ERROR, "HAL: HalpSaveInterruptControllerState - not yet implemented\n"));
  611. HalpHiberInProgress = TRUE;
  612. }
  613. VOID
  614. HalpRestoreInterruptControllerState(
  615. VOID
  616. )
  617. {
  618. //
  619. // Restore the IO APIC state
  620. //
  621. HalDebugPrint(( HAL_ERROR, "HAL: HalpRestoreInterruptControllerState - not yet implemented\n"));
  622. HalpPicStateIntact = TRUE;
  623. }
  624. VOID
  625. HalpSetInterruptControllerWakeupState(
  626. ULONG Context
  627. )
  628. {
  629. HalDebugPrint(( HAL_FATAL_ERROR, "HAL: HalpSetInterruptControllerWakeupState - not yet implemented\n"));
  630. KeBugCheckEx(HAL_INITIALIZATION_FAILED, 0, 0, 0 , 0);
  631. }
  632. BOOLEAN
  633. HalpAcpiPicStateIntact(
  634. VOID
  635. )
  636. {
  637. return HalpPicStateIntact;
  638. }
  639. ULONG
  640. HalpAcpiNumProcessors(
  641. VOID
  642. )
  643. {
  644. return HalpMpInfo.ProcessorCount;
  645. }
  646. VOID
  647. HalpMaskAcpiInterrupt(
  648. VOID
  649. )
  650. {
  651. ULONG inti;
  652. KAFFINITY affinity;
  653. ULONG sciVector = HalpFixedAcpiDescTable.sci_int_vector;
  654. if (sciVector < PIC_VECTORS) {
  655. sciVector = HalpPicVectorRedirect[sciVector];
  656. }
  657. HalpGetSapicInterruptDesc(
  658. Internal,
  659. 0,
  660. sciVector,
  661. &inti,
  662. &affinity
  663. );
  664. HalpDisableRedirEntry(inti);
  665. }
  666. VOID
  667. HalpUnmaskAcpiInterrupt(
  668. VOID
  669. )
  670. {
  671. ULONG inti;
  672. KAFFINITY affinity;
  673. ULONG sciVector = HalpFixedAcpiDescTable.sci_int_vector;
  674. if (sciVector < PIC_VECTORS) {
  675. sciVector = HalpPicVectorRedirect[sciVector];
  676. }
  677. HalpGetSapicInterruptDesc(
  678. Internal,
  679. 0,
  680. sciVector,
  681. &inti,
  682. &affinity
  683. );
  684. HalpEnableRedirEntry(inti);
  685. }
  686. NTSTATUS
  687. HalpGetApicIdByProcessorNumber(
  688. IN UCHAR Processor,
  689. IN OUT USHORT *ApicId
  690. )
  691. /*++
  692. Routine Description:
  693. This function returns an APIC ID for a given processor.
  694. Arguments:
  695. Processor - The logical processor number that is
  696. associated with this APIC ID.
  697. ApicId - pointer to a value to fill in with the APIC ID.
  698. Return Value:
  699. Status.
  700. --*/
  701. {
  702. ULONG index;
  703. for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
  704. if (HalpProcessorInfo[index].NtProcessorNumber == Processor) {
  705. //
  706. // Return the APIC ID, Extended APIC ID for this
  707. // processor.
  708. //
  709. *ApicId = HalpProcessorInfo[index].LocalApicID;
  710. return STATUS_SUCCESS;
  711. }
  712. }
  713. return STATUS_NOT_FOUND;
  714. }