test: hypermap.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# hypermap.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004 Copyright (c) 1992  Digital Equipment Corporation
    00005
    00006 Module Name:
    00007
    00008    hypermap.c
    00009
    00010 Abstract:
    00011
    00012     This module contains the routines which map physical pages into
    00013     reserved PTEs within hyper space.
    00014
    00015     This module is machine dependent.  This version is targetted
    00016     for ALPHA uses KSEG0 (32bit super-page) to map the pages at their physical
    00017     addresses.
    00018
    00019 Author:
    00020
    00021     Lou Perazzoli (loup) 5-Apr-1989
    00022     Joe Notarangelo 23-Apr-1992   ALPHA version from MIPS version
    00023
    00024 Revision History:
    00025
    00026     Chao Chen 21-Aug-1995 Fixed accessing pages above 1 gig problem through
    00027                           hyperspace.
    00028
    00029 --*/
    00030
    00031 #include "mi.h"
    00032
    00033
    00034 PVOID
    00035 MiMapPageInHyperSpace (
    00036     IN ULONG PageFrameIndex,
    00037     IN PKIRQL OldIrql
    00038     )
    00039
    00040 /*++
    00041
    00042 Routine Description:
    00043
    00044     This routine returns the physical address of the page.
    00045
    00046     ************************************
    00047     *                                  *
    00048     * Returns with a spin lock held!!! *
    00049     *                                  *
    00050     ************************************
    00051
    00052 Arguments:
    00053
    00054     PageFrameIndex - Supplies the physical page number to map.
    00055
    00056 Return Value:
    00057
    00058     Returns the address where the requested page was mapped.
    00059
    00060     RETURNS WITH THE HYPERSPACE SPIN LOCK HELD!!!!
    00061
    00062     The routine MiUnmapHyperSpaceMap MUST be called to release the lock!!!!
    00063
    00064 Environment:
    00065
    00066     kernel mode.
    00067
    00068 --*/
    00069
    00070 {
    00071     PMMPTE PointerPte;
    00072     MMPTE TempPte;
    00073     ULONG offset;
    00074
    00075 #if DBG
    00076     if (PageFrameIndex == 0) {
    00077         DbgPrint("attempt to map physical page 0 in hyper space\n");
    00078         KeBugCheck (MEMORY_MANAGEMENT);
    00079     }
    00080 #endif //DBG
    00081
    00082     //
    00083     // If the page is below 1GB physical, then it can be mapped via
    00084     // KSEG0.
    00085     //
    00086
    00087     LOCK_HYPERSPACE (OldIrql);
    00088
    00089     if (PageFrameIndex < MM_PAGES_IN_KSEG0) {
    00090         return (PVOID)(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
    00091     }
    00092
    00093     PointerPte = MmFirstReservedMappingPte;
    00094     if (PointerPte->u.Hard.Valid == 1) {
    00095
    00096         //
    00097         // All the reserved PTEs have been used, make
    00098         // them all invalid.
    00099         //
    00100
    00101         MI_MAKING_MULTIPLE_PTES_INVALID (FALSE);
    00102
    00103         RtlZeroMemory (MmFirstReservedMappingPte,
    00104                        (NUMBER_OF_MAPPING_PTES + 1) * sizeof(MMPTE));
    00105
    00106         //
    00107         // Use the page frame number field of the first PTE as an
    00108         // offset into the available mapping PTEs.
    00109         //
    00110
    00111         PointerPte->u.Hard.PageFrameNumber = NUMBER_OF_MAPPING_PTES;
    00112
    00113         //
    00114         // Flush entire TB only on this processor.
    00115         //
    00116
    00117         KeFlushEntireTb (TRUE, FALSE);
    00118     }
    00119
    00120     //
    00121     // Get offset to first free PTE.
    00122     //
    00123
    00124     offset = PointerPte->u.Hard.PageFrameNumber;
    00125
    00126     //
    00127     // Change offset for next time through.
    00128     //
    00129
    00130     PointerPte->u.Hard.PageFrameNumber = offset - 1;
    00131
    00132     //
    00133     // Point to free entry and make it valid.
    00134     //
    00135
    00136     PointerPte += offset;
    00137     ASSERT (PointerPte->u.Hard.Valid == 0);
    00138
    00139
    00140     TempPte = ValidPtePte;
    00141     TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
    00142     *PointerPte = TempPte;
    00143
    00144     //
    00145     // Return the VA that map the page.
    00146     //
    00147
    00148     return MiGetVirtualAddressMappedByPte (PointerPte);
    00149 }
    00150
    00151
    00152 PVOID
    00153 MiMapImageHeaderInHyperSpace (
    00154     IN ULONG PageFrameIndex
    00155     )
    00156
    00157 /*++
    00158
    00159 Routine Description:
    00160
    00161     The physical address of the specified page is returned.
    00162
    00163 Arguments:
    00164
    00165     PageFrameIndex - Supplies the physical page number to map.
    00166
    00167 Return Value:
    00168
    00169     Returns the virtual address where the specified physical page was
    00170     mapped.
    00171
    00172 Environment:
    00173
    00174     Kernel mode.
    00175
    00176 --*/
    00177
    00178 {
    00179     MMPTE TempPte;
    00180     PMMPTE PointerPte;
    00181     KIRQL OldIrql;
    00182
    00183 #if DBG
    00184
    00185     if (PageFrameIndex == 0) {
    00186         DbgPrint("attempt to map physical page 0 in hyper space\n");
    00187         KeBugCheck (MEMORY_MANAGEMENT);
    00188     }
    00189
    00190 #endif //DBG
    00191
    00192     PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE);
    00193
    00194     LOCK_PFN (OldIrql);
    00195
    00196     while (PointerPte->u.Long != 0) {
    00197
    00198         //
    00199         // If there is no event specified, set one up.
    00200         //
    00201
    00202         if (MmWorkingSetList->WaitingForImageMapping == (PKEVENT)NULL) {
    00203
    00204             //
    00205             // Set the global event into the field and wait for it.
    00206             //
    00207
    00208             MmWorkingSetList->WaitingForImageMapping = &MmImageMappingPteEvent;
    00209         }
    00210
    00211         //
    00212         // Release the PFN lock and wait on the event in an
    00213         // atomic operation.
    00214         //
    00215
    00216         KeEnterCriticalRegion();
    00217         UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
    00218
    00219         KeWaitForSingleObject(MmWorkingSetList->WaitingForImageMapping,
    00220                               Executive,
    00221                               KernelMode,
    00222                               FALSE,
    00223                               (PLARGE_INTEGER)NULL);
    00224         KeLeaveCriticalRegion();
    00225
    00226         LOCK_PFN (OldIrql);
    00227     }
    00228
    00229     ASSERT (PointerPte->u.Long == 0);
    00230
    00231     TempPte = ValidPtePte;
    00232     TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
    00233
    00234     *PointerPte = TempPte;
    00235
    00236     UNLOCK_PFN (OldIrql);
    00237
    00238     return (PVOID)MiGetVirtualAddressMappedByPte (PointerPte);
    00239 }
    00240
    00241
    00242 VOID
    00243 MiUnmapImageHeaderInHyperSpace (
    00244     VOID
    00245     )
    00246
    00247 /*++
    00248
    00249 Routine Description:
    00250
    00251     This procedure unmaps the PTE reserved for mapping the image
    00252     header, flushes the TB, and, if the WaitingForImageMapping field
    00253     is not NULL, sets the specified event.
    00254
    00255     On ALPHA, no action is required as the super-page address of the page
    00256     was used.
    00257
    00258 Arguments:
    00259
    00260     None.
    00261
    00262 Return Value:
    00263
    00264     None.
    00265
    00266 Environment:
    00267
    00268     Kernel mode.
    00269
    00270 --*/
    00271
    00272 {
    00273     MMPTE TempPte;
    00274     PMMPTE PointerPte;
    00275     KIRQL OldIrql;
    00276     PKEVENT Event;
    00277
    00278     PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE);
    00279
    00280     TempPte.u.Long = 0;
    00281
    00282     LOCK_PFN (OldIrql);
    00283
    00284     //
    00285     // Capture the current state of the event field and clear it out.
    00286     //
    00287
    00288     Event = MmWorkingSetList->WaitingForImageMapping;
    00289
    00290     MmWorkingSetList->WaitingForImageMapping = (PKEVENT)NULL;
    00291
    00292     ASSERT (PointerPte->u.Long != 0);
    00293
    00294     KeFlushSingleTb (IMAGE_MAPPING_PTE, TRUE, FALSE,
    00295                      (PHARDWARE_PTE)PointerPte, TempPte.u.Hard);
    00296
    00297     UNLOCK_PFN (OldIrql);
    00298
    00299     if (Event != (PKEVENT)NULL) {
    00300
    00301         //
    00302         // If there was an event specified, set the event.
    00303         //
    00304
    00305         KePulseEvent (Event, 0, FALSE);
    00306     }
    00307
    00308     return;
    00309 }
    00310
    00311
    00312 PVOID
    00313 MiMapPageToZeroInHyperSpace (
    00314     IN ULONG PageFrameIndex
    00315     )
    00316
    00317 /*++
    00318
    00319 Routine Description:
    00320
    00321     This procedure maps the specified physical page into hyper space
    00322     and returns the virtual address which maps the page.
    00323
    00324     NOTE: it maps it into the same location reserved for fork operations!!
    00325     This is only to be used by the zeroing page thread.
    00326
    00327
    00328 Arguments:
    00329
    00330     PageFrameIndex - Supplies the physical page number to map.
    00331
    00332 Return Value:
    00333
    00334     Returns the virtual address where the specified physical page was
    00335     mapped.
    00336
    00337 Environment:
    00338
    00339     Must be holding the PFN lock.
    00340
    00341 --*/
    00342
    00343 {
    00344     MMPTE TempPte;
    00345     PMMPTE PointerPte;
    00346     PVOID MappedAddress;
    00347
    00348 #if DBG
    00349     if (PageFrameIndex == 0) {
    00350         DbgPrint("attempt to map physical page 0 in hyper space\n");
    00351         KeBugCheck (MEMORY_MANAGEMENT);
    00352     }
    00353 #endif //DBG
    00354
    00355     //
    00356     // If the page is below 1GB physical then it can be mapped via
    00357     // KSEG0.
    00358     //
    00359
    00360     if (PageFrameIndex < MM_PAGES_IN_KSEG0) {
    00361         return (PVOID)(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
    00362     }
    00363
    00364     MM_PFN_LOCK_ASSERT();
    00365
    00366     PointerPte = MiGetPteAddress (ZEROING_PAGE_PTE);
    00367     MappedAddress = MiGetVirtualAddressMappedByPte (PointerPte);
    00368
    00369     TempPte.u.Long = 0;
    00370
    00371     KeFlushSingleTb (MappedAddress,
    00372                      TRUE,
    00373                      FALSE,
    00374                      (PHARDWARE_PTE)PointerPte, TempPte.u.Hard);
    00375
    00376     TempPte = ValidPtePte;
    00377     TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
    00378
    00379     *PointerPte = TempPte;
    00380
    00381     return MappedAddress;
    00382 }