4 * Virtual Memory Manager
15 #define PADDR_MASK 0x7FFFFFFF##FFFFF000
17 #define PF_PRESENT 0x1
21 #define PF_PAGED 0x400
22 #define PF_NX 0x80000000##00000000
25 #define PAGETABLE(idx) (*((tPAddr*)MM_FRACTAL_BASE+(idx)))
26 #define PAGEDIR(idx) PAGETABLE((MM_FRACTAL_BASE>>12)+((idx)&0x7FFFFFF))
27 #define PAGEDIRPTR(idx) PAGEDIR((MM_FRACTAL_BASE>>21)+((idx)&0x3FFFF))
28 #define PAGEMAPLVL4(idx) PAGEDIRPTR((MM_FRACTAL_BASE>>30)+((idx)&0x1FF))
33 void MM_InitVirt(void)
39 * \brief Map a physical page to a virtual one
41 int MM_Map(tVAddr VAddr, tPAddr PAddr)
46 if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
50 PAGEMAPLVL4(VAddr >> 39) = tmp | 3;
51 memset( &PAGEDIRPTR( (VAddr>>39)<<9 ), 0, 4096 );
55 if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
59 PAGEDIRPTR(VAddr >> 30) = tmp | 3;
60 memset( &PAGEDIR( (VAddr>>30)<<9 ), 0, 4096 );
64 if( !(PAGEDIR(VAddr >> 21) & 1) )
68 PAGEDIR(VAddr >> 21) = tmp | 3;
69 memset( &PAGETABLE( (VAddr>>21)<<9 ), 0, 4096 );
72 // Check if this virtual address is already mapped
73 if( PAGETABLE(VAddr >> 12) & 1 )
76 PAGETABLE(VAddr >> 12) = PAddr | 3;
82 * \brief Removed a mapped page
84 void MM_Unmap(tVAddr VAddr)
87 if( !(PAGEMAPLVL4(VAddr >> 39) & 1) ) return ;
89 if( !(PAGEDIRPTR(VAddr >> 30) & 1) ) return ;
91 if( !(PAGEDIR(VAddr >> 21) & 1) ) return ;
93 PAGETABLE(VAddr >> 12) = 0;
97 * \brief Allocate a block of memory at the specified virtual address
99 tPAddr MM_Allocate(tVAddr VAddr)
103 ret = MM_AllocPhys();
106 if( !MM_Map(VAddr, ret) )
115 void MM_Deallocate(tVAddr VAddr)
119 phys = MM_GetPhysAddr(VAddr);
128 * \brief Get the physical address of a virtual location
130 tPAddr MM_GetPhysAddr(tVAddr Addr)
132 if( !(PAGEMAPLVL4(Addr >> 39) & 1) )
134 if( !(PAGEDIRPTR(Addr >> 30) & 1) )
136 if( !(PAGEDIR(Addr >> 21) & 1) )
138 if( !(PAGETABLE(Addr >> 12) & 1) )
141 return (PAGETABLE(Addr >> 12) & ~0xFFF) | (Addr & 0xFFF);
145 * \brief Sets the flags on a page
147 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
152 if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
154 if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
156 if( !(PAGEDIR(VAddr >> 21) & 1) )
158 if( !(PAGETABLE(VAddr >> 12) & 1) )
162 ent = &PAGETABLE(VAddr >> 12);
165 if( Mask & MM_PFLAG_RO )
167 if( Flags & MM_PFLAG_RO ) {
176 if( Mask & MM_PFLAG_KERNEL )
178 if( Flags & MM_PFLAG_KERNEL ) {
187 if( Mask & MM_PFLAG_COW )
189 if( Flags & MM_PFLAG_COW ) {
200 if( Mask & MM_PFLAG_EXEC )
202 if( Flags & MM_PFLAG_EXEC ) {
212 * \brief Get the flags applied to a page
214 Uint MM_GetFlags(tVAddr VAddr)
220 if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
222 if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
224 if( !(PAGEDIR(VAddr >> 21) & 1) )
226 if( !(PAGETABLE(VAddr >> 12) & 1) )
230 ent = &PAGETABLE(VAddr >> 12);
233 if( !(*ent & PF_WRITE) ) ret |= MM_PFLAG_RO;
235 if( !(*ent & PF_USER) ) ret |= MM_PFLAG_KERNEL;
237 if( *ent & PF_COW ) ret |= MM_PFLAG_COW;
239 if( !(*ent & PF_NX) ) ret |= MM_PFLAG_EXEC;
244 // --- Hardware Mappings ---
246 * \brief Map a range of hardware pages
248 tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
250 Log_KernelPanic("MM", "TODO: Implement MM_MapHWPages");
255 * \brief Free a range of hardware pages
257 void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
259 Log_KernelPanic("MM", "TODO: Implement MM_UnmapHWPages");
262 // --- Tempory Mappings ---
263 tVAddr MM_MapTemp(tPAddr PAddr)
265 Log_KernelPanic("MM", "TODO: Implement MM_MapTemp");
269 void MM_FreeTemp(tVAddr VAddr)
271 Log_KernelPanic("MM", "TODO: Implement MM_FreeTemp");
276 // --- Address Space Clone --
277 tPAddr MM_Clone(void)
281 // #1 Create a copy of the PML4
282 ret = MM_AllocPhys();
285 // #2 Alter the fractal pointer
286 // #3 Set Copy-On-Write to all user pages
291 void MM_ClearUser(void)
294 // #1 Traverse the structure < 2^47, Deref'ing all pages
295 // #2 Free tables/dirs/pdps once they have been cleared
297 for( addr = 0; addr < 0x800000000000; )
299 if( PAGEMAPLVL4(addr >> PML4_SHIFT) & 1 )
301 if( PAGEDIRPTR(addr >> PDP_SHIFT) & 1 )
303 if( PAGEDIR(addr >> PDIR_SHIFT) & 1 )
306 if( PAGETABLE(addr >> PTAB_SHIFT) & 1 ) {
307 MM_DerefPhys( PAGETABLE(addr >> PTAB_SHIFT) & PADDR_MASK );
308 PAGETABLE(addr >> PTAB_SHIFT) = 0;
310 addr += 1 << PTAB_SHIFT;
311 // Dereference the PDIR Entry
312 if( (addr + (1 << PTAB_SHIFT)) >> PDIR_SHIFT != (addr >> PDIR_SHIFT) ) {
313 MM_DerefPhys( PAGEMAPLVL4(addr >> PDIR_SHIFT) & PADDR_MASK );
314 PAGEDIR(addr >> PDIR_SHIFT) = 0;
318 addr += 1 << PDIR_SHIFT;
321 // Dereference the PDP Entry
322 if( (addr + (1 << PDIR_SHIFT)) >> PDP_SHIFT != (addr >> PDP_SHIFT) ) {
323 MM_DerefPhys( PAGEMAPLVL4(addr >> PDP_SHIFT) & PADDR_MASK );
324 PAGEDIRPTR(addr >> PDP_SHIFT) = 0;
328 addr += 1 << PDP_SHIFT;
331 // Dereference the PML4 Entry
332 if( (addr + (1 << PDP_SHIFT)) >> PML4_SHIFT != (addr >> PML4_SHIFT) ) {
333 MM_DerefPhys( PAGEMAPLVL4(addr >> PML4_SHIFT) & PADDR_MASK );
334 PAGEMAPLVL4(addr >> PML4_SHIFT) = 0;
338 addr += (tVAddr)1 << PML4_SHIFT;