Sync with trunk r58151 to bring the latest changes from Amine and Timo.
[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 ERROR_FATAL();
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 < sizeof(Pfn) / sizeof(Pfn[0]); 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 NTSTATUS
371 NTAPI
372 Mmi386ReleaseMmInfo(IN PEPROCESS Process)
373 {
374 //
375 // FIXME-USER: Need to delete address space
376 //
377 UNIMPLEMENTED_DBGBREAK();
378 return STATUS_NOT_IMPLEMENTED;
379 }
380
381 PULONG
382 NTAPI
383 MmGetPageDirectory(VOID)
384 {
385 //
386 // Return the TTB
387 //
388 return (PULONG)KeArmTranslationTableRegisterGet().AsUlong;
389 }
390
391 VOID
392 NTAPI
393 MmDisableVirtualMapping(IN PEPROCESS Process,
394 IN PVOID Address,
395 OUT PBOOLEAN WasDirty,
396 OUT PPFN_NUMBER Page)
397 {
398 //
399 // TODO
400 //
401 UNIMPLEMENTED_DBGBREAK();
402 }
403
404 VOID
405 NTAPI
406 MmEnableVirtualMapping(IN PEPROCESS Process,
407 IN PVOID Address)
408 {
409 //
410 // TODO
411 //
412 UNIMPLEMENTED_DBGBREAK();
413 }
414
415 NTSTATUS
416 NTAPI
417 MmCreateVirtualMappingInternal(IN PEPROCESS Process,
418 IN PVOID Address,
419 IN ULONG Protection,
420 IN PPFN_NUMBER Pages,
421 IN ULONG PageCount,
422 IN BOOLEAN MarkAsMapped)
423 {
424 PMMPTE PointerPte = NULL;
425 MMPTE TempPte;
426 PVOID Addr;
427 ULONG OldPdeOffset, PdeOffset, i;
428 DPRINT("[KMAP]: %p %d\n", Address, PageCount);
429 //ASSERT(Address >= MmSystemRangeStart);
430
431 //
432 // Get our template PTE
433 //
434 TempPte = MiArmTemplatePte;
435
436 //
437 // Loop every page
438 //
439 Addr = Address;
440 OldPdeOffset = MiGetPdeOffset(Addr) + 1;
441 for (i = 0; i < PageCount; i++)
442 {
443 //
444 // Get the next PDE offset and check if it's a new one
445 //
446 PdeOffset = MiGetPdeOffset(Addr);
447 if (OldPdeOffset != PdeOffset)
448 {
449 //
450 // Get rid of the old L2 Table, if this was the last PTE on it
451 //
452 MiUnmapPageTable(PointerPte);
453
454 //
455 // Get the PTE for this address, and create the PDE for it
456 //
457 PointerPte = MiGetPageTableForProcess(NULL, Addr, TRUE);
458 ASSERT(PointerPte);
459 }
460 else
461 {
462 //
463 // Go to the next PTE on this PDE
464 //
465 ASSERT(PointerPte);
466 PointerPte++;
467 }
468
469 //
470 // Save the current PDE
471 //
472 OldPdeOffset = PdeOffset;
473
474 //
475 // Set the PFN
476 //
477 TempPte.u.Hard.PageFrameNumber = *Pages++;
478
479 //
480 // Write the PTE
481 //
482 ASSERT(PointerPte->u.Hard.Valid == 0);
483 ASSERT(TempPte.u.Hard.Valid == 1);
484 *PointerPte = TempPte;
485
486 //
487 // Move to the next page
488 //
489 Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE);
490 }
491
492 //
493 // All done
494 //
495 return STATUS_SUCCESS;
496 }
497
498 NTSTATUS
499 NTAPI
500 MmCreateVirtualMappingForKernel(IN PVOID Address,
501 IN ULONG Protection,
502 IN PPFN_NUMBER Pages,
503 IN ULONG PageCount)
504 {
505 //
506 // Call the internal version
507 //
508 return MmCreateVirtualMappingInternal(NULL,
509 Address,
510 Protection,
511 Pages,
512 PageCount,
513 FALSE);
514 }
515
516 NTSTATUS
517 NTAPI
518 MmCreateVirtualMappingUnsafe(IN PEPROCESS Process,
519 IN PVOID Address,
520 IN ULONG Protection,
521 IN PPFN_NUMBER Pages,
522 IN ULONG PageCount)
523 {
524 //
525 // Are we only handling the kernel?
526 //
527 if (!(Process) || (Process == PsGetCurrentProcess()))
528 {
529 //
530 // Call the internal version
531 //
532 return MmCreateVirtualMappingInternal(Process,
533 Address,
534 Protection,
535 Pages,
536 PageCount,
537 TRUE);
538 }
539
540 //
541 // FIXME-USER: Support user-mode mappings
542 //
543 ASSERT(FALSE);
544 return 0;
545 }
546
547 NTSTATUS
548 NTAPI
549 MmCreateVirtualMapping(IN PEPROCESS Process,
550 IN PVOID Address,
551 IN ULONG Protection,
552 IN PPFN_NUMBER Pages,
553 IN ULONG PageCount)
554 {
555 ULONG i;
556
557 //
558 // Loop each page
559 //
560 for (i = 0; i < PageCount; i++)
561 {
562 //
563 // Make sure the page is marked as in use
564 //
565 ASSERT(MmIsPageInUse(Pages[i]));
566 }
567
568 //
569 // Call the unsafe version
570 //
571 return MmCreateVirtualMappingUnsafe(Process,
572 Address,
573 Protection,
574 Pages,
575 PageCount);
576 }
577
578 VOID
579 NTAPI
580 MmRawDeleteVirtualMapping(IN PVOID Address)
581 {
582 PMMPTE PointerPte;
583
584 //
585 // Get the PTE
586 //
587 PointerPte = MiGetPageTableForProcess(NULL, Address, FALSE);
588 if ((PointerPte) && (PointerPte->u.Hard.Valid))
589 {
590 //
591 // Destroy it
592 //
593 PointerPte->u.Hard.AsUlong = 0;
594
595 //
596 // Flush the TLB
597 //
598 MiFlushTlb(PointerPte, Address);
599 }
600 }
601
602 VOID
603 NTAPI
604 MmDeleteVirtualMapping(IN PEPROCESS Process,
605 IN PVOID Address,
606 IN BOOLEAN FreePage,
607 OUT PBOOLEAN WasDirty,
608 OUT PPFN_NUMBER Page)
609 {
610 PMMPTE PointerPte;
611 MMPTE Pte;
612 PFN_NUMBER Pfn = 0;
613
614 //
615 // Get the PTE
616 //
617 PointerPte = MiGetPageTableForProcess(NULL, Address, FALSE);
618 if (PointerPte)
619 {
620 //
621 // Save and destroy the PTE
622 //
623 Pte = *PointerPte;
624 PointerPte->u.Hard.AsUlong = 0;
625
626 //
627 // Flush the TLB
628 //
629 MiFlushTlb(PointerPte, Address);
630
631 //
632 // Unmap the PFN
633 //
634 Pfn = Pte.u.Hard.PageFrameNumber;
635
636 //
637 // Release the PFN if it was ours
638 //
639 if ((FreePage) && (Pfn)) MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn);
640 }
641
642 //
643 // Return if the page was dirty
644 //
645 if (WasDirty) *WasDirty = FALSE; // LIE!!!
646 if (Page) *Page = Pfn;
647 }
648
649 VOID
650 NTAPI
651 MmDeletePageFileMapping(IN PEPROCESS Process,
652 IN PVOID Address,
653 IN SWAPENTRY *SwapEntry)
654 {
655 //
656 // TODO
657 //
658 UNIMPLEMENTED_DBGBREAK();
659 }
660
661 NTSTATUS
662 NTAPI
663 MmCreatePageFileMapping(IN PEPROCESS Process,
664 IN PVOID Address,
665 IN SWAPENTRY SwapEntry)
666 {
667 //
668 // TODO
669 //
670 UNIMPLEMENTED_DBGBREAK();
671 return STATUS_NOT_IMPLEMENTED;
672 }
673
674 PFN_NUMBER
675 NTAPI
676 MmGetPfnForProcess(IN PEPROCESS Process,
677 IN PVOID Address)
678 {
679 MMPTE Pte;
680
681 //
682 // Get the PTE
683 //
684 Pte = MiGetPageEntryForProcess(Process, Address);
685 if (Pte.u.Hard.Valid == 0) return 0;
686
687 //
688 // Return PFN
689 //
690 return Pte.u.Hard.PageFrameNumber;
691 }
692
693 BOOLEAN
694 NTAPI
695 MmIsDirtyPage(IN PEPROCESS Process,
696 IN PVOID Address)
697 {
698 //
699 // TODO
700 //
701 UNIMPLEMENTED_DBGBREAK();
702 return FALSE;
703 }
704
705 VOID
706 NTAPI
707 MmSetCleanPage(IN PEPROCESS Process,
708 IN PVOID Address)
709 {
710 //
711 // TODO
712 //
713 UNIMPLEMENTED_DBGBREAK();
714 }
715
716 VOID
717 NTAPI
718 MmSetDirtyPage(IN PEPROCESS Process,
719 IN PVOID Address)
720 {
721 //
722 // TODO
723 //
724 UNIMPLEMENTED_DBGBREAK();
725 }
726
727 BOOLEAN
728 NTAPI
729 MmIsPagePresent(IN PEPROCESS Process,
730 IN PVOID Address)
731 {
732 //
733 // Fault PTEs are 0, which is FALSE (non-present)
734 //
735 return MiGetPageEntryForProcess(Process, Address).u.Hard.Valid;
736 }
737
738 BOOLEAN
739 NTAPI
740 MmIsPageSwapEntry(IN PEPROCESS Process,
741 IN PVOID Address)
742 {
743 MMPTE Pte;
744
745 //
746 // Get the PTE
747 //
748 Pte = MiGetPageEntryForProcess(Process, Address);
749
750 //
751 // Make sure it exists, but is faulting
752 //
753 return (Pte.u.Hard.Valid == 0) && (Pte.u.Hard.AsUlong);
754 }
755
756 ULONG
757 NTAPI
758 MmGetPageProtect(IN PEPROCESS Process,
759 IN PVOID Address)
760 {
761 //
762 // We don't enforce any protection on the pages -- they are all RWX
763 //
764 return PAGE_READWRITE;
765 }
766
767 VOID
768 NTAPI
769 MmSetPageProtect(IN PEPROCESS Process,
770 IN PVOID Address,
771 IN ULONG Protection)
772 {
773 //
774 // We don't enforce any protection on the pages -- they are all RWX
775 //
776 return;
777 }
778
779 VOID
780 NTAPI
781 MmInitGlobalKernelPageDirectory(VOID)
782 {
783 ULONG i;
784 PULONG CurrentPageDirectory = (PULONG)PDE_BASE;
785
786 //
787 // Good place to setup template PTE/PDEs.
788 // We are lazy and pick a known-good PTE
789 //
790 MiArmTemplatePte = *MiGetPteAddress(0x80000000);
791 MiArmTemplatePde = *MiGetPdeAddress(0x80000000);
792
793 //
794 // Loop the 2GB of address space which belong to the kernel
795 //
796 for (i = MiGetPdeOffset(MmSystemRangeStart); i < 1024; i++)
797 {
798 //
799 // Check if we have an entry for this already
800 //
801 if ((i != MiGetPdeOffset(PTE_BASE)) &&
802 (i != MiGetPdeOffset(HYPER_SPACE)) &&
803 (!MmGlobalKernelPageDirectory[i]) &&
804 (CurrentPageDirectory[i]))
805 {
806 //
807 // We don't, link it in our global page directory
808 //
809 MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i];
810 }
811 }
812 }
813
814 VOID
815 NTAPI
816 MiInitPageDirectoryMap(VOID)
817 {
818 MEMORY_AREA* MemoryArea = NULL;
819 PHYSICAL_ADDRESS BoundaryAddressMultiple;
820 PVOID BaseAddress;
821 NTSTATUS Status;
822
823 //
824 // Create memory area for the PTE area
825 //
826 BoundaryAddressMultiple.QuadPart = 0;
827 BaseAddress = (PVOID)PTE_BASE;
828 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
829 MEMORY_AREA_OWNED_BY_ARM3,
830 &BaseAddress,
831 0x1000000,
832 PAGE_READWRITE,
833 &MemoryArea,
834 TRUE,
835 0,
836 BoundaryAddressMultiple);
837 ASSERT(NT_SUCCESS(Status));
838
839 //
840 // Create memory area for the PDE area
841 //
842 BaseAddress = (PVOID)PDE_BASE;
843 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
844 MEMORY_AREA_OWNED_BY_ARM3,
845 &BaseAddress,
846 0x100000,
847 PAGE_READWRITE,
848 &MemoryArea,
849 TRUE,
850 0,
851 BoundaryAddressMultiple);
852 ASSERT(NT_SUCCESS(Status));
853
854 //
855 // And finally, hyperspace
856 //
857 BaseAddress = (PVOID)HYPER_SPACE;
858 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
859 MEMORY_AREA_OWNED_BY_ARM3,
860 &BaseAddress,
861 PAGE_SIZE,
862 PAGE_READWRITE,
863 &MemoryArea,
864 TRUE,
865 0,
866 BoundaryAddressMultiple);
867 ASSERT(NT_SUCCESS(Status));
868 }
869
870 /* PUBLIC FUNCTIONS ***********************************************************/
871
872 /*
873 * @implemented
874 */
875 PHYSICAL_ADDRESS
876 NTAPI
877 MmGetPhysicalAddress(IN PVOID Address)
878 {
879 PHYSICAL_ADDRESS PhysicalAddress;
880 MMPTE Pte;
881
882 //
883 // Early boot PCR check
884 //
885 if (Address == PCR)
886 {
887 //
888 // ARM Hack while we still use a section PTE
889 //
890 PMMPDE_HARDWARE PointerPde;
891 PointerPde = MiGetPdeAddress(PCR);
892 ASSERT(PointerPde->u.Hard.Section.Valid == 1);
893 PhysicalAddress.QuadPart = PointerPde->u.Hard.Section.PageFrameNumber;
894 PhysicalAddress.QuadPart <<= CPT_SHIFT;
895 PhysicalAddress.LowPart += BYTE_OFFSET(Address);
896 return PhysicalAddress;
897 }
898
899 //
900 // Get the PTE
901 //
902 Pte = MiGetPageEntryForProcess(NULL, Address);
903 if (Pte.u.Hard.Valid)
904 {
905 //
906 // Return the information
907 //
908 PhysicalAddress.QuadPart = Pte.u.Hard.PageFrameNumber;
909 PhysicalAddress.QuadPart <<= PAGE_SHIFT;
910 PhysicalAddress.LowPart += BYTE_OFFSET(Address);
911 }
912 else
913 {
914 //
915 // Invalid or unmapped
916 //
917 PhysicalAddress.QuadPart = 0;
918 }
919
920 //
921 // Return the physical address
922 //
923 return PhysicalAddress;
924 }