ReactOS Fundraising Campaign 2012
 
€ 11,198 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

page.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 Thu Oct 25 2012 04:32:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.