Source code of Windows XP (NT5)
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.

1484 lines
29 KiB

  1. /*++
  2. Copyright (c) 1995 Intel Corporation
  3. Module Name:
  4. i64krnl.c
  5. Abstract:
  6. This module implements the kernel support routines for the HAL DLL.
  7. Author:
  8. Bernard Lint
  9. M. Jayakumar (Muthurajan.Jayakumar@intel.com)
  10. 14-Apr-1995
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "halp.h"
  16. #include "i64fw.h"
  17. #include "check.h"
  18. #include "osmca.h"
  19. #include "iosapic.h"
  20. #include "string.h"
  21. #include "stdlib.h"
  22. #include "stdio.h"
  23. #define GreaterThan4GB 0x100000000
  24. VOID
  25. HalpInitReservedPages(
  26. VOID
  27. );
  28. VOID
  29. HalpRegisterKdSupportFunctions(
  30. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  31. );
  32. extern ADDRESS_USAGE HalpDefaultPcIoSpace;
  33. extern ULONGLONG HalpITCFrequency;
  34. extern ULONGLONG HalpProcessorFrequency;
  35. extern ULONG HalpOsBootRendezVector;
  36. WCHAR HalHardwareIdString[] = L"acpi";
  37. ULONG HalpBusType;
  38. ULONGLONG PhysicalIOBase;
  39. static short HalpOwnDisplay = TRUE;
  40. PKPROCESSOR_STATE HalpProcessorState;
  41. PULONGLONG InterruptBlock;
  42. extern KEVENT HalpNewAdapter;
  43. ULONG HalPxbTcap;
  44. //
  45. // When Accessing IO SAPIC, HalpIoSapicLock is acquired and released
  46. //
  47. KSPIN_LOCK HalpIoSapicLock;
  48. PHYSICAL_ADDRESS INTERRUPT_BLOCK_ADDRESS = { 0x0FEE00000 };
  49. //
  50. // Thierry - 10/01/2000 - Do NOT check the HALP_FIX_KD_HALIA64_MASK related
  51. // code and data in the tree.
  52. //
  53. // This is to allow us to enable HAL_INFO level or other desired mask.
  54. // The current debugger does not allow this and it should.
  55. //
  56. // #define HALP_FIX_KD_HALIA64_MASK 1
  57. ULONG HalpFixKdHalia64Mask = 0;
  58. VOID
  59. HalpInitializeInterruptBlock (
  60. VOID
  61. )
  62. /*++
  63. Routine Description:
  64. Map Interrupt Block used for IPI. The size of the IPI area is 1MB.
  65. Arguements:
  66. None
  67. Return Value:
  68. None
  69. --*/
  70. {
  71. InterruptBlock = (PULONGLONG) HalpMapPhysicalMemory (
  72. INTERRUPT_BLOCK_ADDRESS,
  73. 256,
  74. MmNonCached);
  75. return;
  76. }
  77. VOID
  78. HalpCalibrateTB (
  79. )
  80. /*++
  81. Routine Description:
  82. This function calibrates the time base by determining the frequency
  83. that the ITC is running at to determine the interval value for a
  84. 100 ns time increment (used by clock and profile).
  85. Arguments:
  86. None.
  87. Return Value:
  88. None.
  89. */
  90. {
  91. return;
  92. }
  93. VOID
  94. HalpFlushTLB (
  95. VOID
  96. )
  97. {
  98. return;
  99. }
  100. BOOLEAN
  101. HalAllProcessorsStarted (
  102. VOID
  103. )
  104. /**++
  105. Routine Description:
  106. This function returns TRUE if all the processors in the system started
  107. successfully.
  108. Arguments:
  109. None.
  110. Return Value:
  111. Returns TRUE.
  112. --**/
  113. {
  114. return TRUE;
  115. }
  116. VOID
  117. HalpIpiInterruptHandler(
  118. IN PKINTERRUPT_ROUTINE Interrupt,
  119. IN PKTRAP_FRAME TrapFrame
  120. )
  121. /*++
  122. Routine Description:
  123. This routine is entered as the result of an interrupt generated by inter
  124. processor communication.
  125. Arguments:
  126. Interrupt - Interrupt object address
  127. TrapFrame - Trap frame address
  128. Return Value:
  129. None.
  130. --*/
  131. {
  132. KeIpiInterrupt(TrapFrame);
  133. return;
  134. }
  135. VOID
  136. HalpSendIPI(
  137. IN USHORT ProcessorID,
  138. IN ULONGLONG Data
  139. )
  140. /*++
  141. Routine Description:
  142. This function sends IPI to the processor specified.
  143. Arguements:
  144. ProcessorID - Supplies the ID of processor to IPI.
  145. Data - The formatted Data ready to ship it as IPI.
  146. Return Value:
  147. None.
  148. --*/
  149. {
  150. PULONGLONG Address;
  151. ULONG tmp1;
  152. KIRQL OldIrql;
  153. tmp1 = ProcessorID << IPI_ID_SHIFT;
  154. Address = (PULONGLONG)((UINT_PTR)(InterruptBlock) + tmp1);
  155. *(volatile ULONGLONG *)Address = Data;
  156. return;
  157. }
  158. NTSTATUS
  159. HalpSendCrossPartitionIpi(
  160. IN USHORT ProcessorID,
  161. IN UCHAR HardwareVector
  162. )
  163. /*++
  164. Routine Description:
  165. This function sends a cross partition IPI to the processor
  166. specified. The caller must know that this processor is in another
  167. partition and the hardware vector previously reserved for
  168. receiving cross partition IPIs.
  169. Arguements:
  170. ProcessorID - Supplies the ID of processor to IPI.
  171. HardwareVector - Hardware Vector on remote processor that will
  172. receive the interrupt.
  173. Return Value:
  174. NTSTATUS
  175. --*/
  176. {
  177. ULONGLONG Data;
  178. if (HardwareVector < 16) {
  179. return STATUS_INVALID_PARAMETER;
  180. }
  181. Data = HardwareVector | DELIVER_FIXED;
  182. HalpSendIPI(ProcessorID, Data);
  183. return STATUS_SUCCESS;
  184. }
  185. VOID
  186. HalpOSRendez (
  187. IN USHORT ProcessorID
  188. )
  189. /*++
  190. Routine Description:
  191. This function does IPI to start the next processor.
  192. Arguements:
  193. PhysicalNumber - Supplies the physical number of processor to IPI.
  194. Return Value:
  195. None.
  196. --*/
  197. {
  198. HalpSendIPI ( ProcessorID, HalpOsBootRendezVector);
  199. return;
  200. }
  201. BOOLEAN
  202. HalStartNextProcessor (
  203. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  204. IN PKPROCESSOR_STATE ProcessorState
  205. )
  206. /*++
  207. Routine Description:
  208. This function is called to start the next processor.
  209. Arguments:
  210. LoaderBlock - Supplies a pointer to the loader parameter block.
  211. ProcessorState - Supplies a pointer to the processor state to be
  212. used to start the processor.
  213. Return Value:
  214. If a processor is successfully started, then a value of TRUE is
  215. returned. Otherwise a value of FALSE is returned. If a value of
  216. TRUE is returned, then the logical processor number is stored
  217. in the processor control block specified by the loader block.
  218. --*/
  219. {
  220. ULONG count;
  221. ULONGLONG EntryPoint;
  222. ULONG ProcNumber = ((PKPRCB)LoaderBlock->Prcb)->Number;
  223. SAL_PAL_RETURN_VALUES SalReturn;
  224. SAL_STATUS salStatus;
  225. NTSTATUS ntStatus;
  226. USHORT TargetProcessorID;
  227. if (HalpAcpiNumProcessors() <= ProcNumber) {
  228. return (FALSE);
  229. }
  230. //
  231. // Boot OS rendezvous entry point
  232. //
  233. EntryPoint = ProcessorState->ContextFrame.StIIP;
  234. salStatus = HalpSalCall(SAL_SET_VECTORS,
  235. 2 /* Boot rendz */,
  236. (ULONGLONG)(MmGetPhysicalAddress((PUCHAR)EntryPoint).QuadPart),
  237. 0,
  238. 0,
  239. 0,
  240. 0,
  241. 0,
  242. &SalReturn);
  243. if (salStatus != 0) {
  244. HalDebugPrint(( HAL_ERROR, "HAL: HalStartNextProcessor - Cannot register OS rendezvous with SAL for processor %d\n",
  245. ProcNumber ));
  246. return (FALSE);
  247. }
  248. //
  249. // For ia64, we will assume that the processor is ready and not started
  250. //
  251. //
  252. // Start the next processor, if Processor ID not self
  253. //
  254. ntStatus = HalpGetApicIdByProcessorNumber((UCHAR)ProcNumber, &TargetProcessorID);
  255. if (!NT_SUCCESS(ntStatus)) {
  256. return FALSE;
  257. }
  258. HalpOSRendez(TargetProcessorID);
  259. count = 0;
  260. while (*((volatile ULONG_PTR *)&LoaderBlock->Prcb) != 0 && (count < RENDEZ_TIME_OUT)) {
  261. KeStallExecutionProcessor (1000); // 1000000
  262. count++;
  263. } // end while (count < RENDEZ_TIMEOUT)
  264. if (LoaderBlock->Prcb != 0) {
  265. return (FALSE);
  266. } else {
  267. return (TRUE);
  268. }
  269. }
  270. VOID
  271. HalRequestIpi (
  272. IN KAFFINITY Mask
  273. )
  274. /*++
  275. Routine Description:
  276. This function does nothing on a uni-processor platform.
  277. Arguments:
  278. Mask - A mask that specifies the target processor(s) to which an
  279. IPI is to be sent.
  280. Return Value:
  281. None.
  282. --*/
  283. {
  284. USHORT LogicalCpu;
  285. USHORT ProcessorID;
  286. //
  287. // Make sure we don't try and IPI processors that we don't believe are
  288. // started
  289. //
  290. Mask &= HalpActiveProcessors;
  291. //
  292. // Scan the processor set and request an interprocessor interrupt on
  293. // each of the specified targets.
  294. //
  295. for (LogicalCpu = 0; LogicalCpu < HalpMpInfo.ProcessorCount; LogicalCpu++) {
  296. if ((Mask & (1 << HalpProcessorInfo[LogicalCpu].NtProcessorNumber)) != 0) {
  297. ProcessorID = HalpProcessorInfo[LogicalCpu].LocalApicID;
  298. //
  299. // Request interprocessor interrupt on target physicalCpu.
  300. //
  301. HalpSendIPI(ProcessorID, IPI_VECTOR);
  302. }
  303. }
  304. }
  305. VOID
  306. HalProcessorIdle (
  307. VOID
  308. )
  309. /*++
  310. Routine Description:
  311. This function calls the TAL function to halt the processor.
  312. Arguments:
  313. None.
  314. Return Value:
  315. None.
  316. --*/
  317. {
  318. _enable();
  319. }
  320. #if !defined(NO_LEGACY_DRIVERS)
  321. BOOLEAN
  322. HalMakeBeep (
  323. IN ULONG Frequency
  324. )
  325. /*++
  326. Routine Description:
  327. This function calls SSC function SscMakeBeep() to make a beep sound
  328. when the specified frequency has a non-zero value.
  329. Arguments:
  330. Frequency - the frequency of the sound to be made.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. if (Frequency > 0) {
  336. SscMakeBeep(Frequency);
  337. }
  338. return TRUE;
  339. }
  340. #endif // NO_LEGACY_DRIVERS
  341. VOID
  342. KeStallExecutionProcessor (
  343. IN ULONG MicroSeconds
  344. )
  345. /**
  346. Routine Description:
  347. This function stalls the processor.
  348. Arguments:
  349. MicroSeconds - Number of microseconds to stall the processor.
  350. Return Value:
  351. None.
  352. **/
  353. {
  354. ULONGLONG CurrentITC;
  355. ULONGLONG LimitITC;
  356. CurrentITC = __getReg(CV_IA64_ApITC);
  357. #ifndef DISABLE_ITC_WORKAROUND
  358. while ((CurrentITC & 0xFFFFFFFF) == 0xFFFFFFFF) {
  359. CurrentITC = __getReg(CV_IA64_ApITC);
  360. }
  361. #endif
  362. LimitITC = CurrentITC + (ULONGLONG) (HalpITCTicksPer100ns * 10 * MicroSeconds);
  363. while (LimitITC > CurrentITC) {
  364. CurrentITC = __getReg(CV_IA64_ApITC);
  365. #ifndef DISABLE_ITC_WORKAROUND
  366. while ((CurrentITC & 0xFFFFFFFF) == 0xFFFFFFFF) {
  367. CurrentITC = __getReg(CV_IA64_ApITC);
  368. }
  369. #endif
  370. }
  371. return;
  372. }
  373. VOID HalpInitLINT(VOID);
  374. VOID
  375. HalInitializeProcessor (
  376. ULONG Number,
  377. PLOADER_PARAMETER_BLOCK LoaderBlock
  378. )
  379. /*++
  380. Routine Description:
  381. This function is called early in the initialization of the kernel
  382. to perform platform dependent initialization for each processor
  383. before the HAL Is fully functional.
  384. N.B. When this routine is called, the PCR is present but is not
  385. fully initialized.
  386. Arguments:
  387. Number - Supplies the number of the processor to initialize.
  388. Return Value:
  389. None.
  390. --*/
  391. {
  392. extern ULONG HalpDefaultInterruptAffinity;
  393. //
  394. // Add this processor to the interrupt affinity mask
  395. //
  396. HalpDefaultInterruptAffinity |= 1<<Number;
  397. //
  398. // Turn off LINT0 LINT1 (disable 8259)
  399. //
  400. // __setReg(CV_IA64_SaLRR0, 0x10000);
  401. // __setReg(CV_IA64_SaLRR1, 0x10000);
  402. //
  403. HalpInitLINT();
  404. __dsrlz();
  405. //
  406. // No need to Initialize the virtual address mapping for IO port space
  407. // since loader/MM do that
  408. //
  409. PhysicalIOBase = LoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].PhysicalAddress;
  410. PCR->StallScaleFactor = 0;
  411. //
  412. // Save my processor ID in PCR
  413. //
  414. PCR->HalReserved[PROCESSOR_ID_INDEX] = HalpReadLID() >> 16;
  415. //
  416. // This next call has nothing to do with processor init.
  417. // But this is the only function in the HAL that gets
  418. // called before KdInit.
  419. //
  420. HalpRegisterKdSupportFunctions(LoaderBlock);
  421. //
  422. // Update node tables
  423. //
  424. HalpAddNodeNumber(Number);
  425. return;
  426. }
  427. VOID
  428. HalpRegisterInternalInterrupts(
  429. VOID
  430. )
  431. /*++
  432. Routine Description:
  433. This function reserves the known HAL IA64 resources usage and
  434. registers the IDT vectors usage.
  435. Arguements:
  436. None.
  437. Return Value:
  438. None.
  439. --*/
  440. {
  441. ULONG i;
  442. //
  443. // Make sure all vectors 00-2f, c0-ff are reserved
  444. // 00-0E Passive Reserved by Intel
  445. // 0F SAPIC Spurious Interrupt Vector Reserved
  446. // 10-1F APC priority level Reserved
  447. // 20-2F DPC priority level Reserved
  448. // c0-ff clock, ipi, synch, high
  449. // these are reserved in HalpGetSystemInterruptVector()
  450. // Do not report to IoReportHalResourceUsage()
  451. //
  452. for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
  453. if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
  454. HalpIDTUsage[i].Flags = 0;
  455. HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
  456. }
  457. }
  458. //
  459. // Make sure all the interrupts in the SYNCH IRQL range are
  460. // also reserved.
  461. //
  462. for(i= SYNCH_VECTOR; i < (SYNCH_VECTOR+16); i++) {
  463. if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
  464. HalpIDTUsage[i].Flags = 0;
  465. HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
  466. }
  467. }
  468. //
  469. // Make sure all the interrupts in the IPI IRQL range are also
  470. // reserved.
  471. //
  472. for(i= IPI_VECTOR; i < (IPI_VECTOR+16); i++) {
  473. if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
  474. HalpIDTUsage[i].Flags = 0;
  475. HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
  476. }
  477. }
  478. //
  479. // Make sure all the interrupts in the CLOCK IRQL range are also
  480. // reserved.
  481. //
  482. for(i= CLOCK_VECTOR; i < (CLOCK_VECTOR+16); i++) {
  483. if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
  484. HalpIDTUsage[i].Flags = 0;
  485. HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
  486. }
  487. }
  488. //
  489. // Make sure all interrupts in the PROFILE IRQL range also are
  490. // reserved.
  491. //
  492. for(i= PROFILE_VECTOR; i < (PROFILE_VECTOR+16); i++) {
  493. if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
  494. HalpIDTUsage[i].Flags = 0;
  495. HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
  496. }
  497. }
  498. HalpRegisterVector (
  499. 0,
  500. SAPIC_SPURIOUS_VECTOR,
  501. SAPIC_SPURIOUS_VECTOR,
  502. SAPIC_SPURIOUS_LEVEL
  503. );
  504. HalpRegisterVector (
  505. 0,
  506. (APC_LEVEL << VECTOR_IRQL_SHIFT),
  507. (APC_LEVEL << VECTOR_IRQL_SHIFT),
  508. APC_LEVEL
  509. );
  510. HalpRegisterVector (
  511. 0,
  512. (DPC_LEVEL << VECTOR_IRQL_SHIFT),
  513. (DPC_LEVEL << VECTOR_IRQL_SHIFT),
  514. DPC_LEVEL
  515. );
  516. HalpRegisterVector (
  517. 0,
  518. MC_RZ_VECTOR,
  519. MC_RZ_VECTOR,
  520. HIGH_LEVEL
  521. );
  522. HalpRegisterVector (
  523. 0,
  524. MC_WKUP_VECTOR,
  525. MC_WKUP_VECTOR,
  526. HIGH_LEVEL
  527. );
  528. //
  529. // Note that it is possible that HAL_CMC_PRESENT is not set.
  530. // With the current implementation, we always register the CMC vector.
  531. //
  532. HalpRegisterVector (
  533. 0,
  534. CMCI_VECTOR,
  535. CMCI_VECTOR,
  536. CMCI_LEVEL
  537. );
  538. //
  539. // Note that it is possible that HAL_CPE_PRESENT is not set.
  540. // With the current implementation, we always register the CPE vector.
  541. //
  542. HalpRegisterVector (
  543. 0,
  544. CPEI_VECTOR,
  545. CPEI_VECTOR,
  546. CPEI_LEVEL
  547. );
  548. HalpRegisterVector (
  549. 0,
  550. SYNCH_VECTOR,
  551. SYNCH_VECTOR,
  552. SYNCH_LEVEL
  553. );
  554. HalpRegisterVector (
  555. 0,
  556. IPI_VECTOR,
  557. IPI_VECTOR,
  558. IPI_LEVEL
  559. );
  560. HalpRegisterVector (
  561. 0,
  562. CLOCK_VECTOR,
  563. CLOCK_VECTOR,
  564. CLOCK_LEVEL
  565. );
  566. HalpRegisterVector (
  567. 0,
  568. PROFILE_VECTOR,
  569. PROFILE_VECTOR,
  570. PROFILE_LEVEL
  571. );
  572. HalpRegisterVector (
  573. 0,
  574. PERF_VECTOR,
  575. PERF_VECTOR,
  576. PROFILE_LEVEL
  577. );
  578. return;
  579. } // HalpRegisterInternalInterrupts()
  580. VOID
  581. HalpPerfInterrupt (
  582. IN PKINTERRUPT_ROUTINE Interrupt,
  583. IN PKTRAP_FRAME TrapFrame
  584. )
  585. /*++
  586. Routine Description:
  587. Arguements:
  588. Return Parameters:
  589. --*/
  590. {
  591. // Thierry: This interrupt handler could be used to implement instructions
  592. // tracing based on the overflow interrupts generated by PMU events
  593. // like "retired instructions" or "taken branches".
  594. // This would provide very valuable inputs for hardware performance simulators.
  595. //
  596. // XXTF - not implemented yet...
  597. return;
  598. } // HalpPerfInterrupt()
  599. #if defined(HALP_FIX_KD_HALIA64_MASK)
  600. #if DBG
  601. VOID
  602. HalpSetKdHalia64Mask(
  603. ULONG Mask
  604. )
  605. //
  606. // Mask == 0 should return without modifying Kd_HALIA64_Mask.
  607. //
  608. {
  609. NTSTATUS status;
  610. ULONG level, levelMasked;
  611. int shift;
  612. if ( Mask == (ULONG)-1 ) {
  613. status = DbgSetDebugFilterState( DPFLTR_HALIA64_ID, -1, TRUE );
  614. if ( !NT_SUCCESS(status) ) {
  615. HalDebugPrint(( HAL_ERROR,
  616. "HAL!HalInitSystem: failed to set Kd_HALIA64_Mask to maximum debug spew... 0x%lx\n",
  617. status ));
  618. }
  619. return;
  620. }
  621. level = levelMasked = Mask & HALIA64_DPFLTR_MAXMASK;
  622. shift = 0;
  623. while( level ) {
  624. level &= 0x1;
  625. if ( level ) {
  626. status = DbgSetDebugFilterState( DPFLTR_HALIA64_ID, shift, TRUE );
  627. if ( !NT_SUCCESS(status) ) {
  628. HalDebugPrint(( HAL_ERROR,
  629. "HAL!HalInitSystem: failed to set Kd_HALIA64_Mask to 0x%lx... 0x%lx\n",
  630. shift,
  631. status ));
  632. break;
  633. }
  634. }
  635. shift = shift + 1;
  636. level = levelMasked >> shift;
  637. }
  638. return;
  639. } // HalpSetKdHalia64Mask()
  640. #else // !DBG
  641. #define HalpSetKdHalia64Mask()
  642. #endif // !DBG
  643. #endif // HALP_FIX_KD_HALIA64_MASK
  644. BOOLEAN
  645. HalInitSystem (
  646. IN ULONG Phase,
  647. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  648. )
  649. /*++
  650. Routine Description:
  651. This function initializes the Hardware Architecture Layer (HAL) for an
  652. ia64 system.
  653. Arguments:
  654. None.
  655. Return Value:
  656. A value of TRUE is returned is the initialization was successfully
  657. complete. Otherwise a value of FALSE is returned.
  658. --*/
  659. {
  660. PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
  661. PLIST_ENTRY NextMd;
  662. PKPRCB pPRCB;
  663. volatile KPCR * const pPCR = KeGetPcr();
  664. BOOLEAN Found;
  665. ULONGLONG ITCFrequencyQueried;
  666. ULONGLONG ProcessorFrequencyQueried;
  667. ULONG RTCInti;
  668. KIRQL OldIrql;
  669. NTSTATUS status;
  670. //
  671. // This is for testing RTC clock
  672. //
  673. TIME_FIELDS CurrentTimeFields;
  674. pPRCB = KeGetCurrentPrcb();
  675. if (Phase == 0) {
  676. extern VOID DetectAcpiMP();
  677. BOOLEAN IsMP;
  678. BOOLEAN EnableInterrupts;
  679. //
  680. // Phase 0 initialization only called by P0
  681. //
  682. HalpBusType = LoaderBlock->u.Ia64.MachineType & 0x00ff;
  683. HalpGetParameters (LoaderBlock);
  684. //
  685. // Disable Interrupts before messing around with the APIC etc.
  686. //
  687. EnableInterrupts = HalpDisableInterrupts();
  688. DetectAcpiMP(&IsMP, LoaderBlock);
  689. HalpSetupAcpiPhase0(LoaderBlock);
  690. //
  691. // Verify Prcb version and build flags conform to
  692. // this image
  693. //
  694. if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
  695. KeBugCheckEx (
  696. MISMATCHED_HAL,
  697. 1,
  698. pPRCB->MajorVersion,
  699. PRCB_MAJOR_VERSION,
  700. 0
  701. );
  702. }
  703. KeInitializeSpinLock(&HalpIoSapicLock);
  704. //
  705. // Fill in handlers for APIs which this hal supports
  706. //
  707. HalQuerySystemInformation = HaliQuerySystemInformation;
  708. HalSetSystemInformation = HaliSetSystemInformation;
  709. HalInitPnpDriver = HaliInitPnpDriver;
  710. //
  711. // HalGetDmaAdapter was commented in previous version
  712. // also. HalInitPowerManagement, HalLocateHiberRanges and
  713. // HalGetInterruptTranslator are added in the latest version
  714. // of Microsoft source code.
  715. //
  716. HalGetDmaAdapter = HaliGetDmaAdapter;
  717. HalHaltSystem = HaliHaltSystem;
  718. HalResetDisplay = HalpBiosDisplayReset;
  719. #if !defined( HAL_SP )
  720. HalGetInterruptTranslator = HalacpiGetInterruptTranslator;
  721. #endif // HAL_SP
  722. #if DBG
  723. //
  724. // Switch from HalDisplayString to DbgPrint.
  725. //
  726. HalpUseDbgPrint++;
  727. #endif // DBG
  728. #if !defined( HAL_SP ) && !(MCA)
  729. HalInitPowerManagement = HaliInitPowerManagement;
  730. HalLocateHiberRanges = HaliLocateHiberRanges;
  731. #endif// HAL_SP and MCA
  732. //
  733. // Register PC style IO space used by hal
  734. //
  735. HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
  736. HalpInitIntiInfo ();
  737. //
  738. // Initialize CMOS
  739. //
  740. HalpInitializeCmos();
  741. //
  742. // Initialize per processor EOI table
  743. //
  744. HalpInitEOITable();
  745. //
  746. // Initialize the clock for the processor that keeps
  747. // the system time. This uses a stub ISR until Phase 1
  748. //
  749. // Initialize Clock interrupts, profile , APC and DPC interrupts,
  750. HalpInitializeClock();
  751. HalpRegisterInternalInterrupts();
  752. HalpInitializeInterrupts();
  753. //
  754. // Initialize initial processor and NT profiling state
  755. // that should be initialized at Phase 0 and
  756. // do not require to wait for Phase 1.
  757. //
  758. HalpSetInitialProfileState();
  759. //
  760. // Interrupts should be safe now.
  761. //
  762. if (EnableInterrupts) {
  763. HalpEnableInterrupts();
  764. }
  765. //
  766. // Initialize event for serialization of new dma adapter events
  767. //
  768. KeInitializeEvent(&HalpNewAdapter, SynchronizationEvent, TRUE);
  769. //
  770. // Determine if there is physical memory above 4 GB.
  771. //
  772. HalDebugPrint(( HAL_INFO, "HAL: Determine if there is memory above 4 Gb\n" ));
  773. NoMemoryAbove4Gb = TRUE;
  774. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  775. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  776. Descriptor = CONTAINING_RECORD(
  777. NextMd,
  778. MEMORY_ALLOCATION_DESCRIPTOR,
  779. ListEntry
  780. );
  781. if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
  782. Descriptor->MemoryType != LoaderSpecialMemory) {
  783. //
  784. // Test for 4 GB:
  785. //
  786. if ((Descriptor->BasePage + Descriptor->PageCount) > (GreaterThan4GB >> PAGE_SHIFT)) {
  787. NoMemoryAbove4Gb = FALSE;
  788. HalDebugPrint(( HAL_INFO, "HAL: Memory is present above 4Gb\n" ));
  789. break;
  790. }
  791. }
  792. NextMd = Descriptor->ListEntry.Flink;
  793. }
  794. //
  795. // Determine the size needed for map buffers. If this system has
  796. // memory that requires more than 32 bits to access, then allocate
  797. // a large chunk; otherwise, allocate a small chunk.
  798. //
  799. if (NoMemoryAbove4Gb) {
  800. //
  801. // Allocate a small set of map buffers. They are only need for
  802. // devices which do not function.
  803. //
  804. HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
  805. HalDebugPrint(( HAL_INFO, "HAL: No memory beyond 4Gb\n" ));
  806. } else {
  807. //
  808. // Allocate a larger set of map buffers. These are used for
  809. // 32 bit devices to reach memory above 4gb.
  810. //
  811. HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
  812. HalDebugPrint(( HAL_INFO, "HAL: Map Buffers for 32 bit devices to reach memory above 4Gb\n" ));
  813. }
  814. //
  815. // Allocate map buffers for the adapter objects
  816. //
  817. HalpMapBufferPhysicalAddress.QuadPart = (ULONGLONG)
  818. HalpAllocPhysicalMemory(LoaderBlock,
  819. MAXIMUM_PHYSICAL_ADDRESS,
  820. HalpMapBufferSize >> PAGE_SHIFT,
  821. TRUE);
  822. HalpMapBufferPhysicalAddress.HighPart = 0;
  823. if (!HalpMapBufferPhysicalAddress.LowPart) {
  824. //
  825. // There was not a satisfactory block. Clear the allocation.
  826. //
  827. HalpMapBufferSize = 0;
  828. }
  829. //
  830. // Set the processor active in the HAL private active processor mask.
  831. //
  832. // For the BSP processor, the specific bit is set at the end of HalInitSystem(Phase0).
  833. HalpActiveProcessors = 1 << pPRCB->Number;
  834. } else {
  835. //
  836. // Phase 1 initialization
  837. //
  838. if ( pPCR->Number == 0) {
  839. //
  840. // Back-pocket some PTEs for DMA during low mem
  841. //
  842. HalpInitReservedPages();
  843. #if defined(HALP_FIX_KD_HALIA64_MASK)
  844. #if DBG
  845. HalpSetKdHalia64Mask( HalpFixKdHalia64Mask );
  846. #endif // DBG
  847. #endif // HALP_FIX_KD_HALIA64_MASK
  848. HalpEfiInitialization(LoaderBlock);
  849. HalpInitIoMemoryBase();
  850. HalpInitializeX86Int10Call();
  851. HalpInitializeInterruptBlock();
  852. //
  853. // Map the APICs so that MM will allow us to access them in the
  854. // debugger.
  855. //
  856. HalpInitApicDebugMappings();
  857. //
  858. // Initialize MCA,INIT parameters and pre-allocate Event records for BSP processor.
  859. //
  860. if ( !HalpInitializeOSMCA( pPCR->Number ) ) {
  861. return FALSE;
  862. }
  863. HalpInitNonBusHandler();
  864. //
  865. // Raise IRQL to the highest level, set the new clock interrupt
  866. // parameters, lower IRQl, and return the new time increment value.
  867. //
  868. status = HalpQueryFrequency( &ITCFrequencyQueried,
  869. &ProcessorFrequencyQueried);
  870. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  871. if (NT_SUCCESS(status)) {
  872. HalpITCFrequency = ITCFrequencyQueried;
  873. HalpProcessorFrequency = ProcessorFrequencyQueried;
  874. }
  875. HalpSetInitialClockRate();
  876. KeLowerIrql(OldIrql);
  877. //
  878. // Set initial feature bits
  879. //
  880. HalpFeatureBits = HalpGetFeatureBits();
  881. //
  882. // Initialize per-processor profiling
  883. //
  884. // Requires HalpITCTicksPer100ns initialized.
  885. HalpInitializeProfiling( pPCR->Number );
  886. HalpMCAEnable();
  887. HalpCMCEnable();
  888. HalpCPEEnable();
  889. } else {
  890. //
  891. // Initialize per processor EOI table
  892. //
  893. HalpInitEOITable();
  894. //
  895. // Initialization needed only on non BSP processors
  896. //
  897. HalpInitSalPalNonBsp();
  898. HalpInitializeClockPn();
  899. //
  900. // Allocate MCA, INIT stacks on non BSP processors
  901. //
  902. if ( !HalpAllocateMceStacks( pPCR->Number) ) {
  903. return FALSE;
  904. }
  905. //
  906. // Pre-allocate MCA,INIT records on non BSP processors
  907. //
  908. if ( !HalpPreAllocateMceRecords( pPCR->Number) ) {
  909. return FALSE;
  910. }
  911. //
  912. // Reduce feature bits to be a subset
  913. //
  914. HalpFeatureBits &= HalpGetFeatureBits();
  915. HalpInitializeInterrupts();
  916. //
  917. // Initialize per-processor profiling
  918. //
  919. HalpInitializeProfiling( pPCR->Number );
  920. HalpMCAEnable();
  921. HalpCMCEnable();
  922. //
  923. // Set the processor active in the HAL private active processor mask.
  924. //
  925. // For non-BSP processors, the specific bit is set at the end of HalInitSystem(Phase1).
  926. HalpActiveProcessors |= 1 << pPRCB->Number;
  927. }
  928. }
  929. return TRUE;
  930. }
  931. VOID
  932. HalChangeColorPage (
  933. IN PVOID NewColor,
  934. IN PVOID OldColor,
  935. IN ULONG PageFrame
  936. )
  937. /*++
  938. Routine Description:
  939. This function changes the color of a page if the old and new colors
  940. do not match.
  941. Arguments:
  942. NewColor - Supplies the page aligned virtual address of the
  943. new color of the page to change.
  944. OldColor - Supplies the page aligned virtual address of the
  945. old color of the page to change.
  946. pageFrame - Supplies the page frame number of the page that
  947. is changed.
  948. Return Value:
  949. None.
  950. --*/
  951. {
  952. return;
  953. }
  954. //****************************************************************
  955. // T. Kjos Added stuff after this line as part of initial
  956. // APIC, PCMP removal.
  957. // From mpsproc.c
  958. ULONG HalpDontStartProcessors = 0;
  959. //
  960. // Since IA-64 does not support lowest priority interrupts set
  961. // processors per cluster to 1 so that we staically assign interrupts
  962. // in round robin to the processors.
  963. //
  964. UCHAR HalpMaxProcsPerCluster = 1;
  965. // From pmmphal.c:
  966. BOOLEAN HalpStaticIntAffinity = FALSE;
  967. extern UCHAR HalpSzInterruptAffinity[];
  968. extern UCHAR HalpSzOneCpu[];
  969. extern ULONG HalpDontStartProcessors;
  970. extern UCHAR HalpSzPciLock[];
  971. extern UCHAR HalpSzBreak[];
  972. extern UCHAR HalpSzForceClusterMode[];
  973. VOID
  974. HalpGetParameters (
  975. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  976. )
  977. /*++
  978. Routine Description:
  979. This gets any parameters from the boot.ini invocation line.
  980. Arguments:
  981. None.
  982. Return Value:
  983. None
  984. --*/
  985. {
  986. PCHAR Options;
  987. PCHAR p;
  988. if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
  989. Options = LoaderBlock->LoadOptions;
  990. //
  991. // Has the user set the debug flag?
  992. //
  993. //
  994. // Has the user requested a particular number of CPU's?
  995. //
  996. if (strstr(Options, HalpSzOneCpu)) {
  997. HalpDontStartProcessors++;
  998. }
  999. //
  1000. // Check if user wants device ints to go to highest numbered processor
  1001. //
  1002. if (strstr(Options, HalpSzInterruptAffinity)) {
  1003. HalpStaticIntAffinity = TRUE;
  1004. }
  1005. //
  1006. // Has the user asked for an initial BreakPoint?
  1007. //
  1008. if (strstr(Options, HalpSzBreak)) {
  1009. DbgBreakPoint();
  1010. }
  1011. //
  1012. // Used to define the size of a node = MaxProcsPerCluster
  1013. // 0 implies one node for the whole machine
  1014. //
  1015. p = strstr(Options, HalpSzForceClusterMode);
  1016. if (p) {
  1017. // skip to value
  1018. while (*p && *p != ' ' && (*p < '0' || *p > '9')) {
  1019. p++;
  1020. }
  1021. HalpMaxProcsPerCluster = (UCHAR)atoi(p);
  1022. }
  1023. }
  1024. return ;
  1025. }