Sync with trunk (r47116), hopefully without breaking anything.
[reactos.git] / ntoskrnl / mm / arm / stubs.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/arm/stubs.c
5 * PURPOSE: ARM Memory Manager
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 ULONG MmGlobalKernelPageDirectory[1024];
18 MMPTE MiArmTemplatePte;
19 MMPDE_HARDWARE MiArmTemplatePde;
20
21 /* PRIVATE FUNCTIONS **********************************************************/
22
23 BOOLEAN
24 NTAPI
25 MiUnmapPageTable(IN PMMPTE PointerPde)
26 {
27 //
28 // Check if this address belongs to the kernel
29 //
30 if (((ULONG_PTR)PointerPde > PDE_BASE) ||
31 ((ULONG_PTR)PointerPde < (PDE_BASE + 1024*1024)))
32 {
33 //
34 // Nothing to do
35 //
36 return TRUE;
37 }
38
39 //
40 // FIXME-USER: Shouldn't get here yet
41 //
42 ASSERT(FALSE);
43 return FALSE;
44 }
45
46 VOID
47 NTAPI
48 MiFlushTlb(IN PMMPTE PointerPte,
49 IN PVOID Address)
50 {
51 //
52 // Make sure the PTE is valid, and unmap the pagetable if user-mode
53 //
54 if (((PointerPte) && (MiUnmapPageTable(PointerPte))) ||
55 (Address >= MmSystemRangeStart))
56 {
57 //
58 // Invalidate this page
59 //
60 KeArmInvalidateTlbEntry(Address);
61 }
62 }
63
64 PMMPTE
65 NTAPI
66 MiGetPageTableForProcess(IN PEPROCESS Process,
67 IN PVOID Address,
68 IN BOOLEAN Create)
69 {
70 //ULONG PdeOffset;
71 PMMPTE PointerPte;
72 PMMPDE_HARDWARE PointerPde;
73 MMPDE_HARDWARE TempPde;
74 MMPTE TempPte;
75 NTSTATUS Status;
76 PFN_NUMBER Pfn;
77
78 //
79 // Check if this is a user-mode, non-kernel or non-current address
80 //
81 if ((Address < MmSystemRangeStart) &&
82 (Process) &&
83 (Process != PsGetCurrentProcess()))
84 {
85 //
86 // FIXME-USER: No user-mode memory support
87 //
88 ASSERT(FALSE);
89 }
90
91 //
92 // Get our templates
93 //
94 TempPde = MiArmTemplatePde;
95 TempPte = MiArmTemplatePte;
96
97 //
98 // Get the PDE
99 //
100 PointerPde = MiGetPdeAddress(Address);
101 if (PointerPde->u.Hard.Coarse.Valid)
102 {
103 //
104 // Invalid PDE, is this a kernel address?
105 //
106 if (Address >= MmSystemRangeStart)
107 {
108 //
109 // Does it exist in the kernel page directory?
110 //
111 //PdeOffset = MiGetPdeOffset(Address);
112 //if (MmGlobalKernelPageDirectory[PdeOffset] == 0)
113 {
114 //
115 // It doesn't. Is this a create operation? If not, fail
116 //
117 if (Create == FALSE) return NULL;
118 kernelHack:
119 DPRINT1("Must create a page for: %p PDE: %p\n", // Offset: %lx!\n",
120 Address, PointerPde);//, PdeOffset);
121
122 //
123 // Allocate a non paged pool page for the PDE
124 //
125 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
126 if (!NT_SUCCESS(Status)) return NULL;
127
128 //
129 // Setup the PFN
130 //
131 TempPde.u.Hard.Coarse.PageFrameNumber = (Pfn << PAGE_SHIFT) >> CPT_SHIFT;
132
133 //
134 // Write the PDE
135 //
136 ASSERT(PointerPde->u.Hard.Coarse.Valid == 0);
137 ASSERT(TempPde.u.Hard.Coarse.Valid == 1);
138 *PointerPde = TempPde;
139
140 //
141 // Save it
142 //
143 //MmGlobalKernelPageDirectory[PdeOffset] = TempPde.u.Hard.AsUlong;
144 //DPRINT1("KPD: %p PDEADDR: %p\n", &MmGlobalKernelPageDirectory[PdeOffset], MiGetPdeAddress(Address));
145
146 //
147 // FIXFIX: Double check with Felix tomorrow
148 //
149 /////
150 //
151 // Get the PTE for this 1MB region
152 //
153 PointerPte = MiGetPteAddress(MiGetPteAddress(Address));
154 DPRINT1("PointerPte: %p\n", PointerPte);
155
156 //
157 // Write the PFN of the PDE
158 //
159 TempPte.u.Hard.PageFrameNumber = Pfn;
160
161 //
162 // Write the PTE
163 //
164 ASSERT(PointerPte->u.Hard.Valid == 0);
165 ASSERT(TempPte.u.Hard.Valid == 1);
166 *PointerPte = TempPte;
167 /////
168 }
169
170 //
171 // Now set the actual PDE
172 //
173 //PointerPde = (PMMPTE)&MmGlobalKernelPageDirectory[PdeOffset];
174 }
175 else
176 {
177 //
178 // Is this a create operation? If not, fail
179 //
180 if (Create == FALSE) return NULL;
181
182 //
183 // THIS WHOLE PATH IS TODO
184 //
185 goto kernelHack;
186 ASSERT(FALSE);
187
188 //
189 // Allocate a non paged pool page for the PDE
190 //
191 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn);
192 if (!NT_SUCCESS(Status)) return NULL;
193
194 //
195 // Make the entry valid
196 //
197 TempPde.u.Hard.AsUlong = 0xDEADBEEF;
198
199 //
200 // Set it
201 //
202 *PointerPde = TempPde;
203 }
204 }
205
206 //
207 // Return the PTE
208 //
209 return MiGetPteAddress(Address);
210 }
211
212 MMPTE
213 NTAPI
214 MiGetPageEntryForProcess(IN PEPROCESS Process,
215 IN PVOID Address)
216 {
217 PMMPTE PointerPte;
218 MMPTE Pte;
219 Pte.u.Hard.AsUlong = 0;
220
221 //
222 // Get the PTE
223 //
224 PointerPte = MiGetPageTableForProcess(Process, Address, FALSE);
225 if (PointerPte)
226 {
227 //
228 // Capture the PTE value and unmap the page table
229 //
230 Pte = *PointerPte;
231 MiUnmapPageTable(PointerPte);
232 }
233
234 //
235 // Return the PTE value
236 //
237 return Pte;
238 }
239
240 VOID
241 NTAPI
242 MmDeletePageTable(IN PEPROCESS Process,
243 IN PVOID Address)
244 {
245 PMMPDE_HARDWARE PointerPde;
246
247 //
248 // Not valid for kernel addresses
249 //
250 DPRINT("MmDeletePageTable(%p, %p)\n", Process, Address);
251 ASSERT(Address < MmSystemRangeStart);
252
253 //
254 // Check if this is for a different process
255 //
256 if ((Process) && (Process != PsGetCurrentProcess()))
257 {
258 //
259 // FIXME-USER: Need to attach to the process
260 //
261 ASSERT(FALSE);
262 }
263
264 //
265 // Get the PDE
266 //
267 PointerPde = MiGetPdeAddress(Address);
268
269 //
270 // On ARM, we use a section mapping for the original low-memory mapping
271 //
272 if ((Address) || (PointerPde->u.Hard.Section.Valid == 0))
273 {
274 //
275 // Make sure it's valid
276 //
277 ASSERT(PointerPde->u.Hard.Coarse.Valid == 1);
278 }
279
280 //
281 // Clear the PDE
282 //
283 PointerPde->u.Hard.AsUlong = 0;
284 ASSERT(PointerPde->u.Hard.Coarse.Valid == 0);
285
286 //
287 // Invalidate the TLB entry
288 //
289 MiFlushTlb((PMMPTE)PointerPde, MiGetPteAddress(Address));
290 }
291
292 BOOLEAN
293 NTAPI
294 MmCreateProcessAddressSpace(IN ULONG MinWs,
295 IN PEPROCESS Process,
296 IN PULONG DirectoryTableBase)
297 {
298 NTSTATUS Status;
299 ULONG i;
300 PFN_NUMBER Pfn[2];
301 PMMPDE_HARDWARE PageDirectory, PointerPde;
302 MMPDE_HARDWARE TempPde;
303 ASSERT(FALSE);
304
305 //
306 // Loop two tables (Hyperspace and TTB). Each one is 16KB
307 //
308 //
309 for (i = 0; i < 8; i++)
310 {
311 //
312 // Allocate a page
313 //
314 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]);
315 if (!NT_SUCCESS(Status)) ASSERT(FALSE);
316 }
317
318 //
319 // Map the base
320 //
321 PageDirectory = MmCreateHyperspaceMapping(Pfn[0]);
322
323 //
324 // Copy the PDEs for kernel-mode
325 //
326 RtlCopyMemory(PageDirectory + MiGetPdeOffset(MmSystemRangeStart),
327 MmGlobalKernelPageDirectory + MiGetPdeOffset(MmSystemRangeStart),
328 (1024 - MiGetPdeOffset(MmSystemRangeStart)) * sizeof(ULONG));
329
330
331 //
332 // Setup the PDE for the table base
333 //
334 TempPde = MiArmTemplatePde;
335 TempPde.u.Hard.Coarse.PageFrameNumber = (Pfn[0] << PAGE_SHIFT) >> CPT_SHIFT;
336 PointerPde = &PageDirectory[MiGetPdeOffset(PTE_BASE)];
337
338 //
339 // Write the PDE
340 //
341 ASSERT(PointerPde->u.Hard.Coarse.Valid == 0);
342 ASSERT(TempPde.u.Hard.Coarse.Valid == 1);
343 *PointerPde = TempPde;
344
345 //
346 // Setup the PDE for the hyperspace
347 //
348 TempPde.u.Hard.Coarse.PageFrameNumber = (Pfn[1] << PAGE_SHIFT) >> CPT_SHIFT;
349 PointerPde = &PageDirectory[MiGetPdeOffset(HYPER_SPACE)];
350
351 //
352 // Write the PDE
353 //
354 ASSERT(PointerPde->u.Hard.Coarse.Valid == 0);
355 ASSERT(TempPde.u.Hard.Coarse.Valid == 1);
356 *PointerPde = TempPde;
357
358 //
359 // Unmap the page directory
360 //
361 MmDeleteHyperspaceMapping(PageDirectory);
362
363 //
364 // Return the page table base
365 //
366 DirectoryTableBase[0] = Pfn[0] << PAGE_SHIFT;
367 return TRUE;
368 }
369
370 VOID
371 NTAPI
372 MmUpdatePageDir(IN PEPROCESS Process,
373 IN PVOID Address,
374 IN ULONG Size)
375 {
376 //
377 // Nothing to do
378 //
379 return;
380 }
381
382 NTSTATUS
383 NTAPI
384 Mmi386ReleaseMmInfo(IN PEPROCESS Process)
385 {
386 //
387 // FIXME-USER: Need to delete address space
388 //
389 UNIMPLEMENTED;
390 while (TRUE);
391 return 0;
392 }
393
394 NTSTATUS
395 NTAPI
396 MmInitializeHandBuiltProcess(IN PEPROCESS Process,
397 IN PULONG DirectoryTableBase)
398 {
399 //
400 // Share the directory base with the idle process
401 //
402 DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0];
403 DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1];
404
405 //
406 // Initialize the Addresss Space
407 //
408 KeInitializeGuardedMutex(&Process->AddressCreationLock);
409 Process->VadRoot.BalancedRoot.u1.Parent = NULL;
410
411 //
412 // The process now has an address space
413 //
414 Process->HasAddressSpace = TRUE;
415 return STATUS_SUCCESS;
416 }
417
418 PULONG
419 NTAPI
420 MmGetPageDirectory(VOID)
421 {
422 //
423 // Return the TTB
424 //
425 return (PULONG)KeArmTranslationTableRegisterGet().AsUlong;
426 }
427
428 VOID
429 NTAPI
430 MmDisableVirtualMapping(IN PEPROCESS Process,
431 IN PVOID Address,
432 OUT PBOOLEAN WasDirty,
433 OUT PPFN_TYPE Page)
434 {
435 //
436 // TODO
437 //
438 UNIMPLEMENTED;
439 while (TRUE);
440 }
441
442 VOID
443 NTAPI
444 MmEnableVirtualMapping(IN PEPROCESS Process,
445 IN PVOID Address)
446 {
447 //
448 // TODO
449 //
450 UNIMPLEMENTED;
451 while (TRUE);
452 }
453
454 NTSTATUS
455 NTAPI
456 MmCreateVirtualMappingInternal(IN PEPROCESS Process,
457 IN PVOID Address,
458 IN ULONG Protection,
459 IN PPFN_NUMBER Pages,
460 IN ULONG PageCount,
461 IN BOOLEAN MarkAsMapped)
462 {
463 PMMPTE PointerPte = NULL;
464 MMPTE TempPte;
465 PVOID Addr;
466 ULONG OldPdeOffset, PdeOffset, i;
467 DPRINT("[KMAP]: %p %d\n", Address, PageCount);
468 //ASSERT(Address >= MmSystemRangeStart);
469
470 //
471 // Get our template PTE
472 //
473 TempPte = MiArmTemplatePte;
474
475 //
476 // Loop every page
477 //
478 Addr = Address;
479 OldPdeOffset = MiGetPdeOffset(Addr) + 1;
480 for (i = 0; i < PageCount; i++)
481 {
482 //
483 // Get the next PDE offset and check if it's a new one
484 //
485 PdeOffset = MiGetPdeOffset(Addr);
486 if (OldPdeOffset != PdeOffset)
487 {
488 //
489 // Get rid of the old L2 Table, if this was the last PTE on it
490 //
491 MiUnmapPageTable(PointerPte);
492
493 //
494 // Get the PTE for this address, and create the PDE for it
495 //
496 PointerPte = MiGetPageTableForProcess(NULL, Addr, TRUE);
497 ASSERT(PointerPte);
498 }
499 else
500 {
501 //
502 // Go to the next PTE on this PDE
503 //
504 ASSERT(PointerPte);
505 PointerPte++;
506 }
507
508 //
509 // Save the current PDE
510 //
511 OldPdeOffset = PdeOffset;
512
513 //
514 // Set the PFN
515 //
516 TempPte.u.Hard.PageFrameNumber = *Pages++;
517
518 //
519 // Write the PTE
520 //
521 ASSERT(PointerPte->u.Hard.Valid == 0);
522 ASSERT(TempPte.u.Hard.Valid == 1);
523 *PointerPte = TempPte;
524
525 //
526 // Move to the next page
527 //
528 Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE);
529 }
530
531 //
532 // All done
533 //
534 return STATUS_SUCCESS;
535 }
536
537 NTSTATUS
538 NTAPI
539 MmCreateVirtualMappingForKernel(IN PVOID Address,
540 IN ULONG Protection,
541 IN PPFN_NUMBER Pages,
542 IN ULONG PageCount)
543 {
544 //
545 // Call the internal version
546 //
547 return MmCreateVirtualMappingInternal(NULL,
548 Address,
549 Protection,
550 Pages,
551 PageCount,
552 FALSE);
553 }
554
555 NTSTATUS
556 NTAPI
557 MmCreateVirtualMappingUnsafe(IN PEPROCESS Process,
558 IN PVOID Address,
559 IN ULONG Protection,
560 IN PPFN_TYPE Pages,
561 IN ULONG PageCount)
562 {
563 //
564 // Are we only handling the kernel?
565 //
566 if (!(Process) || (Process == PsGetCurrentProcess()))
567 {
568 //
569 // Call the internal version
570 //
571 return MmCreateVirtualMappingInternal(Process,
572 Address,
573 Protection,
574 Pages,
575 PageCount,
576 TRUE);
577 }
578
579 //
580 // FIXME-USER: Support user-mode mappings
581 //
582 ASSERT(FALSE);
583 return 0;
584 }
585
586 NTSTATUS
587 NTAPI
588 MmCreateVirtualMapping(IN PEPROCESS Process,
589 IN PVOID Address,
590 IN ULONG Protection,
591 IN PPFN_TYPE Pages,
592 IN ULONG PageCount)
593 {
594 ULONG i;
595
596 //
597 // Loop each page
598 //
599 for (i = 0; i < PageCount; i++)
600 {
601 //
602 // Make sure the page is marked as in use
603 //
604 ASSERT(MmIsPageInUse(Pages[i]));
605 }
606
607 //
608 // Call the unsafe version
609 //
610 return MmCreateVirtualMappingUnsafe(Process,
611 Address,
612 Protection,
613 Pages,
614 PageCount);
615 }
616
617 VOID
618 NTAPI
619 MmRawDeleteVirtualMapping(IN PVOID Address)
620 {
621 PMMPTE PointerPte;
622
623 //
624 // Get the PTE
625 //
626 PointerPte = MiGetPageTableForProcess(NULL, Address, FALSE);
627 if ((PointerPte) && (PointerPte->u.Hard.Valid))
628 {
629 //
630 // Destroy it
631 //
632 PointerPte->u.Hard.AsUlong = 0;
633
634 //
635 // Flush the TLB
636 //
637 MiFlushTlb(PointerPte, Address);
638 }
639 }
640
641 VOID
642 NTAPI
643 MmDeleteVirtualMapping(IN PEPROCESS Process,
644 IN PVOID Address,
645 IN BOOLEAN FreePage,
646 OUT PBOOLEAN WasDirty,
647 OUT PPFN_TYPE Page)
648 {
649 PMMPTE PointerPte;
650 MMPTE Pte;
651 PFN_NUMBER Pfn = 0;
652
653 //
654 // Get the PTE
655 //
656 PointerPte = MiGetPageTableForProcess(NULL, Address, FALSE);
657 if (PointerPte)
658 {
659 //
660 // Save and destroy the PTE
661 //
662 Pte = *PointerPte;
663 PointerPte->u.Hard.AsUlong = 0;
664
665 //
666 // Flush the TLB
667 //
668 MiFlushTlb(PointerPte, Address);
669
670 //
671 // Unmap the PFN
672 //
673 Pfn = Pte.u.Hard.PageFrameNumber;
674
675 //
676 // Release the PFN if it was ours
677 //
678 if ((FreePage) && (Pfn)) MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
679 }
680
681 //
682 // Return if the page was dirty
683 //
684 if (WasDirty) *WasDirty = FALSE; // LIE!!!
685 if (Page) *Page = Pfn;
686 }
687
688 VOID
689 NTAPI
690 MmDeletePageFileMapping(IN PEPROCESS Process,
691 IN PVOID Address,
692 IN SWAPENTRY *SwapEntry)
693 {
694 //
695 // TODO
696 //
697 UNIMPLEMENTED;
698 while (TRUE);
699 }
700
701 NTSTATUS
702 NTAPI
703 MmCreatePageFileMapping(IN PEPROCESS Process,
704 IN PVOID Address,
705 IN SWAPENTRY SwapEntry)
706 {
707 //
708 // TODO
709 //
710 UNIMPLEMENTED;
711 while (TRUE);
712 return 0;
713 }
714
715 PFN_TYPE
716 NTAPI
717 MmGetPfnForProcess(IN PEPROCESS Process,
718 IN PVOID Address)
719 {
720 MMPTE Pte;
721
722 //
723 // Get the PTE
724 //
725 Pte = MiGetPageEntryForProcess(Process, Address);
726 if (Pte.u.Hard.Valid == 0) return 0;
727
728 //
729 // Return PFN
730 //
731 return Pte.u.Hard.PageFrameNumber;
732 }
733
734 BOOLEAN
735 NTAPI
736 MmIsDirtyPage(IN PEPROCESS Process,
737 IN PVOID Address)
738 {
739 //
740 // TODO
741 //
742 UNIMPLEMENTED;
743 while (TRUE);
744 return 0;
745 }
746
747 VOID
748 NTAPI
749 MmSetCleanPage(IN PEPROCESS Process,
750 IN PVOID Address)
751 {
752 //
753 // TODO
754 //
755 UNIMPLEMENTED;
756 while (TRUE);
757 }
758
759 VOID
760 NTAPI
761 MmSetDirtyPage(IN PEPROCESS Process,
762 IN PVOID Address)
763 {
764 //
765 // TODO
766 //
767 UNIMPLEMENTED;
768 while (TRUE);
769 }
770
771 BOOLEAN
772 NTAPI
773 MmIsPagePresent(IN PEPROCESS Process,
774 IN PVOID Address)
775 {
776 //
777 // Fault PTEs are 0, which is FALSE (non-present)
778 //
779 return MiGetPageEntryForProcess(Process, Address).u.Hard.Valid;
780 }
781
782 BOOLEAN
783 NTAPI
784 MmIsPageSwapEntry(IN PEPROCESS Process,
785 IN PVOID Address)
786 {
787 MMPTE Pte;
788
789 //
790 // Get the PTE
791 //
792 Pte = MiGetPageEntryForProcess(Process, Address);
793
794 //
795 // Make sure it exists, but is faulting
796 //
797 return (Pte.u.Hard.Valid == 0) && (Pte.u.Hard.AsUlong);
798 }
799
800 ULONG
801 NTAPI
802 MmGetPageProtect(IN PEPROCESS Process,
803 IN PVOID Address)
804 {
805 //
806 // We don't enforce any protection on the pages -- they are all RWX
807 //
808 return PAGE_READWRITE;
809 }
810
811 VOID
812 NTAPI
813 MmSetPageProtect(IN PEPROCESS Process,
814 IN PVOID Address,
815 IN ULONG Protection)
816 {
817 //
818 // We don't enforce any protection on the pages -- they are all RWX
819 //
820 return;
821 }
822
823 VOID
824 NTAPI
825 MmInitGlobalKernelPageDirectory(VOID)
826 {
827 ULONG i;
828 PULONG CurrentPageDirectory = (PULONG)PDE_BASE;
829
830 //
831 // Good place to setup template PTE/PDEs.
832 // We are lazy and pick a known-good PTE
833 //
834 MiArmTemplatePte = *MiGetPteAddress(0x80000000);
835 MiArmTemplatePde = *MiGetPdeAddress(0x80000000);
836
837 //
838 // Loop the 2GB of address space which belong to the kernel
839 //
840 for (i = MiGetPdeOffset(MmSystemRangeStart); i < 1024; i++)
841 {
842 //
843 // Check if we have an entry for this already
844 //
845 if ((i != MiGetPdeOffset(PTE_BASE)) &&
846 (i != MiGetPdeOffset(HYPER_SPACE)) &&
847 (!MmGlobalKernelPageDirectory[i]) &&
848 (CurrentPageDirectory[i]))
849 {
850 //
851 // We don't, link it in our global page directory
852 //
853 MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
854 }
855 }
856 }
857
858 VOID
859 NTAPI
860 MiInitPageDirectoryMap(VOID)
861 {
862 MEMORY_AREA* MemoryArea = NULL;
863 PHYSICAL_ADDRESS BoundaryAddressMultiple;
864 PVOID BaseAddress;
865 NTSTATUS Status;
866
867 //
868 // Create memory area for the PTE area
869 //
870 BoundaryAddressMultiple.QuadPart = 0;
871 BaseAddress = (PVOID)PTE_BASE;
872 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
873 MEMORY_AREA_SYSTEM,
874 &BaseAddress,
875 0x1000000,
876 PAGE_READWRITE,
877 &MemoryArea,
878 TRUE,
879 0,
880 BoundaryAddressMultiple);
881 ASSERT(NT_SUCCESS(Status));
882
883 //
884 // Create memory area for the PDE area
885 //
886 BaseAddress = (PVOID)PDE_BASE;
887 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
888 MEMORY_AREA_SYSTEM,
889 &BaseAddress,
890 0x100000,
891 PAGE_READWRITE,
892 &MemoryArea,
893 TRUE,
894 0,
895 BoundaryAddressMultiple);
896 ASSERT(NT_SUCCESS(Status));
897
898 //
899 // And finally, hyperspace
900 //
901 BaseAddress = (PVOID)HYPER_SPACE;
902 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
903 MEMORY_AREA_SYSTEM,
904 &BaseAddress,
905 PAGE_SIZE,
906 PAGE_READWRITE,
907 &MemoryArea,
908 TRUE,
909 0,
910 BoundaryAddressMultiple);
911 ASSERT(NT_SUCCESS(Status));
912 }
913
914 /* PUBLIC FUNCTIONS ***********************************************************/
915
916 /*
917 * @implemented
918 */
919 PHYSICAL_ADDRESS
920 NTAPI
921 MmGetPhysicalAddress(IN PVOID Address)
922 {
923 PHYSICAL_ADDRESS PhysicalAddress;
924 MMPTE Pte;
925
926 //
927 // Early boot PCR check
928 //
929 if (Address == PCR)
930 {
931 //
932 // ARM Hack while we still use a section PTE
933 //
934 PMMPDE_HARDWARE PointerPde;
935 PointerPde = MiGetPdeAddress(PCR);
936 ASSERT(PointerPde->u.Hard.Section.Valid == 1);
937 PhysicalAddress.QuadPart = PointerPde->u.Hard.Section.PageFrameNumber;
938 PhysicalAddress.QuadPart <<= CPT_SHIFT;
939 PhysicalAddress.LowPart += BYTE_OFFSET(Address);
940 return PhysicalAddress;
941 }
942
943 //
944 // Get the PTE
945 //
946 Pte = MiGetPageEntryForProcess(NULL, Address);
947 if (Pte.u.Hard.Valid)
948 {
949 //
950 // Return the information
951 //
952 PhysicalAddress.QuadPart = Pte.u.Hard.PageFrameNumber;
953 PhysicalAddress.QuadPart <<= PAGE_SHIFT;
954 PhysicalAddress.LowPart += BYTE_OFFSET(Address);
955 }
956 else
957 {
958 //
959 // Invalid or unmapped
960 //
961 PhysicalAddress.QuadPart = 0;
962 }
963
964 //
965 // Return the physical address
966 //
967 return PhysicalAddress;
968 }