kernel
Loading...
Searching...
No Matches
hypermap.c
Go to the documentation of this file.
1/*++
2
3Module Name:
4
5 hypermap.c
6
7Purpose:
8
9 This translation unit contains the implementation of the temporary mapping functions. (hyperspace)/s
10
11Author:
12
13 slep (Matanel) 2025.
14
15Revision History:
16
17--*/
18
19#include "../../includes/mm.h"
20#include "../../includes/mh.h"
21#include "../../assert.h"
22
23// The physical memory offset itself is the hypermap virtual address. This is ruled by not touching the 0x0 - 0x1000 physical addresses AT ALL (you may touch the physical addresses, but not map them with the PhysicalMemoryOffset virtual arithemtic.)
24#define HYPERMAP_VIRTUAL_ADDRESS PhysicalMemoryOffset
25
28
29#ifdef PERFORMANCE_ANALYTICS
30uint64_t g_HypermappingsDone;
31#endif
32
33#define LOCK_HYPERSPACE(PtrOldIrql) MsAcquireSpinlock(&HyperLock, PtrOldIrql)
34#define UNLOCK_HYPERSPACE(OldIrql) MsReleaseSpinlock(&HyperLock, OldIrql)
35
36void*
38 IN uint64_t PfnIndex,
39 OUT PIRQL OldIrql
40)
41
42/*++
43
44 Routine description:
45
46 Temporary maps the specified PFN Page into hyperspace and returns the virtual address mapped into.
47
48 ************************************
49 * *
50 * Returns with a spin lock held!!! * // thanks lou
51 * *
52 ************************************
53
54
55 Arguments:
56
57 [IN] PfnIndex - Page frame index to map.
58 [OUT] OldIrql - Pointer to store entry IRQL.
59
60 Return Values:
61
62 Valid Pointer to mapped region.
63
64--*/
65
66{
67 // First, lock the hyperspace.
68 LOCK_HYPERSPACE (OldIrql);
69
70 // Map the PFN into the page.
71 // We do not send an IPI, as we are in a spinlock.
72 // Besides, an IPI does not need to be used here, as the hyperspace is a one CPU exclusive object, 2 cpus cannot use it at the same time
73 // so their TLBs do not need to be updated for this VA.
74 PPFN_ENTRY pfn = INDEX_TO_PPFN (PfnIndex);
75 uint64_t physAddr = PPFN_TO_PHYSICAL_ADDRESS (pfn);
78
79 // Set PFN metadata.
80 pfn->State = PfnStateActive;
81 pfn->Descriptor.Mapping.PteAddress = pte;
82 pfn->Descriptor.Mapping.Vad = NULL;
83 g_pfnInUse = pfn;
84
85#ifdef PERFORMANCE_ANALYTICS
86 // No need for atomic increment, we are under spinlock.
87 g_HypermappingsDone++;
88#endif
89
90 // Return the virtual address (now mapped)
91 return (void*)HYPERMAP_VIRTUAL_ADDRESS;
92}
93
94void
96 IN IRQL OldIrql
97)
98
99/*++
100
101 Routine description:
102
103 Unlocks the hyperspace, clears previous mapping.
104
105 Arguments:
106
107 [IN] OldIrql - Entry IRQL given by MiMapPageInHyperspace
108
109 Return Values:
110
111 None.
112
113 Notes:
114
115 Does not release the PFN that was given, caller must do so.
116
117--*/
118
119{
120 // Assertion that the hyperspace lock must be locked already (double unlock catch)
121 assert((HyperLock.locked) == 1, "Double hypermap unlock");
122 assert((g_pfnInUse) != 0, "No PFN when releasing hyperspace.");
124
125 // Clear the PTE present bit (to prevent use after free)
127 invlpg((void*)HYPERMAP_VIRTUAL_ADDRESS); // No need to call the MiInvalidateTlb (IPI) as this addr is spinlock protected (and next access rewrites the PTE and does invplg in MI_WRITE_PTE)
128
129 // After MiUnmapPte changed the pfn metadata, we change it once again to invalidate it.
130 pfn->Descriptor.Mapping.PteAddress = NULL;
131 pfn->Descriptor.Mapping.Vad = NULL;
133 g_pfnInUse = NULL;
134
135 // We do not release the PFN, caller must do so, because it might have other uses with it.
136
137 // Unlock the hyperspace.
138 UNLOCK_HYPERSPACE (OldIrql);
139}
#define IN
Definition annotations.h:8
#define OUT
Definition annotations.h:9
#define assert(...)
Definition assert.h:57
enum _IRQL IRQL
enum _IRQL * PIRQL
PPFN_ENTRY g_pfnInUse
Definition hypermap.c:27
#define LOCK_HYPERSPACE(PtrOldIrql)
Definition hypermap.c:33
#define HYPERMAP_VIRTUAL_ADDRESS
Definition hypermap.c:24
void * MiMapPageInHyperspace(IN uint64_t PfnIndex, OUT PIRQL OldIrql)
Definition hypermap.c:37
void MiUnmapHyperSpaceMap(IN IRQL OldIrql)
Definition hypermap.c:95
SPINLOCK HyperLock
Definition hypermap.c:26
#define UNLOCK_HYPERSPACE(OldIrql)
Definition hypermap.c:34
FORCEINLINE void invlpg(void *m)
Definition intrin.h:205
PMMPTE MiGetPtePointer(IN uintptr_t va)
Definition map.c:76
@ PAGE_RW
Definition mm.h:311
@ PAGE_PRESENT
Definition mm.h:307
@ PfnStateTransition
Definition mm.h:281
@ PfnStateActive
Definition mm.h:276
struct _MMPTE * PMMPTE
#define PPFN_TO_PHYSICAL_ADDRESS(PPFN)
Definition mm.h:136
#define MI_WRITE_PTE_NO_IPI(_PtePointer, _Va, _Pa, _Flags)
Definition mm.h:115
#define INDEX_TO_PPFN(Index)
Definition mm.h:62
struct _PFN_ENTRY * PPFN_ENTRY
struct _SPINLOCK SPINLOCK
struct _MMPTE::@172372265215056352375070220246156106027174106113::@200357034104227323320222006243127050212100105247 Hard
uint64_t Present
Definition mm.h:430
union _PFN_ENTRY::@217024126340164016372152071216274230164113211246 Descriptor
struct _PFN_ENTRY::@217024126340164016372152071216274230164113211246::@301110335271023021153236134322146064331241142124 Mapping
uint8_t State
Definition mm.h:471
PMMPTE PteAddress
Definition mm.h:482
struct _MMVAD * Vad
Definition mm.h:481