Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpage.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/mm/i386/page.c 00005 * PURPOSE: Low level memory managment manipulation 00006 * 00007 * PROGRAMMERS: David Welch (welch@cwcom.net) 00008 * Revised for PowerPC by arty 00009 */ 00010 00011 /* INCLUDES ***************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #include <ppcmmu/mmu.h> 00015 //#define NDEBUG 00016 #include <debug.h> 00017 00018 #if defined (ALLOC_PRAGMA) 00019 #pragma alloc_text(INIT, MmInitGlobalKernelPageDirectory) 00020 #pragma alloc_text(INIT, MiInitPageDirectoryMap) 00021 #endif 00022 00023 /* GLOBALS *****************************************************************/ 00024 00025 #define HYPERSPACE_PAGEDIR_PTR ((PVOID)0xc0000000) 00026 00027 #define PA_PRESENT (1ll<<63) 00028 #define PA_USER (1ll<<62) 00029 #define PA_ACCESSED 0x200 00030 #define PA_DIRTY 0x100 00031 #define PA_WT 0x20 00032 #define PA_CD 0x10 00033 #define PA_READWRITE 3 00034 00035 #define HYPERSPACE (0xc0400000) 00036 #define IS_HYPERSPACE(v) (((ULONG)(v) >= HYPERSPACE && (ULONG)(v) < HYPERSPACE + 0x400000)) 00037 00038 #define PTE_TO_PFN(X) ((X) >> PAGE_SHIFT) 00039 #define PFN_TO_PTE(X) ((X) << PAGE_SHIFT) 00040 00041 #if defined(__GNUC__) 00042 #define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X))) 00043 #else 00044 __inline LARGE_INTEGER PTE_TO_PAGE(ULONG npage) 00045 { 00046 LARGE_INTEGER dummy; 00047 dummy.QuadPart = (LONGLONG)(PAGE_MASK(npage)); 00048 return dummy; 00049 } 00050 #endif 00051 00052 /* FUNCTIONS ***************************************************************/ 00053 00054 VOID 00055 NTAPI 00056 MiFlushTlbIpiRoutine(PVOID Address) 00057 { 00058 if (Address == (PVOID)0xffffffff) 00059 { 00060 __asm__("tlbsync"); 00061 } 00062 else if (Address == (PVOID)0xfffffffe) 00063 { 00064 __asm__("tlbsync"); 00065 } 00066 else 00067 { 00068 __asm__("tlbi %0" : "=r" (Address)); 00069 } 00070 } 00071 00072 VOID 00073 MiFlushTlb(PULONG Pt, PVOID Address) 00074 { 00075 __asm__("tlbi %0" : "=r" (Address)); 00076 } 00077 00078 00079 00080 PULONG 00081 MmGetPageDirectory(VOID) 00082 { 00083 unsigned int page_dir=0; 00084 return((PULONG)page_dir); 00085 } 00086 00087 static ULONG 00088 ProtectToFlags(ULONG flProtect) 00089 { 00090 return MMU_ALL_RW; // XXX hack 00091 } 00092 00093 NTSTATUS 00094 NTAPI 00095 MmCopyMmInfo(PEPROCESS Src, 00096 PEPROCESS Dest, 00097 PPHYSICAL_ADDRESS DirectoryTableBase) 00098 { 00099 DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest); 00100 00101 ASSERT(FALSE); 00102 00103 return(STATUS_SUCCESS); 00104 } 00105 00106 NTSTATUS 00107 NTAPI 00108 MmInitializeHandBuiltProcess(IN PEPROCESS Process, 00109 IN PLARGE_INTEGER DirectoryTableBase) 00110 { 00111 /* Share the directory base with the idle process */ 00112 *DirectoryTableBase = PsGetCurrentProcess()->Pcb.DirectoryTableBase; 00113 00114 /* Initialize the Addresss Space */ 00115 MmInitializeAddressSpace(Process, (PMADDRESS_SPACE)&Process->VadRoot); 00116 00117 /* The process now has an address space */ 00118 Process->HasAddressSpace = TRUE; 00119 return STATUS_SUCCESS; 00120 } 00121 00122 BOOLEAN 00123 NTAPI 00124 MmCreateProcessAddressSpace(IN ULONG MinWs, 00125 IN PEPROCESS Process, 00126 IN PLARGE_INTEGER DirectoryTableBase) 00127 { 00128 ASSERT(FALSE); 00129 return TRUE; 00130 } 00131 00132 VOID 00133 NTAPI 00134 MmDeletePageTable(PEPROCESS Process, PVOID Address) 00135 { 00136 PEPROCESS CurrentProcess = PsGetCurrentProcess(); 00137 00138 DPRINT1("DeletePageTable: Process: %x CurrentProcess %x\n", 00139 Process, CurrentProcess); 00140 00141 if (Process != NULL && Process != CurrentProcess) 00142 { 00143 KeAttachProcess(&Process->Pcb); 00144 } 00145 00146 if (Process) 00147 { 00148 DPRINT1("Revoking VSID %d\n", (paddr_t)Process->UniqueProcessId); 00149 MmuRevokeVsid((paddr_t)Process->UniqueProcessId, -1); 00150 } 00151 else 00152 { 00153 DPRINT1("No vsid to revoke\n"); 00154 } 00155 00156 if (Process != NULL && Process != CurrentProcess) 00157 { 00158 KeDetachProcess(); 00159 } 00160 } 00161 00162 VOID 00163 NTAPI 00164 MmFreePageTable(PEPROCESS Process, PVOID Address) 00165 { 00166 MmDeletePageTable(Process, Address); 00167 } 00168 00169 PVOID 00170 NTAPI 00171 MmGetPhysicalAddressProcess(PEPROCESS Process, PVOID Addr) 00172 { 00173 ppc_map_info_t info = { 0 }; 00174 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00175 info.addr = (vaddr_t)Addr; 00176 MmuInqPage(&info, 1); 00177 return (PVOID)info.phys; 00178 } 00179 00180 /* 00181 * @implemented 00182 */ 00183 PHYSICAL_ADDRESS NTAPI 00184 MmGetPhysicalAddress(PVOID vaddr) 00185 /* 00186 * FUNCTION: Returns the physical address corresponding to a virtual address 00187 */ 00188 { 00189 PHYSICAL_ADDRESS Addr; 00190 Addr.QuadPart = (ULONG)MmGetPhysicalAddressProcess(PsGetCurrentProcess()->UniqueProcessId, vaddr); 00191 return Addr; 00192 } 00193 00194 PFN_NUMBER 00195 NTAPI 00196 MmGetPfnForProcess(PEPROCESS Process, 00197 PVOID Address) 00198 { 00199 return((PFN_NUMBER)MmGetPhysicalAddressProcess(Process, Address) >> PAGE_SHIFT); 00200 } 00201 00202 VOID 00203 NTAPI 00204 MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN* WasDirty, PPFN_NUMBER Page) 00205 /* 00206 * FUNCTION: Delete a virtual mapping 00207 */ 00208 { 00209 ppc_map_info_t info = { 0 }; 00210 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00211 info.addr = (vaddr_t)Address; 00212 MmuUnmapPage(&info, 1); 00213 } 00214 00215 VOID 00216 NTAPI 00217 MmRawDeleteVirtualMapping(PVOID Address) 00218 { 00219 } 00220 00221 VOID 00222 NTAPI 00223 MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage, 00224 BOOLEAN* WasDirty, PPFN_NUMBER Page) 00225 /* 00226 * FUNCTION: Delete a virtual mapping 00227 */ 00228 { 00229 ppc_map_info_t info = { 0 }; 00230 00231 DPRINT("MmDeleteVirtualMapping(%x, %x, %d, %x, %x)\n", 00232 Process, Address, FreePage, WasDirty, Page); 00233 00234 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00235 info.addr = (vaddr_t)Address; 00236 MmuInqPage(&info, 1); 00237 00238 if (FreePage && info.phys) 00239 { 00240 MmReleasePageMemoryConsumer(MC_NPPOOL, info.phys >> PAGE_SHIFT); 00241 } 00242 00243 /* 00244 * Return some information to the caller 00245 */ 00246 if (WasDirty != NULL) 00247 { 00248 *WasDirty = !!(info.flags & MMU_PAGE_DIRTY); 00249 } 00250 if (Page != NULL) 00251 { 00252 *Page = info.phys >> PAGE_SHIFT; 00253 } 00254 } 00255 00256 VOID 00257 NTAPI 00258 MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, 00259 SWAPENTRY* SwapEntry) 00260 /* 00261 * FUNCTION: Delete a virtual mapping 00262 */ 00263 { 00264 ppc_map_info_t info = { 0 }; 00265 /* 00266 * Decrement the reference count for this page table. 00267 */ 00268 if (Process != NULL && 00269 ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL && 00270 Address < MmSystemRangeStart) 00271 { 00272 PUSHORT Ptrc; 00273 00274 Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable; 00275 MmFreePageTable(Process, Address); 00276 } 00277 00278 /* 00279 * Return some information to the caller 00280 */ 00281 MmuInqPage(&info, 1); 00282 *SwapEntry = info.phys; 00283 } 00284 00285 BOOLEAN 00286 NTAPI 00287 MmIsDirtyPage(PEPROCESS Process, PVOID Address) 00288 { 00289 ppc_map_info_t info = { 0 }; 00290 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00291 info.addr = (vaddr_t)Address; 00292 MmuInqPage(&info, 1); 00293 return !!(info.flags & MMU_PAGE_DIRTY); 00294 } 00295 00296 BOOLEAN 00297 NTAPI 00298 MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address) 00299 { 00300 ppc_map_info_t info = { 0 }; 00301 00302 if (Address < MmSystemRangeStart && Process == NULL) 00303 { 00304 DPRINT1("MmIsAccessedAndResetAccessPage is called for user space without a process.\n"); 00305 ASSERT(FALSE); 00306 } 00307 00308 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00309 info.addr = (vaddr_t)Address; 00310 MmuInqPage(&info, 1); 00311 return !!(info.flags /*& MMU_PAGE_ACCESS*/); 00312 } 00313 00314 VOID 00315 NTAPI 00316 MmSetCleanPage(PEPROCESS Process, PVOID Address) 00317 { 00318 } 00319 00320 VOID 00321 NTAPI 00322 MmSetDirtyPage(PEPROCESS Process, PVOID Address) 00323 { 00324 } 00325 00326 VOID 00327 NTAPI 00328 MmEnableVirtualMapping(PEPROCESS Process, PVOID Address) 00329 { 00330 } 00331 00332 BOOLEAN 00333 NTAPI 00334 MmIsPagePresent(PEPROCESS Process, PVOID Address) 00335 { 00336 ppc_map_info_t info = { 0 }; 00337 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00338 info.addr = (vaddr_t)Address; 00339 MmuInqPage(&info, 1); 00340 return !!info.phys; 00341 } 00342 00343 ULONGLONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address) 00344 { 00345 return 0; // XXX arty 00346 } 00347 00348 BOOLEAN 00349 NTAPI 00350 MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) 00351 { 00352 ULONG Entry; 00353 Entry = MmGetPageEntryForProcess(Process, Address); 00354 return !(Entry & PA_PRESENT) && Entry != 0 ? TRUE : FALSE; 00355 } 00356 00357 NTSTATUS 00358 NTAPI 00359 MmCreateVirtualMappingForKernel(PVOID Address, 00360 ULONG flProtect, 00361 PPFN_NUMBER Pages, 00362 ULONG PageCount) 00363 { 00364 ULONG i; 00365 PVOID Addr; 00366 00367 DPRINT("MmCreateVirtualMappingForKernel(%x, %x, %x, %d)\n", 00368 Address, flProtect, Pages, PageCount); 00369 00370 if (Address < MmSystemRangeStart) 00371 { 00372 DPRINT1("MmCreateVirtualMappingForKernel is called for user space\n"); 00373 ASSERT(FALSE); 00374 } 00375 00376 Addr = Address; 00377 00378 for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE)) 00379 { 00380 #if 0 00381 if (!(Attributes & PA_PRESENT) && Pages[i] != 0) 00382 { 00383 DPRINT1("Setting physical address but not allowing access at address " 00384 "0x%.8X with attributes %x/%x.\n", 00385 Addr, Attributes, flProtect); 00386 ASSERT(FALSE); 00387 } 00388 (void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes); 00389 #endif 00390 } 00391 00392 return(STATUS_SUCCESS); 00393 } 00394 00395 NTSTATUS 00396 NTAPI 00397 MmCreatePageFileMapping(PEPROCESS Process, 00398 PVOID Address, 00399 SWAPENTRY SwapEntry) 00400 { 00401 if (Process == NULL && Address < MmSystemRangeStart) 00402 { 00403 DPRINT1("No process\n"); 00404 ASSERT(FALSE); 00405 } 00406 if (Process != NULL && Address >= MmSystemRangeStart) 00407 { 00408 DPRINT1("Setting kernel address with process context\n"); 00409 ASSERT(FALSE); 00410 } 00411 if (SwapEntry & (1 << 31)) 00412 { 00413 ASSERT(FALSE); 00414 } 00415 00416 // XXX arty 00417 00418 return(STATUS_SUCCESS); 00419 } 00420 00421 00422 NTSTATUS 00423 NTAPI 00424 MmCreateVirtualMappingUnsafe(PEPROCESS Process, 00425 PVOID Address, 00426 ULONG flProtect, 00427 PPFN_NUMBER Pages, 00428 ULONG PageCount) 00429 { 00430 ULONG Attributes; 00431 PVOID Addr; 00432 ULONG i; 00433 ppc_map_info_t info = { 0 }; 00434 00435 DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n", 00436 Process, Address, flProtect, Pages, *Pages, PageCount); 00437 00438 if (Process == NULL) 00439 { 00440 if (Address < MmSystemRangeStart) 00441 { 00442 DPRINT1("No process\n"); 00443 ASSERT(FALSE); 00444 } 00445 if (PageCount > 0x10000 || 00446 (ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000) 00447 { 00448 DPRINT1("Page count to large\n"); 00449 ASSERT(FALSE); 00450 } 00451 } 00452 else 00453 { 00454 if (Address >= MmSystemRangeStart) 00455 { 00456 DPRINT1("Setting kernel address with process context\n"); 00457 ASSERT(FALSE); 00458 } 00459 if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE || 00460 (ULONG_PTR) Address / PAGE_SIZE + PageCount > 00461 (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE) 00462 { 00463 DPRINT1("Page Count to large\n"); 00464 ASSERT(FALSE); 00465 } 00466 } 00467 00468 Attributes = ProtectToFlags(flProtect); 00469 Addr = Address; 00470 00471 for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE)) 00472 { 00473 Process = PsGetCurrentProcess(); 00474 info.proc = ((Addr < MmSystemRangeStart) && Process) ? 00475 (int)Process->UniqueProcessId : 0; 00476 info.addr = (vaddr_t)Addr; 00477 info.flags = Attributes; 00478 MmuMapPage(&info, 1); 00479 //(void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes); 00480 if (Address < MmSystemRangeStart && 00481 ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL && 00482 Attributes & PA_PRESENT) 00483 { 00484 #if 0 00485 PUSHORT Ptrc; 00486 00487 Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable; 00488 00489 Ptrc[ADDR_TO_PAGE_TABLE(Addr)]++; 00490 #endif 00491 } 00492 } 00493 return(STATUS_SUCCESS); 00494 } 00495 00496 NTSTATUS 00497 NTAPI 00498 MmCreateVirtualMapping(PEPROCESS Process, 00499 PVOID Address, 00500 ULONG flProtect, 00501 PPFN_NUMBER Pages, 00502 ULONG PageCount) 00503 { 00504 ULONG i; 00505 00506 for (i = 0; i < PageCount; i++) 00507 { 00508 if (!MmIsUsablePage(Pages[i])) 00509 { 00510 DPRINT1("Page at address %x not usable\n", PFN_TO_PTE(Pages[i])); 00511 ASSERT(FALSE); 00512 } 00513 } 00514 00515 return(MmCreateVirtualMappingUnsafe(Process, 00516 Address, 00517 flProtect, 00518 Pages, 00519 PageCount)); 00520 } 00521 00522 ULONG 00523 NTAPI 00524 MmGetPageProtect(PEPROCESS Process, PVOID Address) 00525 { 00526 ULONG Protect = 0; 00527 ppc_map_info_t info = { 0 }; 00528 00529 info.proc = Process ? (int)Process->UniqueProcessId : 0; 00530 info.addr = (vaddr_t)Address; 00531 MmuInqPage(&info, 1); 00532 00533 if (!info.phys) { return PAGE_NOACCESS; } 00534 if (!(info.flags & MMU_KMASK)) 00535 { 00536 Protect |= PAGE_SYSTEM; 00537 if ((info.flags & MMU_KR) && (info.flags & MMU_KW)) 00538 Protect = PAGE_READWRITE; 00539 else if (info.flags & MMU_KR) 00540 Protect = PAGE_EXECUTE_READ; 00541 } 00542 else 00543 { 00544 if ((info.flags & MMU_UR) && (info.flags & MMU_UW)) 00545 Protect = PAGE_READWRITE; 00546 else 00547 Protect = PAGE_EXECUTE_READ; 00548 } 00549 return(Protect); 00550 } 00551 00552 VOID 00553 NTAPI 00554 MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) 00555 { 00556 //ULONG Attributes = 0; 00557 00558 DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n", 00559 Process, Address, flProtect); 00560 00561 #if 0 00562 Attributes = ProtectToPTE(flProtect); 00563 00564 Pt = MmGetPageTableForProcess(Process, Address, FALSE); 00565 if (Pt == NULL) 00566 { 00567 ASSERT(FALSE); 00568 } 00569 InterlockedExchange((PLONG)Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY))); 00570 MiFlushTlb(Pt, Address); 00571 #endif 00572 } 00573 00574 PVOID 00575 NTAPI 00576 MmCreateHyperspaceMapping(PFN_NUMBER Page) 00577 { 00578 PVOID Address; 00579 ppc_map_info_t info = { 0 }; 00580 00581 Address = (PVOID)((ULONG_PTR)HYPERSPACE * PAGE_SIZE); 00582 info.proc = 0; 00583 info.addr = (vaddr_t)Address; 00584 info.flags = MMU_KRW; 00585 MmuMapPage(&info, 1); 00586 00587 return Address; 00588 } 00589 00590 PFN_NUMBER 00591 NTAPI 00592 MmChangeHyperspaceMapping(PVOID Address, PFN_NUMBER NewPage) 00593 { 00594 PFN_NUMBER OldPage; 00595 ppc_map_info_t info = { 0 }; 00596 00597 info.proc = 0; 00598 info.addr = (vaddr_t)Address; 00599 MmuUnmapPage(&info, 1); 00600 OldPage = info.phys; 00601 info.phys = (paddr_t)NewPage; 00602 MmuMapPage(&info, 1); 00603 00604 return NewPage; 00605 } 00606 00607 PFN_NUMBER 00608 NTAPI 00609 MmDeleteHyperspaceMapping(PVOID Address) 00610 { 00611 ppc_map_info_t info = { 0 }; 00612 ASSERT (IS_HYPERSPACE(Address)); 00613 00614 info.proc = 0; 00615 info.addr = (vaddr_t)Address; 00616 00617 MmuUnmapPage(&info, 1); 00618 00619 return (PFN_NUMBER)info.phys; 00620 } 00621 00622 VOID 00623 INIT_FUNCTION 00624 NTAPI 00625 MmInitGlobalKernelPageDirectory(VOID) 00626 { 00627 } 00628 00629 VOID 00630 INIT_FUNCTION 00631 NTAPI 00632 MiInitPageDirectoryMap(VOID) 00633 { 00634 } 00635 00636 ULONG 00637 NTAPI 00638 MiGetUserPageDirectoryCount(VOID) 00639 { 00640 return 0; 00641 } 00642 00643 VOID 00644 NTAPI 00645 MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) 00646 { 00647 } 00648 00649 /* Create a simple, primitive mapping at the specified address on a new page */ 00650 NTSTATUS MmPPCCreatePrimitiveMapping(ULONG_PTR PageAddr) 00651 { 00652 NTSTATUS result; 00653 ppc_map_info_t info = { 0 }; 00654 info.flags = MMU_KRW; 00655 info.addr = (vaddr_t)PageAddr; 00656 result = MmuMapPage(&info, 1) ? STATUS_SUCCESS : STATUS_NO_MEMORY; 00657 return result; 00658 } 00659 00660 /* Use our primitive allocator */ 00661 PFN_NUMBER MmPPCPrimitiveAllocPage() 00662 { 00663 paddr_t Result = MmuGetPage(); 00664 DbgPrint("Got Page %x\n", Result); 00665 return Result / PAGE_SIZE; 00666 } 00667 00668 /* EOF */ Generated on Tue May 22 2012 04:30:56 for ReactOS by
1.7.6.1
|