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.

515 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997 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. mpprocst.c
  12. Abstract:
  13. This code has been moved from mpsproc.c so that it
  14. can be included from both the MPS hal and the ACPI hal.
  15. Author:
  16. Ken Reneris (kenr) 22-Jan-1991
  17. Environment:
  18. Kernel mode only.
  19. Revision History:
  20. Ron Mosgrove (Intel) - Modified to support the PC+MP
  21. Jake Oshins (jakeo) - moved from mpsproc.c
  22. --*/
  23. #include "halp.h"
  24. #include "pcmp_nt.inc"
  25. #include "apic.inc"
  26. #include "stdio.h"
  27. VOID
  28. HalpMapCR3 (
  29. IN ULONG VirtAddress,
  30. IN PHYSICAL_ADDRESS PhysicalAddress,
  31. IN ULONG Length
  32. );
  33. ULONG
  34. HalpBuildTiledCR3 (
  35. IN PKPROCESSOR_STATE ProcessorState
  36. );
  37. VOID
  38. HalpFreeTiledCR3 (
  39. VOID
  40. );
  41. VOID
  42. StartPx_PMStub (
  43. VOID
  44. );
  45. ULONG
  46. HalpBuildTiledCR3Ex (
  47. IN PKPROCESSOR_STATE ProcessorState,
  48. IN ULONG ProcNum
  49. );
  50. VOID
  51. HalpMapCR3Ex (
  52. IN ULONG VirtAddress,
  53. IN PHYSICAL_ADDRESS PhysicalAddress,
  54. IN ULONG Length,
  55. IN ULONG ProcNum
  56. );
  57. VOID
  58. HalpFreeTiledCR3Ex (
  59. ULONG ProcNum
  60. );
  61. #define MAX_PT 16
  62. PVOID HiberFreeCR3[MAX_PROCESSORS][MAX_PT]; // remember pool memory to free
  63. PVOID HalpLowStubPhysicalAddress; // pointer to low memory bootup stub
  64. PUCHAR HalpLowStub; // pointer to low memory bootup stub
  65. #ifdef ALLOC_PRAGMA
  66. #pragma alloc_text(PAGELK,HalpBuildTiledCR3)
  67. #pragma alloc_text(PAGELK,HalpMapCR3)
  68. #pragma alloc_text(PAGELK,HalpFreeTiledCR3)
  69. #pragma alloc_text(PAGELK,HalpBuildTiledCR3Ex)
  70. #pragma alloc_text(PAGELK,HalpMapCR3Ex)
  71. #pragma alloc_text(PAGELK,HalpFreeTiledCR3Ex)
  72. #endif
  73. #define PTES_PER_PAGE (PAGE_SIZE / HalPteSize())
  74. PHARDWARE_PTE
  75. GetPdeAddressEx(
  76. ULONG Va,
  77. ULONG ProcessorNumber
  78. )
  79. {
  80. PHARDWARE_PTE pageDirectories;
  81. PHARDWARE_PTE pageDirectoryEntry;
  82. ULONG pageDirectoryIndex;
  83. pageDirectories = (PHARDWARE_PTE)(HiberFreeCR3[ ProcessorNumber ][0]);
  84. if (HalPaeEnabled() != FALSE) {
  85. //
  86. // Skip over the first page, which contains the page directory pointer
  87. // table.
  88. //
  89. HalpAdvancePte( &pageDirectories, PTES_PER_PAGE );
  90. }
  91. pageDirectoryIndex = Va >> MiGetPdiShift();
  92. //
  93. // Note that in the case of PAE, pageDirectoryIndex includes the PDPT
  94. // bits. This works because we know that the four page directory tables
  95. // are adjacent.
  96. //
  97. pageDirectoryEntry = HalpIndexPteArray( pageDirectories,
  98. pageDirectoryIndex );
  99. return pageDirectoryEntry;
  100. }
  101. PHARDWARE_PTE
  102. GetPteAddress(
  103. IN ULONG Va,
  104. IN PHARDWARE_PTE PageTable
  105. )
  106. {
  107. PHARDWARE_PTE pointerPte;
  108. ULONG index;
  109. index = MiGetPteIndex( (PVOID)Va );
  110. pointerPte = HalpIndexPteArray( PageTable, index );
  111. return pointerPte;
  112. }
  113. ULONG
  114. HalpBuildTiledCR3 (
  115. IN PKPROCESSOR_STATE ProcessorState
  116. )
  117. /*++
  118. Routine Description:
  119. When the x86 processor is reset it starts in real-mode.
  120. In order to move the processor from real-mode to protected
  121. mode with flat addressing the segment which loads CR0 needs
  122. to have its linear address mapped to the physical
  123. location of the segment for said instruction so the
  124. processor can continue to execute the following instruction.
  125. This function is called to build such a tiled page directory.
  126. In addition, other flat addresses are tiled to match the
  127. current running flat address for the new state. Once the
  128. processor is in flat mode, we move to a NT tiled page which
  129. can then load up the remaining processor state.
  130. Arguments:
  131. ProcessorState - The state the new processor should start in.
  132. Return Value:
  133. Physical address of Tiled page directory
  134. --*/
  135. {
  136. return(HalpBuildTiledCR3Ex(ProcessorState,0));
  137. }
  138. ULONG
  139. HalpBuildTiledCR3Ex (
  140. IN PKPROCESSOR_STATE ProcessorState,
  141. IN ULONG ProcNum
  142. )
  143. /*++
  144. Routine Description:
  145. When the x86 processor is reset it starts in real-mode.
  146. In order to move the processor from real-mode to protected
  147. mode with flat addressing the segment which loads CR0 needs
  148. to have its linear address mapped to machine the physical
  149. location of the segment for said instruction so the
  150. processor can continue to execute the following instruction.
  151. This function is called to build such a tiled page directory.
  152. In addition, other flat addresses are tiled to match the
  153. current running flat address for the new state. Once the
  154. processor is in flat mode, we move to a NT tiled page which
  155. can then load up the remaining processor state.
  156. Arguments:
  157. ProcessorState - The state the new processor should start in.
  158. Return Value:
  159. Physical address of Tiled page directory
  160. --*/
  161. {
  162. ULONG allocationSize;
  163. PHARDWARE_PTE pte;
  164. PHARDWARE_PTE pdpt;
  165. PHARDWARE_PTE pdpte;
  166. PHARDWARE_PTE pageDirectory;
  167. PHYSICAL_ADDRESS physicalAddress;
  168. ULONG i;
  169. if (HalPaeEnabled() != FALSE) {
  170. //
  171. // Need 5 pages for PAE mode: one for the page directory pointer
  172. // table and one for each of the four page directories. Note that
  173. // only the single PDPT page really needs to come from memory below 4GB
  174. // physical.
  175. //
  176. allocationSize = PAGE_SIZE * 5;
  177. physicalAddress.HighPart = 0;
  178. physicalAddress.LowPart = 0xffffffff;
  179. HiberFreeCR3[ProcNum][0] =
  180. MmAllocateContiguousMemory (allocationSize, physicalAddress);
  181. } else {
  182. //
  183. // Just one page for the page directory.
  184. //
  185. allocationSize = PAGE_SIZE;
  186. HiberFreeCR3[ProcNum][0] =
  187. ExAllocatePoolWithTag (NonPagedPool, allocationSize, HAL_POOL_TAG);
  188. }
  189. if (!HiberFreeCR3[ProcNum][0]) {
  190. // Failed to allocate memory.
  191. return 0;
  192. }
  193. RtlZeroMemory (HiberFreeCR3[ProcNum][0], allocationSize);
  194. if (HalPaeEnabled() != FALSE) {
  195. //
  196. // Initialize each of the four page directory pointer table entries
  197. //
  198. pdpt = (PHARDWARE_PTE)HiberFreeCR3[ProcNum][0];
  199. pageDirectory = pdpt;
  200. for (i = 0; i < 4; i++) {
  201. //
  202. // Get a pointer to the page directory pointer table entry
  203. //
  204. pdpte = HalpIndexPteArray( pdpt, i );
  205. //
  206. // Skip to the first (next) page directory.
  207. //
  208. HalpAdvancePte( &pageDirectory, PTES_PER_PAGE );
  209. //
  210. // Find its physical address and update the page directory pointer
  211. // table entry.
  212. //
  213. physicalAddress = MmGetPhysicalAddress( pageDirectory );
  214. pdpte->Valid = 1;
  215. HalpSetPageFrameNumber( pdpte,
  216. physicalAddress.QuadPart >> PAGE_SHIFT );
  217. }
  218. }
  219. //
  220. // Map page for real mode stub (one page)
  221. //
  222. HalpMapCR3Ex ((ULONG) HalpLowStubPhysicalAddress,
  223. HalpPtrToPhysicalAddress( HalpLowStubPhysicalAddress ),
  224. PAGE_SIZE,
  225. ProcNum);
  226. //
  227. // Map page for protect mode stub (one page)
  228. //
  229. HalpMapCR3Ex ((ULONG) &StartPx_PMStub,
  230. HalpPtrToPhysicalAddress( NULL ),
  231. PAGE_SIZE,
  232. ProcNum);
  233. //
  234. // Map page(s) for processors GDT
  235. //
  236. HalpMapCR3Ex (ProcessorState->SpecialRegisters.Gdtr.Base,
  237. HalpPtrToPhysicalAddress( NULL ),
  238. ProcessorState->SpecialRegisters.Gdtr.Limit,
  239. ProcNum);
  240. //
  241. // Map page(s) for processors IDT
  242. //
  243. HalpMapCR3Ex (ProcessorState->SpecialRegisters.Idtr.Base,
  244. HalpPtrToPhysicalAddress( NULL ),
  245. ProcessorState->SpecialRegisters.Idtr.Limit,
  246. ProcNum);
  247. ASSERT (MmGetPhysicalAddress (HiberFreeCR3[ProcNum][0]).HighPart == 0);
  248. return MmGetPhysicalAddress (HiberFreeCR3[ProcNum][0]).LowPart;
  249. }
  250. VOID
  251. HalpMapCR3 (
  252. IN ULONG VirtAddress,
  253. IN PHYSICAL_ADDRESS PhysicalAddress,
  254. IN ULONG Length
  255. )
  256. /*++
  257. Routine Description:
  258. Called to build a page table entry for the passed page
  259. directory. Used to build a tiled page directory with
  260. real-mode & flat mode.
  261. Arguments:
  262. VirtAddress - Current virtual address
  263. PhysicalAddress - Optional. Physical address to be mapped
  264. to, if passed as a NULL then the physical
  265. address of the passed virtual address
  266. is assumed.
  267. Length - number of bytes to map
  268. Return Value:
  269. none.
  270. --*/
  271. {
  272. HalpMapCR3Ex(VirtAddress,PhysicalAddress,Length,0);
  273. }
  274. VOID
  275. HalpMapCR3Ex (
  276. IN ULONG VirtAddress,
  277. IN PHYSICAL_ADDRESS PhysicalAddress,
  278. IN ULONG Length,
  279. IN ULONG ProcNum
  280. )
  281. /*++
  282. Routine Description:
  283. Called to build a page table entry for the passed page
  284. directory. Used to build a tiled page directory with
  285. real-mode & flat mode.
  286. Arguments:
  287. VirtAddress - Current virtual address
  288. PhysicalAddress - Optional. Physical address to be mapped
  289. to, if passed as a NULL then the physical
  290. address of the passed virtual address
  291. is assumed.
  292. Length - number of bytes to map
  293. Return Value:
  294. none.
  295. --*/
  296. {
  297. ULONG i;
  298. PHARDWARE_PTE PTE;
  299. PVOID pPageTable;
  300. PHYSICAL_ADDRESS pPhysicalPage;
  301. while (Length) {
  302. PTE = GetPdeAddressEx (VirtAddress,ProcNum);
  303. if (HalpIsPteFree( PTE ) != FALSE) {
  304. pPageTable = ExAllocatePoolWithTag(NonPagedPool,
  305. PAGE_SIZE,
  306. HAL_POOL_TAG);
  307. if (!pPageTable) {
  308. //
  309. // This allocation is critical.
  310. //
  311. KeBugCheckEx(HAL_MEMORY_ALLOCATION,
  312. PAGE_SIZE,
  313. 6,
  314. (ULONG)__FILE__,
  315. __LINE__
  316. );
  317. }
  318. RtlZeroMemory (pPageTable, PAGE_SIZE);
  319. for (i=0; i < MAX_PT; i++) {
  320. if (!(HiberFreeCR3[ProcNum][i])) {
  321. HiberFreeCR3[ProcNum][i] = pPageTable;
  322. break;
  323. }
  324. }
  325. ASSERT (i < MAX_PT);
  326. pPhysicalPage = MmGetPhysicalAddress (pPageTable);
  327. HalpSetPageFrameNumber( PTE, pPhysicalPage.QuadPart >> PAGE_SHIFT );
  328. PTE->Valid = 1;
  329. PTE->Write = 1;
  330. }
  331. pPhysicalPage.QuadPart =
  332. HalpGetPageFrameNumber( PTE ) << PAGE_SHIFT;
  333. pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
  334. PTE = GetPteAddress (VirtAddress, pPageTable);
  335. if (PhysicalAddress.QuadPart == 0) {
  336. PhysicalAddress = MmGetPhysicalAddress((PVOID)VirtAddress);
  337. }
  338. HalpSetPageFrameNumber( PTE, PhysicalAddress.QuadPart >> PAGE_SHIFT );
  339. PTE->Valid = 1;
  340. PTE->Write = 1;
  341. MmUnmapIoSpace (pPageTable, PAGE_SIZE);
  342. PhysicalAddress.QuadPart = 0;
  343. VirtAddress += PAGE_SIZE;
  344. if (Length > PAGE_SIZE) {
  345. Length -= PAGE_SIZE;
  346. } else {
  347. Length = 0;
  348. }
  349. }
  350. }
  351. VOID
  352. HalpFreeTiledCR3 (
  353. VOID
  354. )
  355. /*++
  356. Routine Description:
  357. Frees any memory allocated when the tiled page directory
  358. was built.
  359. Arguments:
  360. none
  361. Return Value:
  362. none
  363. --*/
  364. {
  365. HalpFreeTiledCR3Ex(0);
  366. }
  367. VOID
  368. HalpFreeTiledCR3Ex (
  369. ULONG ProcNum
  370. )
  371. /*++
  372. Routine Description:
  373. Frees any memory allocated when the tiled page directory
  374. was built.
  375. Arguments:
  376. none
  377. Return Value:
  378. none
  379. --*/
  380. {
  381. ULONG i;
  382. for (i = 0; HiberFreeCR3[ProcNum][i]; i++) {
  383. //
  384. // Only the very first entry for each processor might have been
  385. // allocated via MmAllocateContiguousMemory. So only this one can
  386. // (and MUST) be freed via MmFreeContiguousMemory.
  387. //
  388. if ((i == 0) && (HalPaeEnabled() != FALSE)) {
  389. MmFreeContiguousMemory (HiberFreeCR3[ProcNum][i]);
  390. }
  391. else {
  392. ExFreePool (HiberFreeCR3[ProcNum][i]);
  393. }
  394. HiberFreeCR3[ProcNum][i] = 0;
  395. }
  396. }