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.

913 lines
22 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_PTR 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. #if defined(_AMD64_)
  42. VOID
  43. HalpLMStub (
  44. VOID
  45. );
  46. #endif
  47. VOID
  48. StartPx_PMStub (
  49. VOID
  50. );
  51. ULONG
  52. HalpBuildTiledCR3Ex (
  53. IN PKPROCESSOR_STATE ProcessorState,
  54. IN ULONG ProcNum
  55. );
  56. VOID
  57. HalpMapCR3Ex (
  58. IN ULONG_PTR VirtAddress,
  59. IN PHYSICAL_ADDRESS PhysicalAddress,
  60. IN ULONG Length,
  61. IN ULONG ProcNum
  62. );
  63. #if defined(_AMD64_)
  64. VOID
  65. HalpCommitCR3 (
  66. ULONG ProcNum
  67. );
  68. VOID
  69. HalpCommitCR3Worker (
  70. PVOID *PageTable,
  71. ULONG Level
  72. );
  73. #endif
  74. VOID
  75. HalpFreeTiledCR3Ex (
  76. ULONG ProcNum
  77. );
  78. VOID
  79. HalpFreeTiledCR3WorkRoutine(
  80. IN PVOID pWorkItem
  81. );
  82. VOID
  83. HalpFreeTiledCR3Worker(
  84. ULONG ProcNum
  85. );
  86. #define MAX_PT 16
  87. PVOID HiberFreeCR3[MAX_PROCESSORS][MAX_PT]; // remember pool memory to free
  88. #define HiberFreeCR3Page(p,i) \
  89. (PVOID)((ULONG_PTR)HiberFreeCR3[p][i] & ~(ULONG_PTR)1)
  90. PVOID HalpLowStubPhysicalAddress; // pointer to low memory bootup stub
  91. PUCHAR HalpLowStub; // pointer to low memory bootup stub
  92. #ifdef ALLOC_PRAGMA
  93. #pragma alloc_text(PAGELK,HalpBuildTiledCR3)
  94. #pragma alloc_text(PAGELK,HalpMapCR3)
  95. #pragma alloc_text(PAGELK,HalpFreeTiledCR3)
  96. #pragma alloc_text(PAGELK,HalpBuildTiledCR3Ex)
  97. #pragma alloc_text(PAGELK,HalpMapCR3Ex)
  98. #pragma alloc_text(PAGELK,HalpFreeTiledCR3Ex)
  99. #if defined(_AMD64_)
  100. #pragma alloc_text(PAGELK,HalpCommitCR3)
  101. #pragma alloc_text(PAGELK,HalpCommitCR3Worker)
  102. #endif
  103. #endif
  104. #define PTES_PER_PAGE (PAGE_SIZE / HalPteSize())
  105. #if !defined(_AMD64_)
  106. PHARDWARE_PTE
  107. GetPdeAddressEx(
  108. ULONG_PTR Va,
  109. ULONG ProcessorNumber
  110. )
  111. {
  112. PHARDWARE_PTE pageDirectories;
  113. PHARDWARE_PTE pageDirectoryEntry;
  114. ULONG pageDirectoryIndex;
  115. pageDirectories = (PHARDWARE_PTE)(HiberFreeCR3Page(ProcessorNumber,0));
  116. if (HalPaeEnabled() != FALSE) {
  117. //
  118. // Skip over the first page, which contains the page directory pointer
  119. // table.
  120. //
  121. HalpAdvancePte( &pageDirectories, PTES_PER_PAGE );
  122. }
  123. pageDirectoryIndex = (ULONG)(Va >> MiGetPdiShift());
  124. //
  125. // Note that in the case of PAE, pageDirectoryIndex includes the PDPT
  126. // bits. This works because we know that the four page directory tables
  127. // are adjacent.
  128. //
  129. pageDirectoryEntry = HalpIndexPteArray( pageDirectories,
  130. pageDirectoryIndex );
  131. return pageDirectoryEntry;
  132. }
  133. PHARDWARE_PTE
  134. GetPteAddress(
  135. IN ULONG_PTR Va,
  136. IN PHARDWARE_PTE PageTable
  137. )
  138. {
  139. PHARDWARE_PTE pointerPte;
  140. ULONG index;
  141. index = (ULONG)MiGetPteIndex( (PVOID)Va );
  142. pointerPte = HalpIndexPteArray( PageTable, index );
  143. return pointerPte;
  144. }
  145. #endif
  146. ULONG
  147. HalpBuildTiledCR3 (
  148. IN PKPROCESSOR_STATE ProcessorState
  149. )
  150. /*++
  151. Routine Description:
  152. When the x86 processor is reset it starts in real-mode.
  153. In order to move the processor from real-mode to protected
  154. mode with flat addressing the segment which loads CR0 needs
  155. to have its linear address mapped to the physical
  156. location of the segment for said instruction so the
  157. processor can continue to execute the following instruction.
  158. This function is called to build such a tiled page directory.
  159. In addition, other flat addresses are tiled to match the
  160. current running flat address for the new state. Once the
  161. processor is in flat mode, we move to a NT tiled page which
  162. can then load up the remaining processor state.
  163. Arguments:
  164. ProcessorState - The state the new processor should start in.
  165. Return Value:
  166. Physical address of Tiled page directory
  167. --*/
  168. {
  169. return(HalpBuildTiledCR3Ex(ProcessorState,0));
  170. }
  171. VOID
  172. HalpStoreFreeCr3 (
  173. IN ULONG ProcNum,
  174. IN PVOID Page,
  175. IN BOOLEAN FreeContiguous
  176. )
  177. {
  178. ULONG index;
  179. PVOID page;
  180. page = Page;
  181. //
  182. // Remember whether this page should be freed via MmFreeContiguousMemory()
  183. // or ExFreePool();
  184. //
  185. if (FreeContiguous != FALSE) {
  186. //
  187. // Set the low bit to indicate that this page must be freed
  188. // via MmFreeContiguousMemory()
  189. //
  190. (ULONG_PTR)page |= 1;
  191. }
  192. for (index = 0; index < MAX_PT; index += 1) {
  193. if (HiberFreeCR3[ProcNum][index] == NULL) {
  194. HiberFreeCR3[ProcNum][index] = page;
  195. break;
  196. }
  197. }
  198. ASSERT(index < MAX_PT);
  199. }
  200. ULONG
  201. HalpBuildTiledCR3Ex (
  202. IN PKPROCESSOR_STATE ProcessorState,
  203. IN ULONG ProcNum
  204. )
  205. /*++
  206. Routine Description:
  207. When the x86 processor is reset it starts in real-mode.
  208. In order to move the processor from real-mode to protected
  209. mode with flat addressing the segment which loads CR0 needs
  210. to have its linear address mapped to machine the physical
  211. location of the segment for said instruction so the
  212. processor can continue to execute the following instruction.
  213. This function is called to build such a tiled page directory.
  214. In addition, other flat addresses are tiled to match the
  215. current running flat address for the new state. Once the
  216. processor is in flat mode, we move to a NT tiled page which
  217. can then load up the remaining processor state.
  218. Arguments:
  219. ProcessorState - The state the new processor should start in.
  220. Return Value:
  221. Physical address of Tiled page directory
  222. --*/
  223. {
  224. ULONG allocationSize;
  225. PHARDWARE_PTE pte;
  226. PHARDWARE_PTE pdpt;
  227. PHARDWARE_PTE pdpte;
  228. PHARDWARE_PTE pageDirectory;
  229. PHYSICAL_ADDRESS physicalAddress;
  230. ULONG i;
  231. PVOID pageTable;
  232. BOOLEAN contigMemory;
  233. contigMemory = FALSE;
  234. #if defined(_AMD64_)
  235. //
  236. // Need a single level 4 page to reside below 4G.
  237. //
  238. allocationSize = PAGE_SIZE;
  239. physicalAddress.HighPart = 0;
  240. physicalAddress.LowPart = 0xffffffff;
  241. pageTable = MmAllocateContiguousMemory (allocationSize, physicalAddress);
  242. contigMemory = TRUE;
  243. #else
  244. if (HalPaeEnabled() != FALSE) {
  245. //
  246. // Need 5 pages for PAE mode: one for the page directory pointer
  247. // table and one for each of the four page directories. Note that
  248. // only the single PDPT page really needs to come from memory below 4GB
  249. // physical.
  250. //
  251. allocationSize = PAGE_SIZE * 5;
  252. physicalAddress.HighPart = 0;
  253. physicalAddress.LowPart = 0xffffffff;
  254. pageTable = MmAllocateContiguousMemory (allocationSize, physicalAddress);
  255. contigMemory = TRUE;
  256. } else {
  257. //
  258. // Just one page for the page directory.
  259. //
  260. allocationSize = PAGE_SIZE;
  261. pageTable = ExAllocatePoolWithTag (NonPagedPool, allocationSize, HAL_POOL_TAG);
  262. }
  263. #endif
  264. if (!pageTable) {
  265. // Failed to allocate memory.
  266. return 0;
  267. }
  268. //
  269. // Remember to free this page table when the process is complete.
  270. //
  271. HalpStoreFreeCr3(ProcNum,pageTable,contigMemory);
  272. RtlZeroMemory (pageTable, allocationSize);
  273. #if !defined(_AMD64_)
  274. if (HalPaeEnabled() != FALSE) {
  275. //
  276. // Initialize each of the four page directory pointer table entries
  277. //
  278. pdpt = (PHARDWARE_PTE)pageTable;
  279. pageDirectory = pdpt;
  280. for (i = 0; i < 4; i++) {
  281. //
  282. // Get a pointer to the page directory pointer table entry
  283. //
  284. pdpte = HalpIndexPteArray( pdpt, i );
  285. //
  286. // Skip to the first (next) page directory.
  287. //
  288. HalpAdvancePte( &pageDirectory, PTES_PER_PAGE );
  289. //
  290. // Find its physical address and update the page directory pointer
  291. // table entry.
  292. //
  293. physicalAddress = MmGetPhysicalAddress( pageDirectory );
  294. pdpte->Valid = 1;
  295. HalpSetPageFrameNumber( pdpte,
  296. physicalAddress.QuadPart >> PAGE_SHIFT );
  297. }
  298. }
  299. #endif // _AMD64_
  300. //
  301. // Map page for real mode stub (one page)
  302. //
  303. HalpMapCR3Ex ((ULONG_PTR) HalpLowStubPhysicalAddress,
  304. HalpPtrToPhysicalAddress( HalpLowStubPhysicalAddress ),
  305. PAGE_SIZE,
  306. ProcNum);
  307. #if defined(_AMD64_)
  308. //
  309. // Map page for long mode stub (one page)
  310. //
  311. HalpMapCR3Ex ((ULONG64) &HalpLMStub,
  312. HalpPtrToPhysicalAddress( NULL ),
  313. PAGE_SIZE,
  314. ProcNum);
  315. #else // _AMD64_
  316. //
  317. // Map page for protect mode stub (one page)
  318. //
  319. HalpMapCR3Ex ((ULONG_PTR) &StartPx_PMStub,
  320. HalpPtrToPhysicalAddress( NULL ),
  321. PAGE_SIZE,
  322. ProcNum);
  323. //
  324. // Map page(s) for processors GDT
  325. //
  326. HalpMapCR3Ex ((ULONG_PTR)ProcessorState->SpecialRegisters.Gdtr.Base,
  327. HalpPtrToPhysicalAddress( NULL ),
  328. ProcessorState->SpecialRegisters.Gdtr.Limit,
  329. ProcNum);
  330. //
  331. // Map page(s) for processors IDT
  332. //
  333. HalpMapCR3Ex ((ULONG_PTR)ProcessorState->SpecialRegisters.Idtr.Base,
  334. HalpPtrToPhysicalAddress( NULL ),
  335. ProcessorState->SpecialRegisters.Idtr.Limit,
  336. ProcNum);
  337. #endif // _AMD64_
  338. #if defined(_AMD64_)
  339. //
  340. // Commit the mapping structures
  341. //
  342. HalpCommitCR3 (ProcNum);
  343. #endif
  344. ASSERT (MmGetPhysicalAddress (pageTable).HighPart == 0);
  345. return MmGetPhysicalAddress (pageTable).LowPart;
  346. }
  347. VOID
  348. HalpMapCR3 (
  349. IN ULONG_PTR VirtAddress,
  350. IN PHYSICAL_ADDRESS PhysicalAddress,
  351. IN ULONG Length
  352. )
  353. /*++
  354. Routine Description:
  355. Called to build a page table entry for the passed page
  356. directory. Used to build a tiled page directory with
  357. real-mode & flat mode.
  358. Arguments:
  359. VirtAddress - Current virtual address
  360. PhysicalAddress - Optional. Physical address to be mapped
  361. to, if passed as a NULL then the physical
  362. address of the passed virtual address
  363. is assumed.
  364. Length - number of bytes to map
  365. Return Value:
  366. none.
  367. --*/
  368. {
  369. HalpMapCR3Ex(VirtAddress,PhysicalAddress,Length,0);
  370. }
  371. #if defined(_AMD64_)
  372. VOID
  373. HalpMapCR3Ex (
  374. IN ULONG_PTR VirtAddress,
  375. IN PHYSICAL_ADDRESS PhysicalAddress,
  376. IN ULONG Length,
  377. IN ULONG ProcNum
  378. )
  379. /*++
  380. Routine Description:
  381. Called to build a page table entry for the passed page
  382. directory. Used to build a tiled page directory with
  383. real-mode & flat mode.
  384. Arguments:
  385. VirtAddress - Current virtual address
  386. PhysicalAddress - Optional. Physical address to be mapped
  387. to, if passed as a NULL then the physical
  388. address of the passed virtual address
  389. is assumed.
  390. Length - number of bytes to map
  391. Return Value:
  392. none.
  393. --*/
  394. {
  395. PVOID *pageTable;
  396. PVOID *tableEntry;
  397. PHARDWARE_PTE pte;
  398. ULONG tableIndex;
  399. ULONG level;
  400. ULONG i;
  401. while (Length > 0) {
  402. pageTable = HiberFreeCR3Page(ProcNum,0);
  403. level = 3;
  404. while (TRUE) {
  405. //
  406. // Descend down the mapping tables, making sure that a page table
  407. // exists at each level for this address.
  408. //
  409. // NOTE: The "page table entries" are in reality linear pointers
  410. // to the next lower page. After the structure is built,
  411. // these will be converted to real page table entries.
  412. //
  413. tableIndex = (ULONG)(VirtAddress >> (level * 9 + PTI_SHIFT));
  414. tableIndex &= PTE_PER_PAGE - 1;
  415. tableEntry = &pageTable[tableIndex];
  416. if (level == 0) {
  417. break;
  418. }
  419. pageTable = *tableEntry;
  420. if (pageTable == NULL) {
  421. pageTable = ExAllocatePoolWithTag(NonPagedPool,
  422. PAGE_SIZE,
  423. HAL_POOL_TAG);
  424. if (!pageTable) {
  425. //
  426. // This allocation is critical.
  427. //
  428. KeBugCheckEx(HAL_MEMORY_ALLOCATION,
  429. PAGE_SIZE,
  430. 6,
  431. (ULONG_PTR)__FILE__,
  432. __LINE__
  433. );
  434. }
  435. //
  436. // Zero the page and store it in our list of mapping pages
  437. //
  438. RtlZeroMemory (pageTable, PAGE_SIZE);
  439. HalpStoreFreeCr3(ProcNum,pageTable,FALSE);
  440. *tableEntry = pageTable;
  441. }
  442. level -= 1;
  443. }
  444. //
  445. // The lowest-level page table entries are treated as real PTEs.
  446. //
  447. pte = (PHARDWARE_PTE)tableEntry;
  448. if (PhysicalAddress.QuadPart == 0) {
  449. PhysicalAddress = MmGetPhysicalAddress((PVOID)VirtAddress);
  450. }
  451. HalpSetPageFrameNumber( pte, PhysicalAddress.QuadPart >> PAGE_SHIFT );
  452. pte->Valid = 1;
  453. pte->Write = 1;
  454. PhysicalAddress.QuadPart = 0;
  455. VirtAddress += PAGE_SIZE;
  456. if (Length > PAGE_SIZE) {
  457. Length -= PAGE_SIZE;
  458. } else {
  459. Length = 0;
  460. }
  461. }
  462. }
  463. VOID
  464. HalpCommitCR3 (
  465. ULONG ProcNum
  466. )
  467. /*++
  468. Routine Description:
  469. The AMD64 four-level page table structure was created for each processor
  470. using linear pointers in place of PTEs. This routine walks the structures,
  471. replacing these linear pointers with actual PTE entries.
  472. Arguments:
  473. ProcNum - Identifies the processor for which the page table structure
  474. will be processed.
  475. Return Value:
  476. None.
  477. --*/
  478. {
  479. HalpCommitCR3Worker(HiberFreeCR3Page(ProcNum,0),3);
  480. }
  481. VOID
  482. HalpCommitCR3Worker (
  483. PVOID *PageTable,
  484. ULONG Level
  485. )
  486. /*++
  487. Routine Description:
  488. This is the worker routine for HalpCommitCR3. It is called recursively
  489. for three of the four levels of page tables. The lowest level, the
  490. page tables themselves, are already filled in with PTEs.
  491. Arguments:
  492. PageTable - Pointer to the topmost level of the pagetable structure.
  493. Level - Supplies the remaining number of page levels.
  494. Return Value:
  495. None.
  496. --*/
  497. {
  498. PVOID *tableEntry;
  499. ULONG index;
  500. PHYSICAL_ADDRESS physicalAddress;
  501. PHARDWARE_PTE pte;
  502. //
  503. // Examine each PTE in this page.
  504. //
  505. for (index = 0; index < PTE_PER_PAGE; index++) {
  506. tableEntry = &PageTable[index];
  507. if (*tableEntry != NULL) {
  508. //
  509. // A non-null entry was found. It contains a linear pointer
  510. // to the next lower page table. If the current level is 2
  511. // or higher then the next level is at least a Page Directory
  512. // so convert that page as well with a recursive call to this
  513. // routine.
  514. //
  515. if (Level >= 2) {
  516. HalpCommitCR3Worker( *tableEntry, Level - 1 );
  517. }
  518. //
  519. // Now convert the current table entry to PTE format.
  520. //
  521. pte = (PHARDWARE_PTE)tableEntry;
  522. physicalAddress = MmGetPhysicalAddress(*tableEntry);
  523. *tableEntry = NULL;
  524. HalpSetPageFrameNumber(pte,physicalAddress.QuadPart >> PAGE_SHIFT);
  525. pte->Valid = 1;
  526. pte->Write = 1;
  527. }
  528. }
  529. }
  530. #else
  531. VOID
  532. HalpMapCR3Ex (
  533. IN ULONG_PTR VirtAddress,
  534. IN PHYSICAL_ADDRESS PhysicalAddress,
  535. IN ULONG Length,
  536. IN ULONG ProcNum
  537. )
  538. /*++
  539. Routine Description:
  540. Called to build a page table entry for the passed page
  541. directory. Used to build a tiled page directory with
  542. real-mode & flat mode.
  543. Arguments:
  544. VirtAddress - Current virtual address
  545. PhysicalAddress - Optional. Physical address to be mapped
  546. to, if passed as a NULL then the physical
  547. address of the passed virtual address
  548. is assumed.
  549. Length - number of bytes to map
  550. Return Value:
  551. none.
  552. --*/
  553. {
  554. ULONG i;
  555. PHARDWARE_PTE PTE;
  556. PVOID pPageTable;
  557. PHYSICAL_ADDRESS pPhysicalPage;
  558. while (Length) {
  559. PTE = GetPdeAddressEx (VirtAddress,ProcNum);
  560. if (HalpIsPteFree( PTE ) != FALSE) {
  561. pPageTable = ExAllocatePoolWithTag(NonPagedPool,
  562. PAGE_SIZE,
  563. HAL_POOL_TAG);
  564. if (!pPageTable) {
  565. //
  566. // This allocation is critical.
  567. //
  568. KeBugCheckEx(HAL_MEMORY_ALLOCATION,
  569. PAGE_SIZE,
  570. 6,
  571. (ULONG_PTR)__FILE__,
  572. __LINE__
  573. );
  574. }
  575. RtlZeroMemory (pPageTable, PAGE_SIZE);
  576. HalpStoreFreeCr3(ProcNum,pPageTable,FALSE);
  577. pPhysicalPage = MmGetPhysicalAddress (pPageTable);
  578. HalpSetPageFrameNumber( PTE, pPhysicalPage.QuadPart >> PAGE_SHIFT );
  579. PTE->Valid = 1;
  580. PTE->Write = 1;
  581. }
  582. pPhysicalPage.QuadPart =
  583. HalpGetPageFrameNumber( PTE ) << PAGE_SHIFT;
  584. pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
  585. PTE = GetPteAddress (VirtAddress, pPageTable);
  586. if (PhysicalAddress.QuadPart == 0) {
  587. PhysicalAddress = MmGetPhysicalAddress((PVOID)VirtAddress);
  588. }
  589. HalpSetPageFrameNumber( PTE, PhysicalAddress.QuadPart >> PAGE_SHIFT );
  590. PTE->Valid = 1;
  591. PTE->Write = 1;
  592. MmUnmapIoSpace (pPageTable, PAGE_SIZE);
  593. PhysicalAddress.QuadPart = 0;
  594. VirtAddress += PAGE_SIZE;
  595. if (Length > PAGE_SIZE) {
  596. Length -= PAGE_SIZE;
  597. } else {
  598. Length = 0;
  599. }
  600. }
  601. }
  602. #endif
  603. VOID
  604. HalpFreeTiledCR3 (
  605. VOID
  606. )
  607. /*++
  608. Routine Description:
  609. Frees any memory allocated when the tiled page directory
  610. was built.
  611. Arguments:
  612. none
  613. Return Value:
  614. none
  615. --*/
  616. {
  617. HalpFreeTiledCR3Ex(0);
  618. }
  619. typedef struct _FREE_TILED_CR3_CONTEXT {
  620. WORK_QUEUE_ITEM WorkItem;
  621. ULONG ProcNum;
  622. } FREE_TILED_CR3_CONTEXT, *PFREE_TILED_CR3_CONTEXT;
  623. VOID
  624. HalpFreeTiledCR3Worker(
  625. ULONG ProcNum
  626. )
  627. {
  628. ULONG i;
  629. PVOID page;
  630. for (i = 0; HiberFreeCR3[ProcNum][i]; i++) {
  631. //
  632. // Free each page according to the method with which it was
  633. // allocated.
  634. //
  635. page = HiberFreeCR3[ProcNum][i];
  636. if (((ULONG_PTR)page & 1 ) == 0) {
  637. ExFreePool(page);
  638. } else {
  639. (ULONG_PTR)page ^= 1;
  640. MmFreeContiguousMemory(page);
  641. }
  642. HiberFreeCR3[ProcNum][i] = 0;
  643. }
  644. }
  645. VOID
  646. HalpFreeTiledCR3WorkRoutine(
  647. IN PFREE_TILED_CR3_CONTEXT Context
  648. )
  649. {
  650. HalpFreeTiledCR3Worker(Context->ProcNum);
  651. ExFreePool((PVOID)Context);
  652. }
  653. VOID
  654. HalpFreeTiledCR3Ex (
  655. ULONG ProcNum
  656. )
  657. /*++
  658. Routine Description:
  659. Frees any memory allocated when the tiled page directory
  660. was built.
  661. Arguments:
  662. none
  663. Return Value:
  664. none
  665. --*/
  666. {
  667. PFREE_TILED_CR3_CONTEXT Context;
  668. if(KeGetCurrentIrql() == PASSIVE_LEVEL) {
  669. HalpFreeTiledCR3Worker(ProcNum);
  670. } else {
  671. Context = (PFREE_TILED_CR3_CONTEXT) ExAllocatePoolWithTag(
  672. NonPagedPool,
  673. sizeof(FREE_TILED_CR3_CONTEXT),
  674. HAL_POOL_TAG
  675. );
  676. if (Context) {
  677. Context->ProcNum = ProcNum;
  678. ExInitializeWorkItem(&Context->WorkItem,
  679. HalpFreeTiledCR3WorkRoutine,
  680. Context);
  681. ExQueueWorkItem(&Context->WorkItem, DelayedWorkQueue);
  682. }
  683. }
  684. }