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.

1231 lines
29 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Copyright (c) 1992 Intel Corporation
  4. All rights reserved
  5. INTEL CORPORATION PROPRIETARY INFORMATION
  6. This software is supplied to Microsoft under the terms
  7. of a license agreement with Intel Corporation and may not be
  8. copied nor disclosed except in accordance with the terms
  9. of that agreement.
  10. Module Name:
  11. mphal.c
  12. Abstract:
  13. This module implements the initialization of the system dependent
  14. functions that define the Hardware Architecture Layer (HAL) for a
  15. PC+MP system.
  16. Author:
  17. David N. Cutler (davec) 25-Apr-1991
  18. Environment:
  19. Kernel mode only.
  20. Revision History:
  21. Ron Mosgrove (Intel) - Modified to support the PC+MP Spec
  22. Jake Oshins (jakeo) - Modified to support the ACPI Spec
  23. */
  24. #include "halp.h"
  25. #include "pcmp_nt.inc"
  26. #include "string.h"
  27. #include "stdlib.h"
  28. #include "stdio.h"
  29. ULONG HalpBusType;
  30. extern ADDRESS_USAGE HalpDefaultPcIoSpace;
  31. extern ADDRESS_USAGE HalpEisaIoSpace;
  32. extern ADDRESS_USAGE HalpImcrIoSpace;
  33. extern struct HalpMpInfo HalpMpInfoTable;
  34. extern UCHAR rgzRTCNotFound[];
  35. extern USHORT HalpVectorToINTI[];
  36. extern UCHAR HalpAuthenticAMD[];
  37. extern UCHAR HalpGenuineIntel[];
  38. extern const UCHAR HalName[];
  39. extern BOOLEAN HalpDoingCrashDump;
  40. extern PULONG KiEnableTimerWatchdog;
  41. extern ULONG HalpTimerWatchdogEnabled;
  42. extern PCHAR HalpTimerWatchdogStorage;
  43. extern PVOID HalpTimerWatchdogCurFrame;
  44. extern PVOID HalpTimerWatchdogLastFrame;
  45. extern ULONG HalpTimerWatchdogStorageOverflow;
  46. extern KSPIN_LOCK HalpDmaAdapterListLock;
  47. extern LIST_ENTRY HalpDmaAdapterList;
  48. extern ULONGLONG HalpProc0TSCHz;
  49. #ifdef ACPI_HAL
  50. extern ULONG HalpPicVectorRedirect[];
  51. #define ADJUSTED_VECTOR(x) \
  52. HalpPicVectorRedirect[x]
  53. #else
  54. #define ADJUSTED_VECTOR(x) x
  55. #endif
  56. #if defined(_AMD64_)
  57. VOID
  58. HalpInitializeBios(VOID);
  59. #endif
  60. VOID
  61. HalpInitMP(
  62. IN ULONG Phase,
  63. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  64. );
  65. KSPIN_LOCK HalpSystemHardwareLock;
  66. VOID
  67. HalpInitBusHandlers (
  68. VOID
  69. );
  70. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpClockInterruptPn);
  71. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpClockInterruptStub);
  72. BOOLEAN
  73. HalpmmTimer(
  74. VOID
  75. );
  76. VOID
  77. HalpmmTimerClockInit(
  78. VOID
  79. );
  80. VOID
  81. HalpmmTimerClockInterruptStub(
  82. VOID
  83. );
  84. ULONG
  85. HalpScaleTimers(
  86. VOID
  87. );
  88. BOOLEAN
  89. HalpPmTimerScaleTimers(
  90. VOID
  91. );
  92. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpApicRebootService);
  93. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpBroadcastCallService);
  94. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpDispatchInterrupt);
  95. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpApcInterrupt);
  96. HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpIpiHandler);
  97. VOID
  98. HalpInitializeIOUnits (
  99. VOID
  100. );
  101. VOID
  102. HalpInitIntiInfo (
  103. VOID
  104. );
  105. VOID
  106. HalpGetParameters (
  107. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  108. );
  109. VOID
  110. HalpInitializeTimerResolution (
  111. ULONG Rate
  112. );
  113. ULONG
  114. HalpGetFeatureBits (
  115. VOID
  116. );
  117. VOID
  118. HalpInitializeApicAddressing(
  119. UCHAR Number
  120. );
  121. VOID
  122. HalpInitReservedPages(
  123. VOID
  124. );
  125. VOID
  126. HalpAcpiTimerPerfCountHack(
  127. VOID
  128. );
  129. BOOLEAN
  130. HalpFindBusAddressTranslation(
  131. IN PHYSICAL_ADDRESS BusAddress,
  132. IN OUT PULONG AddressSpace,
  133. OUT PPHYSICAL_ADDRESS TranslatedAddress,
  134. IN OUT PULONG_PTR Context,
  135. IN BOOLEAN NextBus
  136. );
  137. #ifdef DEBUGGING
  138. extern void HalpDisplayLocalUnit(void);
  139. extern void HalpDisplayConfigTable(void);
  140. extern void HalpDisplayExtConfigTable(void);
  141. #endif // DEBUGGING
  142. BOOLEAN HalpStaticIntAffinity = FALSE;
  143. BOOLEAN HalpClockMode = Latched;
  144. UCHAR HalpMaxProcsPerCluster = 0;
  145. extern BOOLEAN HalpUse8254;
  146. extern UCHAR HalpSzInterruptAffinity[];
  147. extern BOOLEAN HalpPciLockSettings;
  148. extern UCHAR HalpVectorToIRQL[];
  149. extern ULONG HalpDontStartProcessors;
  150. extern UCHAR HalpSzOneCpu[];
  151. extern UCHAR HalpSzNoIoApic[];
  152. extern UCHAR HalpSzBreak[];
  153. extern UCHAR HalpSzPciLock[];
  154. extern UCHAR HalpSzTimerRes[];
  155. extern UCHAR HalpSzClockLevel[];
  156. extern UCHAR HalpSzUse8254[];
  157. extern UCHAR HalpSzForceClusterMode[];
  158. ULONG UserSpecifiedCpuCount = 0;
  159. KSPIN_LOCK HalpAccountingLock;
  160. #ifdef ACPI_HAL
  161. extern KEVENT HalpNewAdapter;
  162. #endif
  163. #ifdef ALLOC_PRAGMA
  164. VOID
  165. HalpInitTimerWatchdog(
  166. IN ULONG Phase
  167. );
  168. #pragma alloc_text(INIT,HalpGetParameters)
  169. #pragma alloc_text(INIT,HalpInitTimerWatchdog)
  170. #pragma alloc_text(INIT,HalInitSystem)
  171. #endif // ALLOC_PRAGMA
  172. KIRQL
  173. FASTCALL
  174. KeAcquireSpinLockRaiseToSynchMCE(
  175. IN PKSPIN_LOCK SpinLock
  176. );
  177. //
  178. // Define bug check callback record.
  179. //
  180. KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
  181. VOID
  182. HalpBugCheckCallback (
  183. IN PVOID Buffer,
  184. IN ULONG Length
  185. )
  186. /*++
  187. Routine Description:
  188. This function is called when a bug check occurs. Its function is
  189. to perform anything the HAL needs done as the system bugchecks.
  190. Arguments: (Unused in this callback).
  191. Buffer - Supplies a pointer to the bug check buffer.
  192. Length - Supplies the length of the bug check buffer in bytes.
  193. Return Value:
  194. None.
  195. --*/
  196. {
  197. //
  198. // Make sure the HAL won't spin waiting on other processors
  199. // during a crashdump.
  200. //
  201. HalpDoingCrashDump = TRUE;
  202. }
  203. VOID
  204. HalpGetParameters (
  205. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  206. )
  207. /*++
  208. Routine Description:
  209. This gets any parameters from the boot.ini invocation line.
  210. Arguments:
  211. None.
  212. Return Value:
  213. None
  214. --*/
  215. {
  216. PCHAR Options;
  217. PCHAR p;
  218. if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
  219. Options = LoaderBlock->LoadOptions;
  220. //
  221. // Has the user set the debug flag?
  222. //
  223. //
  224. // Has the user requested a particular number of CPU's?
  225. //
  226. if (strstr(Options, HalpSzOneCpu)) {
  227. HalpDontStartProcessors++;
  228. }
  229. //
  230. // Check if PCI settings are locked down
  231. //
  232. if (strstr(Options, HalpSzPciLock)) {
  233. HalpPciLockSettings = TRUE;
  234. }
  235. #ifndef ACPI_HAL
  236. //
  237. // Check if CLKLVL setting
  238. //
  239. if (strstr(Options, HalpSzClockLevel)) {
  240. HalpClockMode = LevelSensitive;
  241. }
  242. //
  243. // Check if 8254 is to be used as high resolution counter
  244. //
  245. if (strstr(Options, HalpSzUse8254)) {
  246. HalpUse8254 = TRUE;
  247. }
  248. #endif
  249. //
  250. // Check if user wants device ints to go to highest numbered processor
  251. //
  252. if (strstr(Options, HalpSzInterruptAffinity)) {
  253. HalpStaticIntAffinity = TRUE;
  254. }
  255. #ifndef ACPI_HAL
  256. //
  257. // Check for TIMERES setting
  258. //
  259. p = strstr(Options, HalpSzTimerRes);
  260. if (p) {
  261. // skip to value
  262. while (*p && *p != ' ' && (*p < '0' || *p > '9')) {
  263. p++;
  264. }
  265. HalpInitializeTimerResolution (atoi(p));
  266. }
  267. #endif
  268. //
  269. // Has the user asked for an initial BreakPoint?
  270. //
  271. if (strstr(Options, HalpSzBreak)) {
  272. DbgBreakPoint();
  273. }
  274. //
  275. // Does the user want to force Cluster mode APIC addressing?
  276. //
  277. p = strstr(Options, HalpSzForceClusterMode);
  278. if (p) {
  279. // skip to value
  280. while (*p && *p != ' ' && (*p < '0' || *p > '9')) {
  281. p++;
  282. }
  283. HalpMaxProcsPerCluster = (UCHAR)atoi(p);
  284. //
  285. // Current processors support maximum 4 processors per cluster.
  286. //
  287. if(HalpMaxProcsPerCluster > 4) {
  288. HalpMaxProcsPerCluster = 4;
  289. }
  290. if (HalpMpInfoTable.ApicVersion == APIC_82489DX) {
  291. //
  292. // Ignore user's attempt to force cluster mode if running
  293. // on 82489DX external APIC interrupt controller.
  294. //
  295. HalpMaxProcsPerCluster = 0;
  296. }
  297. //
  298. // Hack to reprogram the boot processor to use Cluster mode APIC
  299. // addressing if the user supplied a boot.ini switch
  300. // (/MAXPROCSPERCLUSTER=n) to force this. The boot.ini switch is
  301. // parsed after the boot processor's APIC is programmed originally
  302. // but before other non-boot processors were woken up.
  303. //
  304. HalpInitializeApicAddressing(0);
  305. }
  306. }
  307. return ;
  308. }
  309. VOID
  310. HalpInitTimerWatchdog(
  311. IN ULONG Phase
  312. )
  313. /*++
  314. Routine Description:
  315. Determines if the system is running on a GenuineIntel part and initializes
  316. HalpTimerWatchdogEnabled accordingly.
  317. Arguments:
  318. None.
  319. Return Value:
  320. None.
  321. --*/
  322. {
  323. if (Phase == 0) {
  324. ULONG GenuinePentiumOrLater = FALSE, Junk;
  325. PKPRCB Prcb;
  326. Prcb = KeGetCurrentPrcb();
  327. if (Prcb->CpuID) {
  328. UCHAR Buffer[50];
  329. //
  330. // Determine the processor type
  331. //
  332. HalpCpuID (0, &Junk, (PULONG) Buffer+0, (PULONG) Buffer+2, (PULONG) Buffer+1);
  333. Buffer[12] = 0;
  334. GenuinePentiumOrLater =
  335. ((strcmp(Buffer, HalpGenuineIntel) == 0) && (Prcb->CpuType >= 5));
  336. HalpTimerWatchdogEnabled = *KiEnableTimerWatchdog && GenuinePentiumOrLater;
  337. }
  338. } else if (HalpTimerWatchdogEnabled) {
  339. //
  340. // Allocate 2 pages for stack snapshots, each snapshot is 64 DWORDs.
  341. //
  342. if (HalpTimerWatchdogStorage =
  343. ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE * 2, HAL_POOL_TAG )) {
  344. HalpTimerWatchdogLastFrame =
  345. HalpTimerWatchdogStorage + (PAGE_SIZE * 2 - 64*4);
  346. HalpTimerWatchdogStorageOverflow = 0;
  347. HalpTimerWatchdogCurFrame = HalpTimerWatchdogStorage;
  348. } else {
  349. HalpTimerWatchdogEnabled = FALSE;
  350. }
  351. }
  352. }
  353. #ifdef TIMER_DBG
  354. BOOLEAN HalInitialized = FALSE;
  355. #endif
  356. BOOLEAN
  357. HalInitSystem (
  358. IN ULONG Phase,
  359. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  360. )
  361. /*++
  362. Routine Description:
  363. This function initializes the Hardware Architecture Layer (HAL) for an
  364. x86 system.
  365. Arguments:
  366. None.
  367. Return Value:
  368. A value of TRUE is returned is the initialization was successfully
  369. complete. Otherwise a value of FALSE is returend.
  370. --*/
  371. {
  372. PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
  373. PLIST_ENTRY NextMd;
  374. PKPRCB pPRCB;
  375. PKPCR pPCR;
  376. BOOLEAN Found;
  377. USHORT RTCInti;
  378. USHORT mmTInti;
  379. ULONG mapBufferSize;
  380. ULONG mapBufferAddress;
  381. #ifdef DEBUGGING
  382. extern ULONG HalpUseDbgPrint;
  383. #endif // DEBUGGING
  384. pPRCB = KeGetCurrentPrcb();
  385. if (Phase == 0) {
  386. HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
  387. HalpGetParameters (LoaderBlock);
  388. //
  389. // Verify Prcb version and build flags conform to
  390. // this image
  391. //
  392. #if !defined(_AMD64_)
  393. #if DBG
  394. if (!(pPRCB->BuildType & PRCB_BUILD_DEBUG)) {
  395. // This checked hal requires a checked kernel
  396. KeBugCheckEx (MISMATCHED_HAL,
  397. 2, pPRCB->BuildType, PRCB_BUILD_DEBUG, 0);
  398. }
  399. #else
  400. if (pPRCB->BuildType & PRCB_BUILD_DEBUG) {
  401. // This free hal requires a free kernel
  402. KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
  403. }
  404. #endif
  405. #ifndef NT_UP
  406. if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
  407. // This MP hal requires an MP kernel
  408. KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
  409. }
  410. #endif
  411. #endif // _AMD64_
  412. if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
  413. KeBugCheckEx (MISMATCHED_HAL,
  414. 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
  415. }
  416. KeInitializeSpinLock(&HalpAccountingLock);
  417. #ifdef ACPI_HAL
  418. //
  419. // Make sure that this is really an ACPI machine and initialize
  420. // the ACPI structures.
  421. //
  422. HalpSetupAcpiPhase0(LoaderBlock);
  423. #endif
  424. //
  425. // Fill in handlers for APIs which this hal supports
  426. //
  427. #ifndef NT_35
  428. HalQuerySystemInformation = HaliQuerySystemInformation;
  429. HalSetSystemInformation = HalpSetSystemInformation;
  430. #endif
  431. //
  432. // check to see whether the kernel supports these calls
  433. //
  434. if (HALDISPATCH->Version >= HAL_DISPATCH_VERSION) {
  435. HalInitPnpDriver = HaliInitPnpDriver;
  436. HalGetDmaAdapter = HaliGetDmaAdapter;
  437. HalLocateHiberRanges = HaliLocateHiberRanges;
  438. HalResetDisplay = HalpBiosDisplayReset;
  439. HalAllocateMapRegisters = HalpAllocateMapRegisters;
  440. #ifdef ACPI_HAL
  441. HalInitPowerManagement = HaliInitPowerManagement;
  442. HalGetInterruptTranslator = HalacpiGetInterruptTranslator;
  443. HalHaltSystem = HaliHaltSystem;
  444. #else
  445. HalGetInterruptTranslator = HaliGetInterruptTranslator;
  446. #endif
  447. }
  448. //
  449. // Phase 0 initialization only called by P0
  450. //
  451. #ifdef DEBUGGING
  452. HalpUseDbgPrint++;
  453. HalpDisplayLocalUnit();
  454. #ifndef ACPI_HAL
  455. HalpDisplayConfigTable();
  456. HalpDisplayExtConfigTable();
  457. #endif
  458. #endif // DEBUGGING
  459. //
  460. // Keep track of which IRQs are level triggered.
  461. //
  462. #if !defined(MCA) && !defined(ACPI_HAL)
  463. if (HalpBusType == MACHINE_TYPE_EISA) {
  464. HalpRecordEisaInterruptVectors();
  465. }
  466. #endif
  467. //
  468. // Register PC style IO space used by hal
  469. //
  470. HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
  471. if (HalpBusType == MACHINE_TYPE_EISA) {
  472. HalpRegisterAddressUsage (&HalpEisaIoSpace);
  473. }
  474. if (HalpMpInfoTable.IMCRPresent) {
  475. HalpRegisterAddressUsage (&HalpImcrIoSpace);
  476. }
  477. //
  478. // initialize the APIC IO unit, this could be a NOP if none exist
  479. //
  480. HalpInitIntiInfo ();
  481. HalpInitializeIOUnits();
  482. HalpInitializePICs(TRUE);
  483. //
  484. // Initialize CMOS
  485. //
  486. HalpInitializeCmos();
  487. //
  488. // Find the RTC interrupt.
  489. //
  490. Found = HalpGetApicInterruptDesc (
  491. DEFAULT_PC_BUS,
  492. 0,
  493. ADJUSTED_VECTOR(RTC_IRQ),
  494. &RTCInti
  495. );
  496. if (!Found) {
  497. HalDisplayString (rgzRTCNotFound);
  498. return FALSE;
  499. }
  500. //
  501. // Initialize timers
  502. //
  503. //
  504. // We can cut down the boot time using the PM timer to scale,
  505. // but there are so many broken ACPI timers this might not work
  506. //
  507. #ifdef SPEEDY_BOOT
  508. if (!HalpPmTimerScaleTimers())
  509. #endif
  510. HalpScaleTimers();
  511. HalpProc0TSCHz = ((PHALPCR)(KeGetPcr()->HalReserved))->TSCHz;
  512. //
  513. // Initialize the reboot handler
  514. //
  515. HalpSetInternalVector(APIC_REBOOT_VECTOR,
  516. HalpApicRebootService,
  517. NULL,
  518. HIGH_LEVEL);
  519. HalpSetInternalVector(APIC_GENERIC_VECTOR,
  520. HalpBroadcastCallService,
  521. NULL,
  522. CLOCK2_LEVEL - 1);
  523. //
  524. // Initialize the clock for the processor that keeps
  525. // the system time. This uses a stub ISR until Phase 1
  526. //
  527. KiSetHandlerAddressToIDTIrql(APIC_CLOCK_VECTOR,
  528. HalpClockInterruptStub,
  529. NULL,
  530. CLOCK2_LEVEL);
  531. HalpVectorToINTI[APIC_CLOCK_VECTOR] = RTCInti;
  532. HalEnableSystemInterrupt(APIC_CLOCK_VECTOR, CLOCK2_LEVEL, HalpClockMode);
  533. //
  534. // Init timer watchdog if enabled.
  535. //
  536. HalpInitTimerWatchdog( Phase );
  537. HalpInitializeClock();
  538. #ifndef ACPI_HAL
  539. HalpRegisterVector (
  540. DeviceUsage | InterruptLatched,
  541. ADJUSTED_VECTOR(RTC_IRQ),
  542. APIC_CLOCK_VECTOR,
  543. HalpVectorToIRQL [APIC_CLOCK_VECTOR >> 4]
  544. );
  545. #endif
  546. //
  547. // Register NMI vector
  548. //
  549. HalpRegisterVector (
  550. InternalUsage,
  551. NMI_VECTOR,
  552. NMI_VECTOR,
  553. HIGH_LEVEL
  554. );
  555. //
  556. // Register spurious IDTs as in use
  557. //
  558. HalpRegisterVector (
  559. InternalUsage,
  560. APIC_SPURIOUS_VECTOR,
  561. APIC_SPURIOUS_VECTOR,
  562. HIGH_LEVEL
  563. );
  564. //
  565. // Initialize the profile interrupt vector.
  566. //
  567. KeSetProfileIrql(HIGH_LEVEL);
  568. HalStopProfileInterrupt(0);
  569. HalpSetInternalVector(APIC_PROFILE_VECTOR,
  570. HalpProfileInterrupt,
  571. NULL,
  572. PROFILE_LEVEL);
  573. //
  574. // Set performance interrupt vector
  575. //
  576. HalpSetInternalVector(APIC_PERF_VECTOR,
  577. HalpPerfInterrupt,
  578. NULL,
  579. PROFILE_LEVEL);
  580. //
  581. // Initialize the IPI, APC and DPC handlers. On AMD64, the
  582. // APC and DPC handling is done in the kernel.
  583. //
  584. #if !defined(_AMD64_)
  585. HalpSetInternalVector(DPC_VECTOR,
  586. HalpDispatchInterrupt,
  587. NULL,
  588. DISPATCH_LEVEL);
  589. HalpSetInternalVector(APC_VECTOR,
  590. HalpApcInterrupt,
  591. NULL,
  592. APC_LEVEL);
  593. #endif
  594. HalpSetInternalVector(APIC_IPI_VECTOR,
  595. HalpIpiHandler,
  596. NULL,
  597. IPI_LEVEL);
  598. //
  599. // HALMPS doesn't actually do address translation on a
  600. // bus. Register the quick version of FindBusAddressTranslation.
  601. //
  602. HALPDISPATCH->HalFindBusAddressTranslation =
  603. HalpFindBusAddressTranslation;
  604. //
  605. // Initialize spinlock used by HalGetBusData hardware access routines
  606. //
  607. KeInitializeSpinLock(&HalpSystemHardwareLock);
  608. //
  609. // Initialize data structures used to chain dma adapters
  610. // together for debugging purposes
  611. //
  612. KeInitializeSpinLock(&HalpDmaAdapterListLock);
  613. InitializeListHead(&HalpDmaAdapterList);
  614. #ifdef ACPI_HAL
  615. //
  616. // Initialize synchronzation event used to serialize
  617. // new adapter events on the ACPI HAL (which has no notion of bus
  618. // handlers)
  619. //
  620. KeInitializeEvent (&HalpNewAdapter, SynchronizationEvent, TRUE);
  621. #endif
  622. //
  623. // Determine if there is physical memory above 16 MB.
  624. //
  625. LessThan16Mb = TRUE;
  626. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  627. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  628. Descriptor = CONTAINING_RECORD( NextMd,
  629. MEMORY_ALLOCATION_DESCRIPTOR,
  630. ListEntry );
  631. if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
  632. Descriptor->MemoryType != LoaderSpecialMemory &&
  633. Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
  634. LessThan16Mb = FALSE;
  635. break;
  636. }
  637. NextMd = Descriptor->ListEntry.Flink;
  638. }
  639. #if !defined(_HALPAE_)
  640. HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
  641. //
  642. // Allocate map buffers for the adapter objects
  643. //
  644. HalpMapBufferPhysicalAddress.LowPart =
  645. HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
  646. HalpMapBufferSize >> PAGE_SHIFT, TRUE);
  647. HalpMapBufferPhysicalAddress.HighPart = 0;
  648. if (!HalpMapBufferPhysicalAddress.LowPart) {
  649. //
  650. // There was not a satisfactory block. Clear the allocation.
  651. //
  652. HalpMapBufferSize = 0;
  653. }
  654. #else
  655. //
  656. // Initialize and allocate map buffers for the 24bit master adapter
  657. // object.
  658. //
  659. MasterAdapter24.MaxBufferPages =
  660. MAXIMUM_ISA_MAP_BUFFER_SIZE / PAGE_SIZE;
  661. mapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
  662. mapBufferAddress =
  663. HalpAllocPhysicalMemory (LoaderBlock,
  664. MAXIMUM_PHYSICAL_ADDRESS,
  665. mapBufferSize >> PAGE_SHIFT,
  666. TRUE);
  667. if (mapBufferAddress == 0) {
  668. mapBufferSize = 0;
  669. }
  670. MasterAdapter24.MapBufferPhysicalAddress.LowPart = mapBufferAddress;
  671. MasterAdapter24.MapBufferPhysicalAddress.HighPart = 0;
  672. MasterAdapter24.MapBufferSize = mapBufferSize;
  673. if (HalPaeEnabled() != FALSE) {
  674. //
  675. // Initialize and allocate map buffers for the 32bit master adapter
  676. // object. This should only be needed on a PAE-enabled system.
  677. //
  678. MasterAdapter32.MaxBufferPages =
  679. MAXIMUM_PCI_MAP_BUFFER_SIZE / PAGE_SIZE;
  680. mapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
  681. mapBufferAddress =
  682. HalpAllocPhysicalMemory (LoaderBlock,
  683. (ULONG)-1,
  684. mapBufferSize >> PAGE_SHIFT,
  685. TRUE);
  686. if (mapBufferAddress == 0) {
  687. mapBufferSize = 0;
  688. }
  689. MasterAdapter32.MapBufferPhysicalAddress.LowPart = mapBufferAddress;
  690. MasterAdapter32.MapBufferPhysicalAddress.HighPart = 0;
  691. MasterAdapter32.MapBufferSize = mapBufferSize;
  692. }
  693. #endif
  694. //
  695. // Initialize and register a bug check callback record.
  696. //
  697. KeInitializeCallbackRecord(&HalpCallbackRecord);
  698. KeRegisterBugCheckCallback(&HalpCallbackRecord,
  699. HalpBugCheckCallback,
  700. NULL,
  701. 0,
  702. (PUCHAR)HalName);
  703. } else {
  704. //
  705. // Phase 1 initialization
  706. //
  707. pPCR = KeGetPcr();
  708. if (pPCR->Number == 0) {
  709. //
  710. // Back-pocket some PTEs for DMA during low mem
  711. //
  712. HalpInitReservedPages();
  713. #ifdef ACPI_HAL
  714. HalpInitNonBusHandler ();
  715. #else
  716. HalpRegisterInternalBusHandlers ();
  717. #endif
  718. #if defined(_AMD64_)
  719. //
  720. // Initialize the BIOS support subsystem
  721. //
  722. HalpInitializeBios();
  723. #endif
  724. //
  725. // Init timer watchdog if enabled (allocate snapshot buffer).
  726. //
  727. HalpInitTimerWatchdog( Phase );
  728. //
  729. // Initialize the clock for the processor
  730. // that keeps the system time.
  731. //
  732. KiSetHandlerAddressToIDTIrql(APIC_CLOCK_VECTOR,
  733. HalpClockInterrupt,
  734. NULL,
  735. CLOCK_LEVEL);
  736. //
  737. // Set initial feature bits
  738. //
  739. HalpFeatureBits = HalpGetFeatureBits();
  740. #if DBG_SPECIAL_IRQL
  741. //
  742. // Do Special IRQL initialization.
  743. //
  744. HalpInitializeSpecialIrqlSupport();
  745. #endif
  746. #if !defined(_WIN64)
  747. //
  748. // Point to new movnti routine if Movnti is detected
  749. //
  750. if(HalpFeatureBits & HAL_WNI_PRESENT) {
  751. HalpMoveMemory = HalpMovntiCopyBuffer;
  752. }
  753. #ifdef ACPI_HAL
  754. #ifdef NT_UP
  755. //
  756. // Perf counter patch for non-compliant ACPI machines
  757. //
  758. HalpAcpiTimerPerfCountHack();
  759. #endif
  760. #endif
  761. #endif
  762. #if defined(_AMD64_)
  763. //
  764. // Initialize per-processor profiling
  765. //
  766. HalpInitializeProfiling (pPCR->Number);
  767. #endif
  768. } else {
  769. //
  770. // Initialization needed only on non BSP processors
  771. //
  772. #ifdef SPEEDY_BOOT
  773. if (!HalpPmTimerScaleTimers())
  774. #endif
  775. HalpScaleTimers();
  776. //
  777. // Hack. Make all processors have the same value for
  778. // the timestamp counter frequency.
  779. //
  780. ((PHALPCR)(KeGetPcr()->HalReserved))->TSCHz = HalpProc0TSCHz;
  781. //
  782. // Initialize the clock for all other processors
  783. //
  784. KiSetHandlerAddressToIDTIrql(APIC_CLOCK_VECTOR,
  785. HalpClockInterruptPn,
  786. NULL,
  787. CLOCK_LEVEL);
  788. //
  789. // Reduce feature bits to be a subset
  790. //
  791. HalpFeatureBits &= HalpGetFeatureBits();
  792. #if defined(_AMD64_)
  793. //
  794. // Initialize per-processor profiling
  795. //
  796. HalpInitializeProfiling (pPCR->Number);
  797. #endif
  798. }
  799. }
  800. HalpInitMP (Phase, LoaderBlock);
  801. if (Phase == 1) {
  802. //
  803. // Enable system NMIs on Pn
  804. //
  805. HalpEnableNMI ();
  806. #ifdef TIMER_DBG
  807. HalInitialized = TRUE;
  808. #endif
  809. }
  810. return TRUE;
  811. }
  812. ULONG
  813. HalpGetFeatureBits (
  814. VOID
  815. )
  816. {
  817. UCHAR Buffer[50];
  818. ULONG Junk, ProcessorStepping, ProcessorFeatures, Bits;
  819. PULONG p1, p2;
  820. PUCHAR OrgRoutineAddress;
  821. PUCHAR MCERoutineAddress;
  822. ULONG newop;
  823. PKPRCB Prcb;
  824. Bits = 0;
  825. Prcb = KeGetCurrentPrcb();
  826. if (!Prcb->CpuID) {
  827. Bits |= HAL_NO_SPECULATION;
  828. return Bits;
  829. }
  830. //
  831. // Determine the processor type
  832. //
  833. HalpCpuID (0, &Junk, (PULONG) Buffer+0, (PULONG) Buffer+2, (PULONG) Buffer+1);
  834. Buffer[12] = 0;
  835. //
  836. // Determine which features are present
  837. //
  838. HalpCpuID (1, &ProcessorStepping, &Junk, &Junk, &ProcessorFeatures);
  839. if (ProcessorFeatures & CPUID_MCA_MASK) {
  840. Bits |= HAL_MCA_PRESENT;
  841. }
  842. if (ProcessorFeatures & CPUID_MCE_MASK) {
  843. Bits |= HAL_MCE_PRESENT;
  844. }
  845. if (ProcessorFeatures & CPUID_VME_MASK) {
  846. Bits |= HAL_CR4_PRESENT;
  847. }
  848. if(ProcessorFeatures & CPUID_WNI_MASK) {
  849. Bits |= HAL_WNI_PRESENT;
  850. }
  851. #if defined(_AMD64_)
  852. Bits |= HAL_PERF_EVENTS;
  853. #endif
  854. //
  855. // Check Intel feature bits for HAL features needed
  856. //
  857. #if !defined(_WIN64)
  858. if (strcmp (Buffer, HalpGenuineIntel) == 0) {
  859. if ((Prcb->CpuType == 6) || (Prcb->CpuType == 0xf)) {
  860. Bits |= HAL_PERF_EVENTS;
  861. }
  862. if (Prcb->CpuType < 6) {
  863. Bits |= HAL_NO_SPECULATION;
  864. }
  865. #ifndef NT_UP
  866. //
  867. // Check if IFU errata workaround is required
  868. //
  869. if (Prcb->Number == 0 && (Bits & HAL_MCA_PRESENT) &&
  870. ((ProcessorStepping & 0x700) == 0x600) &&
  871. ((ProcessorStepping & 0xF0) == 0x10) &&
  872. ((ProcessorStepping & 0xF) <= 0x7) ) {
  873. //
  874. // If the stepping is 617 or earlier, provide software workaround
  875. //
  876. p1 = (PULONG) (KeAcquireSpinLockRaiseToSynch);
  877. p2 = (PULONG) (KeAcquireSpinLockRaiseToSynchMCE);
  878. newop = (ULONG) p2 - (ULONG) p1 - 2; // compute offset
  879. ASSERT (newop < 0x7f); // verify within range
  880. newop = 0xeb | (newop << 8); // short-jmp
  881. *(p1) = newop; // patch it
  882. }
  883. #endif // NT_UP
  884. } else if (strcmp (Buffer, HalpAuthenticAMD) == 0) {
  885. ULONG ExtendedProcessorFeatures;
  886. ULONG MaxExtendedFunc;
  887. MaxExtendedFunc = 0;
  888. HalpCpuID (0x80000000, &MaxExtendedFunc, &Junk, &Junk, &Junk);
  889. if (MaxExtendedFunc >= 0x80000001) {
  890. HalpCpuID (0x80000001, &Junk, &Junk, &Junk, &ExtendedProcessorFeatures);
  891. if (ExtendedProcessorFeatures & CPUID_NX_MASK) {
  892. Bits |= HAL_NX_PRESENT;
  893. }
  894. }
  895. }
  896. #endif // _WIN64
  897. return Bits;
  898. }
  899. #if !defined(_WIN64)
  900. BOOLEAN
  901. HalpIsNXEnabled (
  902. VOID
  903. )
  904. /*++
  905. Routine Description:
  906. This function returns a boolean indicating whether the current processor
  907. has the no-execute bit set in the EFER MSR.
  908. Arguments:
  909. None.
  910. Return Value:
  911. A value of TRUE is returned indicates that the current processor has
  912. enabled NX mode, otherwise FALSE is returned.
  913. --*/
  914. {
  915. ULONGLONG msrValue;
  916. BOOLEAN result;
  917. result = FALSE;
  918. if ((HalpGetFeatureBits() & HAL_NX_PRESENT) != 0) {
  919. msrValue = RDMSR(0xc0000080);
  920. if ((msrValue & 0x800) != 0) {
  921. result = TRUE;
  922. }
  923. }
  924. return result;
  925. }
  926. #endif