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.

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