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.

758 lines
18 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. xxhal.c
  5. Abstract:
  6. This module implements the initialization of the system dependent
  7. functions that define the Hardware Architecture Layer (HAL) for an
  8. x86 system.
  9. Author:
  10. David N. Cutler (davec) 25-Apr-1991
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "halp.h"
  16. ULONG HalpBusType;
  17. extern ADDRESS_USAGE HalpDefaultPcIoSpace;
  18. extern ADDRESS_USAGE HalpEisaIoSpace;
  19. extern UCHAR HalpSzPciLock[];
  20. extern UCHAR HalpSzBreak[];
  21. extern BOOLEAN HalpPciLockSettings;
  22. extern UCHAR HalpAuthenticAMD[];
  23. extern UCHAR HalpGenuineIntel[];
  24. extern PULONG KiEnableTimerWatchdog;
  25. extern ULONG HalpTimerWatchdogEnabled;
  26. extern PCHAR HalpTimerWatchdogStorage;
  27. extern PVOID HalpTimerWatchdogCurFrame;
  28. extern PVOID HalpTimerWatchdogLastFrame;
  29. extern ULONG HalpTimerWatchdogStorageOverflow;
  30. extern KSPIN_LOCK HalpDmaAdapterListLock;
  31. extern LIST_ENTRY HalpDmaAdapterList;
  32. #ifdef ACPI_HAL
  33. extern KEVENT HalpNewAdapter;
  34. #endif
  35. VOID
  36. HalpGetParameters (
  37. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  38. );
  39. ULONG
  40. HalpGetFeatureBits (
  41. VOID
  42. );
  43. VOID
  44. HalpInitReservedPages(
  45. VOID
  46. );
  47. VOID
  48. HalpAcpiTimerPerfCountHack(
  49. VOID
  50. );
  51. #ifndef NT_UP
  52. ULONG
  53. HalpInitMP(
  54. IN ULONG Phase,
  55. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  56. );
  57. #endif
  58. KSPIN_LOCK HalpSystemHardwareLock;
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text(INIT,HalpGetParameters)
  61. #pragma alloc_text(INIT,HalInitSystem)
  62. #endif
  63. VOID
  64. HalpGetParameters (
  65. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  66. )
  67. /*++
  68. Routine Description:
  69. This gets any parameters from the boot.ini invocation line.
  70. Arguments:
  71. None.
  72. Return Value:
  73. None
  74. --*/
  75. {
  76. PCHAR Options;
  77. if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
  78. Options = LoaderBlock->LoadOptions;
  79. //
  80. // Check if PCI settings are locked down
  81. //
  82. if (strstr(Options, HalpSzPciLock)) {
  83. HalpPciLockSettings = TRUE;
  84. }
  85. //
  86. // Has the user asked for an initial BreakPoint?
  87. //
  88. if (strstr(Options, HalpSzBreak)) {
  89. DbgBreakPoint();
  90. }
  91. }
  92. return;
  93. }
  94. VOID
  95. HalpInitTimerWatchdog(
  96. IN ULONG Phase
  97. )
  98. /*++
  99. Routine Description:
  100. Determines if the system is running on a GenuineIntel part and initializes
  101. HalpTimerWatchdogEnabled accordingly.
  102. Arguments:
  103. None.
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. if (Phase == 0) {
  109. ULONG GenuinePentiumOrLater = FALSE, Junk;
  110. PKPRCB Prcb;
  111. Prcb = KeGetCurrentPrcb();
  112. if (Prcb->CpuID) {
  113. UCHAR Buffer[50];
  114. //
  115. // Determine the processor type
  116. //
  117. HalpCpuID (0, &Junk, (PULONG) Buffer+0, (PULONG) Buffer+2, (PULONG) Buffer+1);
  118. Buffer[12] = 0;
  119. GenuinePentiumOrLater =
  120. ((strcmp(Buffer, HalpGenuineIntel) == 0) && (Prcb->CpuType >= 5));
  121. HalpTimerWatchdogEnabled = GenuinePentiumOrLater;
  122. }
  123. } else if (HalpTimerWatchdogEnabled) {
  124. //
  125. // Allocate 2 pages for stack snapshots, each snapshot is 64 DWORDs.
  126. //
  127. if (HalpTimerWatchdogStorage =
  128. ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE * 2, HAL_POOL_TAG )) {
  129. HalpTimerWatchdogLastFrame =
  130. HalpTimerWatchdogStorage + (PAGE_SIZE * 2 - 64*4);
  131. HalpTimerWatchdogStorageOverflow = 0;
  132. HalpTimerWatchdogCurFrame = HalpTimerWatchdogStorage;
  133. } else {
  134. HalpTimerWatchdogEnabled = FALSE;
  135. }
  136. }
  137. }
  138. BOOLEAN
  139. HalInitSystem (
  140. IN ULONG Phase,
  141. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  142. )
  143. /*++
  144. Routine Description:
  145. This function initializes the Hardware Architecture Layer (HAL) for an
  146. x86 system.
  147. Arguments:
  148. None.
  149. Return Value:
  150. A value of TRUE is returned is the initialization was successfully
  151. complete. Otherwise a value of FALSE is returend.
  152. --*/
  153. {
  154. PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
  155. PLIST_ENTRY NextMd;
  156. KIRQL CurrentIrql;
  157. PKPRCB pPRCB;
  158. ULONG mapBufferSize;
  159. ULONG mapBufferAddress;
  160. pPRCB = KeGetCurrentPrcb();
  161. if (Phase == 0) {
  162. HalpBusType = LoaderBlock->u.I386.MachineType & 0x00ff;
  163. HalpGetParameters (LoaderBlock);
  164. //
  165. // Verify Prcb version and build flags conform to
  166. // this image
  167. //
  168. #if DBG
  169. if (!(pPRCB->BuildType & PRCB_BUILD_DEBUG)) {
  170. // This checked hal requires a checked kernel
  171. KeBugCheckEx (MISMATCHED_HAL,
  172. 2, pPRCB->BuildType, PRCB_BUILD_DEBUG, 0);
  173. }
  174. #else
  175. if (pPRCB->BuildType & PRCB_BUILD_DEBUG) {
  176. // This free hal requires a free kernel
  177. KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
  178. }
  179. #endif
  180. #ifndef NT_UP
  181. if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
  182. // This MP hal requires an MP kernel
  183. KeBugCheckEx (MISMATCHED_HAL, 2, pPRCB->BuildType, 0, 0);
  184. }
  185. #endif
  186. if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
  187. KeBugCheckEx (MISMATCHED_HAL,
  188. 1, pPRCB->MajorVersion, PRCB_MAJOR_VERSION, 0);
  189. }
  190. //
  191. // Phase 0 initialization
  192. // only called by P0
  193. //
  194. //
  195. // Check to make sure the MCA HAL is not running on an ISA/EISA
  196. // system, and vice-versa.
  197. //
  198. #if MCA
  199. if (HalpBusType != MACHINE_TYPE_MCA) {
  200. KeBugCheckEx (MISMATCHED_HAL,
  201. 3, HalpBusType, MACHINE_TYPE_MCA, 0);
  202. }
  203. #else
  204. if (HalpBusType == MACHINE_TYPE_MCA) {
  205. KeBugCheckEx (MISMATCHED_HAL,
  206. 3, HalpBusType, 0, 0);
  207. }
  208. #endif
  209. #ifdef ACPI_HAL
  210. //
  211. // Make sure that this is really an ACPI machine and initialize
  212. // the ACPI structures.
  213. //
  214. HalpSetupAcpiPhase0(LoaderBlock);
  215. #endif
  216. HalpInitializePICs(TRUE);
  217. //
  218. // Now that the PICs are initialized, we need to mask them to
  219. // reflect the current Irql
  220. //
  221. CurrentIrql = KeGetCurrentIrql();
  222. CurrentIrql = KfRaiseIrql(CurrentIrql);
  223. //
  224. // Initialize CMOS
  225. //
  226. HalpInitializeCmos();
  227. //
  228. // Fill in handlers for APIs which this hal supports
  229. //
  230. HalQuerySystemInformation = HaliQuerySystemInformation;
  231. HalSetSystemInformation = HaliSetSystemInformation;
  232. HalInitPnpDriver = HaliInitPnpDriver;
  233. HalGetDmaAdapter = HaliGetDmaAdapter;
  234. HalHaltSystem = HaliHaltSystem;
  235. HalResetDisplay = HalpBiosDisplayReset;
  236. HalAllocateMapRegisters = HalpAllocateMapRegisters;
  237. #if !defined( HAL_SP )
  238. #ifdef ACPI_HAL
  239. HalGetInterruptTranslator = HalacpiGetInterruptTranslator;
  240. #else
  241. HalGetInterruptTranslator = HaliGetInterruptTranslator;
  242. #endif
  243. #endif
  244. #if !defined( HAL_SP ) && !(MCA)
  245. HalInitPowerManagement = HaliInitPowerManagement;
  246. HalLocateHiberRanges = HaliLocateHiberRanges;
  247. #endif
  248. //
  249. // Register cascade vector
  250. //
  251. HalpRegisterVector (
  252. InternalUsage,
  253. PIC_SLAVE_IRQ + PRIMARY_VECTOR_BASE,
  254. PIC_SLAVE_IRQ + PRIMARY_VECTOR_BASE,
  255. HIGH_LEVEL );
  256. //
  257. // Keep track of which IRQs are level triggered.
  258. //
  259. if (HalpBusType == MACHINE_TYPE_EISA) {
  260. HalpRecordEisaInterruptVectors();
  261. }
  262. //
  263. // Register base IO space used by hal
  264. //
  265. HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
  266. if (HalpBusType == MACHINE_TYPE_EISA) {
  267. HalpRegisterAddressUsage (&HalpEisaIoSpace);
  268. }
  269. //
  270. // Note that HalpInitializeClock MUST be called after
  271. // HalpInitializeStallExecution, because HalpInitializeStallExecution
  272. // reprograms the timer.
  273. //
  274. HalpInitializeStallExecution(0);
  275. //
  276. // Init timer watchdog if enabled.
  277. //
  278. HalpInitTimerWatchdog(Phase);
  279. //
  280. // Setup the clock
  281. //
  282. HalpInitializeClock();
  283. //
  284. // Make sure profile is disabled
  285. //
  286. HalStopProfileInterrupt(0);
  287. //
  288. // Remove this for the sake of the graphical boot driver. There is
  289. // no negative effect of this. If the display isn't initialized, it
  290. // will be initialized during HalDisplayString.
  291. //
  292. // HalpInitializeDisplay();
  293. //
  294. // Initialize spinlock used by HalGetBusData hardware access routines
  295. //
  296. KeInitializeSpinLock(&HalpSystemHardwareLock);
  297. //
  298. // Initialize data structures used to chain dma adapters
  299. // together for debugging purposes
  300. //
  301. KeInitializeSpinLock(&HalpDmaAdapterListLock);
  302. InitializeListHead(&HalpDmaAdapterList);
  303. #ifdef ACPI_HAL
  304. //
  305. // Initialize synchronzation event used to serialize
  306. // new adapter events on the ACPI HAL (which has no notion of bus
  307. // handlers)
  308. //
  309. KeInitializeEvent (&HalpNewAdapter, SynchronizationEvent, TRUE);
  310. #endif
  311. //
  312. // Determine if there is physical memory above 16 MB.
  313. //
  314. LessThan16Mb = TRUE;
  315. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  316. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  317. Descriptor = CONTAINING_RECORD( NextMd,
  318. MEMORY_ALLOCATION_DESCRIPTOR,
  319. ListEntry );
  320. if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
  321. Descriptor->MemoryType != LoaderSpecialMemory &&
  322. Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
  323. LessThan16Mb = FALSE;
  324. break;
  325. }
  326. NextMd = Descriptor->ListEntry.Flink;
  327. }
  328. #if !defined(_HALPAE_)
  329. HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
  330. //
  331. // Allocate map buffers for the adapter objects
  332. //
  333. HalpMapBufferPhysicalAddress.LowPart =
  334. HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
  335. HalpMapBufferSize >> PAGE_SHIFT, TRUE);
  336. HalpMapBufferPhysicalAddress.HighPart = 0;
  337. if (!HalpMapBufferPhysicalAddress.LowPart) {
  338. //
  339. // There was not a satisfactory block. Clear the allocation.
  340. //
  341. HalpMapBufferSize = 0;
  342. }
  343. #else
  344. //
  345. // Initialize and allocate map buffers for the 24bit master adapter
  346. // object.
  347. //
  348. MasterAdapter24.MaxBufferPages =
  349. MAXIMUM_ISA_MAP_BUFFER_SIZE / PAGE_SIZE;
  350. mapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
  351. mapBufferAddress =
  352. HalpAllocPhysicalMemory (LoaderBlock,
  353. MAXIMUM_PHYSICAL_ADDRESS,
  354. mapBufferSize >> PAGE_SHIFT,
  355. TRUE);
  356. if (mapBufferAddress == 0) {
  357. mapBufferSize = 0;
  358. }
  359. MasterAdapter24.MapBufferPhysicalAddress.LowPart = mapBufferAddress;
  360. MasterAdapter24.MapBufferPhysicalAddress.HighPart = 0;
  361. MasterAdapter24.MapBufferSize = mapBufferSize;
  362. if (HalPaeEnabled() != FALSE) {
  363. //
  364. // Initialize and allocate map buffers for the 32bit master adapter
  365. // object. This should only be needed on a PAE-enabled system.
  366. //
  367. MasterAdapter32.MaxBufferPages =
  368. MAXIMUM_PCI_MAP_BUFFER_SIZE / PAGE_SIZE;
  369. mapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
  370. mapBufferAddress =
  371. HalpAllocPhysicalMemory (LoaderBlock,
  372. (ULONG)-1,
  373. mapBufferSize >> PAGE_SHIFT,
  374. TRUE);
  375. if (mapBufferAddress == 0) {
  376. mapBufferSize = 0;
  377. }
  378. MasterAdapter32.MapBufferPhysicalAddress.LowPart = mapBufferAddress;
  379. MasterAdapter32.MapBufferPhysicalAddress.HighPart = 0;
  380. MasterAdapter32.MapBufferSize = mapBufferSize;
  381. }
  382. #endif
  383. } else {
  384. //
  385. // Phase 1 initialization
  386. //
  387. if (pPRCB->Number == 0) {
  388. //
  389. // Back-pocket some PTEs for DMA during low mem
  390. //
  391. HalpInitReservedPages();
  392. #ifndef ACPI_HAL
  393. //
  394. // If P0, then setup global vectors
  395. //
  396. HalpRegisterInternalBusHandlers ();
  397. #else
  398. HalpInitNonBusHandler();
  399. #endif
  400. //
  401. // Set feature bits
  402. //
  403. HalpFeatureBits = HalpGetFeatureBits();
  404. //
  405. // Use movnti routine to copy memory if Movnti support is detected
  406. //
  407. #if !defined(_WIN64)
  408. if (HalpFeatureBits & HAL_WNI_PRESENT) {
  409. HalpMoveMemory = HalpMovntiCopyBuffer;
  410. }
  411. #endif
  412. //
  413. // Init timer watchdog if enabled (allocate stack snapshot buffer).
  414. //
  415. HalpInitTimerWatchdog(Phase);
  416. HalpEnableInterruptHandler (
  417. DeviceUsage | InterruptLatched, // Report as device vector
  418. V2I (CLOCK_VECTOR), // Bus interrupt level
  419. CLOCK_VECTOR, // System IDT
  420. CLOCK2_LEVEL, // System Irql
  421. HalpClockInterrupt, // ISR
  422. Latched );
  423. HalpEnableInterruptHandler (
  424. DeviceUsage | InterruptLatched, // Report as device vector
  425. V2I (PROFILE_VECTOR), // Bus interrupt level
  426. PROFILE_VECTOR, // System IDT
  427. PROFILE_LEVEL, // System Irql
  428. HalpProfileInterrupt, // ISR
  429. Latched );
  430. #ifdef ACPI_HAL
  431. #if !defined(_WIN64)
  432. //
  433. // Perf counter patch for non-compliant ACPI machines
  434. //
  435. HalpAcpiTimerPerfCountHack();
  436. #endif
  437. #endif
  438. #if !defined(_WIN64)
  439. //
  440. // If 486, the FP error will be routed via trap10. So we
  441. // don't enable irq13. Otherwise (CPU=386), we will enable irq13
  442. // to handle FP error.
  443. //
  444. if (pPRCB->CpuType == 3) {
  445. HalpEnableInterruptHandler (
  446. DeviceUsage, // Report as device vector
  447. V2I (I386_80387_VECTOR), // Bus interrupt level
  448. I386_80387_VECTOR, // System IDT
  449. I386_80387_IRQL, // System Irql
  450. HalpIrq13Handler, // ISR
  451. Latched );
  452. }
  453. #endif
  454. }
  455. }
  456. #ifndef NT_UP
  457. HalpInitMP (Phase, LoaderBlock);
  458. #endif
  459. return TRUE;
  460. }
  461. ULONG
  462. HalpGetFeatureBits (
  463. VOID
  464. )
  465. {
  466. UCHAR Buffer[50];
  467. ULONG Junk, ProcessorFeatures, Bits;
  468. PKPRCB Prcb;
  469. ULONGLONG ApicBits;
  470. Bits = 0;
  471. Prcb = KeGetCurrentPrcb();
  472. if (!Prcb->CpuID) {
  473. Bits |= HAL_NO_SPECULATION;
  474. return Bits;
  475. }
  476. //
  477. // Determine the processor type
  478. //
  479. HalpCpuID (0, &Junk, (PULONG) Buffer+0, (PULONG) Buffer+2, (PULONG) Buffer+1);
  480. Buffer[12] = 0;
  481. HalpCpuID (1, &Junk, &Junk, &Junk, &ProcessorFeatures);
  482. //
  483. // Determine which features are present.
  484. //
  485. if (strcmp (Buffer, HalpGenuineIntel) == 0) {
  486. //
  487. // Check Intel feature bits for HAL features needed
  488. //
  489. if (Prcb->CpuType == 6) {
  490. Bits |= HAL_PERF_EVENTS;
  491. //
  492. // Workaround for Pentium Pro Local APIC trap 0x0F and trap 0x00
  493. // spurious interrupt errata 5AP and 6AP. Disable the Local APIC
  494. // on UP Pentium Pro Systems. Interrupts are routed directly from
  495. // 8259 PIC to CPU.
  496. //
  497. ApicBits = RDMSR(APIC_BASE_MSR);
  498. if (ApicBits & APIC_ENABLED) {
  499. //
  500. // Local APIC is enabled - Disable it.
  501. //
  502. WRMSR(APIC_BASE_MSR, (ApicBits & ~APIC_ENABLED));
  503. }
  504. }
  505. if (Prcb->CpuType < 6) {
  506. Bits |= HAL_NO_SPECULATION;
  507. }
  508. } else if (strcmp (Buffer, HalpAuthenticAMD) == 0) {
  509. ULONG ExtendedProcessorFeatures;
  510. ULONG MaxExtendedFunc;
  511. MaxExtendedFunc = 0;
  512. HalpCpuID (0x80000000, &MaxExtendedFunc, &Junk, &Junk, &Junk);
  513. if (MaxExtendedFunc >= 0x80000001) {
  514. HalpCpuID (0x80000001, &Junk, &Junk, &Junk, &ExtendedProcessorFeatures);
  515. if (ExtendedProcessorFeatures & CPUID_NX_MASK) {
  516. Bits |= HAL_NX_PRESENT;
  517. }
  518. }
  519. }
  520. if (ProcessorFeatures & CPUID_MCA_MASK) {
  521. Bits |= HAL_MCA_PRESENT;
  522. }
  523. if (ProcessorFeatures & CPUID_MCE_MASK) {
  524. Bits |= HAL_MCE_PRESENT;
  525. }
  526. if (ProcessorFeatures & CPUID_VME_MASK) {
  527. Bits |= HAL_CR4_PRESENT;
  528. }
  529. if (ProcessorFeatures & CPUID_WNI_MASK) {
  530. Bits |= HAL_WNI_PRESENT;
  531. }
  532. return Bits;
  533. }
  534. #if !defined(_WIN64)
  535. BOOLEAN
  536. HalpIsNXEnabled (
  537. VOID
  538. )
  539. /*++
  540. Routine Description:
  541. This function returns a boolean indicating whether the current processor
  542. has the no-execute bit set in the EFER MSR.
  543. Arguments:
  544. None.
  545. Return Value:
  546. A value of TRUE is returned indicates that the current processor has
  547. enabled NX mode, otherwise FALSE is returned.
  548. --*/
  549. {
  550. ULONGLONG msrValue;
  551. BOOLEAN result;
  552. result = FALSE;
  553. if ((HalpGetFeatureBits() & HAL_NX_PRESENT) != 0) {
  554. msrValue = RDMSR(0xc0000080);
  555. if ((msrValue & 0x800) != 0) {
  556. result = TRUE;
  557. }
  558. }
  559. return result;
  560. }
  561. #endif