test: mips/hypermap.c File Reference

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

# hypermap.c File Reference

`#include "mi.h"`

Go to the source code of this file.

## Functions

PVOID | MiMapPageInHyperSpace (IN ULONG PageFrameIndex, IN PKIRQL OldIrql)
PVOID | MiMapImageHeaderInHyperSpace (IN ULONG PageFrameIndex)
VOID | MiUnmapImageHeaderInHyperSpace (VOID)

## Function Documentation

PVOID MiMapImageHeaderInHyperSpace | ( | IN ULONG | PageFrameIndex | ) |

Definition at line 165 of file mips/hypermap.c.

References ASSERT, DbgPrint, Executive, FALSE, IMAGE_MAPPING_PTE, KeBugCheck(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KernelMode, KeWaitForSingleObject(), LOCK_PFN, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MmImageMappingPteEvent, MmWorkingSetList, NULL, _MMPTE::u, UNLOCK_PFN, UNLOCK_PFN_AND_THEN_WAIT, ValidPtePte, and _MMWSL::WaitingForImageMapping.

    00171                    :
    00172
    00173     The physical address of the specified page is returned.
    00174
    00175 Arguments:
    00176
    00177     PageFrameIndex - Supplies the physical page number to map.
    00178
    00179 Return Value:
    00180
    00181     Returns the virtual address where the specified physical page was
    00182     mapped.
    00183
    00184 Environment:
    00185
    00186     Kernel mode.
    00187
    00188 --*/
    00189
    00190 {
    00191     MMPTE TempPte;
    00192     PMMPTE PointerPte;
    00193     KIRQL OldIrql;
    00194
    00195 #if DBG
    00196     if (PageFrameIndex == 0) {
    00197         DbgPrint("attempt to map physical page 0 in hyper space\n");
    00198         KeBugCheck (MEMORY_MANAGEMENT);
    00199     }
    00200 #endif //DBG
    00201
    00202     //
    00203     // Avoid address aliasing problem on r4000.
    00204     //
    00205
    00206     PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE);
    00207
    00208     LOCK_PFN (OldIrql);
    00209
    00210     while (PointerPte->u.Long != 0) {
    00211
    00212         //
    00213         // If there is no event specified, set one up.
    00214         //
    00215
    00216         if (MmWorkingSetList->WaitingForImageMapping == (PKEVENT)NULL) {
    00217
    00218             //
    00219             // Set the global event into the field and wait for it.
    00220             //
    00221
    00222             MmWorkingSetList->WaitingForImageMapping = &MmImageMappingPteEvent;
    00223         }
    00224
    00225         //
    00226         // Release the PFN lock and wait on the event in an
    00227         // atomic operation.
    00228         //
    00229
    00230         KeEnterCriticalRegion();
    00231         UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
    00232
    00233         KeWaitForSingleObject(MmWorkingSetList->WaitingForImageMapping,
    00234                               Executive,
    00235                               KernelMode,
    00236                               FALSE,
    00237                               (PLARGE_INTEGER)NULL);
    00238         KeLeaveCriticalRegion();
    00239
    00240         LOCK_PFN (OldIrql);
    00241     }
    00242
    00243     ASSERT (PointerPte->u.Long == 0);
    00244
    00245     TempPte = ValidPtePte;
    00246     TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
    00247
    00248     *PointerPte = TempPte;
    00249
    00250     UNLOCK_PFN (OldIrql);
    00251
    00252     return (PVOID)MiGetVirtualAddressMappedByPte (PointerPte);
    00253 }

PVOID MiMapPageInHyperSpace | ( | IN ULONG | PageFrameIndex,
|  | IN PKIRQL | OldIrql
| ) |

Definition at line 30 of file mips/hypermap.c.

References ASSERT, DbgPrint, FALSE, KeBugCheck(), KeFlushEntireTb(), KSEG0_BASE, LOCK_HYPERSPACE, MI_PFN_ELEMENT, MiGetVirtualAddressMappedByPte, MM_COLOR_MASK, MM_PAGES_IN_KSEG0, MmFirstReservedMappingPte, NUMBER_OF_MAPPING_PTES, PAGE_SHIFT, PTE_SHIFT, TRUE, _MMPTE::u, _MMPFN::u3, and ValidPtePte.

    00037                    :
    00038
    00039     This routine returns the physical address of the page.
    00040
    00041     ************************************
    00042     *                                  *
    00043     * Returns with a spin lock held!!! *
    00044     *                                  *
    00045     ************************************
    00046
    00047 Arguments:
    00048
    00049     PageFrameIndex - Supplies the physical page number to map.
    00050
    00051 Return Value:
    00052
    00053     Returns the address where the requested page was mapped.
    00054
    00055     RETURNS WITH THE HYPERSPACE SPIN LOCK HELD!!!!
    00056
    00057     The routine MiUnmapHyperSpaceMap MUST be called to release the lock!!!!
    00058
    00059 Environment:
    00060
    00061     Kernel mode.
    00062
    00063 --*/
    00064
    00065 {
    00066     PMMPFN Pfn1;
    00067     ULONG i;
    00068     PMMPTE PointerPte;
    00069     PMMPTE NextPte;
    00070     MMPTE TempPte;
    00071     ULONG LastEntry;
    00072
    00073 #if DBG
    00074     if (PageFrameIndex == 0) {
    00075         DbgPrint("attempt to map physical page 0 in hyper space\n");
    00076         KeBugCheck (MEMORY_MANAGEMENT);
    00077     }
    00078 #endif //DBG
    00079
    00080     //
    00081     // Pages must be aligned on their natural boundaries.
    00082     //
    00083
    00084     Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    00085     i = Pfn1->u3.e1.PageColor;
    00086     if ((i == (PageFrameIndex & MM_COLOR_MASK)) &&
    00087         (PageFrameIndex < MM_PAGES_IN_KSEG0)) {
    00088
    00089         //
    00090         // Virtual and physical alignment match, return the KSEG0 address
    00091         // for this page.
    00092         //
    00093
    00094         LOCK_HYPERSPACE (OldIrql);
    00095         return (PVOID)(KSEG0_BASE + (PageFrameIndex << PAGE_SHIFT));
    00096     }
    00097
    00098     //
    00099     // Find the proper location in hyper space and map the page there.
    00100     //
    00101
    00102     LOCK_HYPERSPACE (OldIrql);
    00103     PointerPte = MmFirstReservedMappingPte + i;
    00104     if (PointerPte->u.Hard.Valid == 1 ) {
    00105
    00106         //
    00107         // All the pages in reserved for mapping have been used,
    00108         // flush the TB and reinitialize the pages.
    00109         //
    00110
    00111         RtlZeroMemory ((PVOID)MmFirstReservedMappingPte,
    00112                        ( NUMBER_OF_MAPPING_PTES + 1) * sizeof (MMPTE));
    00113         KeFlushEntireTb (TRUE, FALSE);
    00114
    00115         LastEntry = NUMBER_OF_MAPPING_PTES - MM_COLOR_MASK;
    00116         NextPte = MmFirstReservedMappingPte;
    00117         while (NextPte <= (MmFirstReservedMappingPte + MM_COLOR_MASK)) {
    00118             NextPte->u.Hard.PageFrameNumber = LastEntry;
    00119             NextPte += 1;
    00120         }
    00121     }
    00122
    00123     //
    00124     // Locate next entry in list and reset the next entry in the
    00125     // list.  The list is organized thusly:
    00126     //
    00127     // The first N elements corresponding to the alignment mask + 1
    00128     // contain in their page frame number fields the value of the
    00129     // last free mapping PTE with this alignment.  However, if
    00130     // the valid bit is set, this PTE has been used and the TB
    00131     // must be flushed and the list reinitialized.
    00132     //
    00133
    00134     //
    00135     // Get the offset to the first free PTE.
    00136     //
    00137
    00138     i = PointerPte->u.Hard.PageFrameNumber;
    00139
    00140     //
    00141     // Change the offset for the next time through.
    00142     //
    00143
    00144     PointerPte->u.Hard.PageFrameNumber = i - (MM_COLOR_MASK + 1);
    00145
    00146     //
    00147     // Point to the free entry and make it valid.
    00148     //
    00149
    00150     PointerPte += i;
    00151
    00152     ASSERT (PointerPte->u.Hard.Valid == 0);
    00153
    00154     TempPte = ValidPtePte;
    00155     TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
    00156     *PointerPte = TempPte;
    00157
    00158     ASSERT ((((ULONG)PointerPte >> PTE_SHIFT) & MM_COLOR_MASK) ==
    00159          (((ULONG)Pfn1->u3.e1.PageColor)));
    00160
    00161     return MiGetVirtualAddressMappedByPte (PointerPte);
    00162 }

VOID MiUnmapImageHeaderInHyperSpace | ( | VOID |  | ) |

Definition at line 256 of file mips/hypermap.c.

References ASSERT, Event(), FALSE, IMAGE_MAPPING_PTE, KeFlushSingleTb(), KePulseEvent(), LOCK_PFN, MiGetPteAddress, MmWorkingSetList, NULL, TRUE, _MMPTE::u, UNLOCK_PFN, and _MMWSL::WaitingForImageMapping.

    00262                    :
    00263
    00264     This procedure unmaps the PTE reserved for mapping the image
    00265     header, flushes the TB, and, if the WaitingForImageMapping field
    00266     is not NULL, sets the specified event.
    00267
    00268     On the MIPS serries, no action is required as the physical address
    00269     of the page is used.
    00270
    00271 Arguments:
    00272
    00273     None.
    00274
    00275 Return Value:
    00276
    00277     None.
    00278
    00279 Environment:
    00280
    00281     Kernel mode.
    00282
    00283 --*/
    00284
    00285 {
    00286     MMPTE TempPte;
    00287     PMMPTE PointerPte;
    00288     KIRQL OldIrql;
    00289     PKEVENT Event;
    00290
    00291     PointerPte = MiGetPteAddress (IMAGE_MAPPING_PTE);
    00292
    00293     TempPte.u.Long = 0;
    00294
    00295     LOCK_PFN (OldIrql);
    00296
    00297     //
    00298     // Capture the current state of the event field and clear it out.
    00299     //
    00300
    00301     Event = MmWorkingSetList->WaitingForImageMapping;
    00302
    00303     MmWorkingSetList->WaitingForImageMapping = (PKEVENT)NULL;
    00304
    00305     ASSERT (PointerPte->u.Long != 0);
    00306
    00307     KeFlushSingleTb (IMAGE_MAPPING_PTE,
    00308                      TRUE,
    00309                      FALSE,
    00310                      (PHARDWARE_PTE)PointerPte,
    00311                      TempPte.u.Hard);
    00312
    00313     UNLOCK_PFN (OldIrql);
    00314
    00315     if (Event != (PKEVENT)NULL) {
    00316
    00317         //
    00318         // If there was an event specified, set the event.
    00319         //
    00320
    00321         KePulseEvent (Event, 0, FALSE);
    00322     }
    00323
    00324     return;
    00325 }
    }