slight change to memory map
[tpg/acess2.git] / Kernel / arch / x86_64 / mm_virt.c
index 4107575..19bf72f 100644 (file)
 #define PDIR_SHIFT     21
 #define PTAB_SHIFT     12
 
+#define        PADDR_MASK      0x7FFFFFFF##FFFFF000
+
 #define        PF_PRESENT      0x1
 #define        PF_WRITE        0x2
 #define        PF_USER         0x4
-#define        PF_NX           0x80000000##00000000
 #define        PF_COW          0x200
 #define        PF_PAGED        0x400
+#define        PF_NX           0x80000000##00000000
 
 // === MACROS ===
 #define PAGETABLE(idx) (*((tPAddr*)MM_FRACTAL_BASE+(idx)))
 #define PAGEDIR(idx)   PAGETABLE((MM_FRACTAL_BASE>>12)+((idx)&0x7FFFFFF))
-#define PAGEDIRPTR(idx)        PAGETABLE((MM_FRACTAL_BASE>>21)+((idx)&0x3FFFF))
-#define PAGEMAPLVL4(idx)       PAGETABLE((MM_FRACTAL_BASE>>30)+((idx)&0x1FF))
+#define PAGEDIRPTR(idx)        PAGEDIR((MM_FRACTAL_BASE>>21)+((idx)&0x3FFFF))
+#define PAGEMAPLVL4(idx)       PAGEDIRPTR((MM_FRACTAL_BASE>>30)+((idx)&0x1FF))
 
 // === GLOBALS ===
 
@@ -76,6 +78,21 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr)
        return 1;
 }
 
+/**
+ * \brief Removed a mapped page
+ */
+void MM_Unmap(tVAddr VAddr)
+{
+       // Check PML4
+       if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )   return ;
+       // Check PDP
+       if( !(PAGEDIRPTR(VAddr >> 30) & 1) )    return ;
+       // Check Page Dir
+       if( !(PAGEDIR(VAddr >> 21) & 1) )       return ;
+       
+       PAGETABLE(VAddr >> 12) = 0;
+}
+
 /**
  * \brief Allocate a block of memory at the specified virtual address
  */
@@ -95,6 +112,18 @@ tPAddr MM_Allocate(tVAddr VAddr)
        return ret;
 }
 
+void MM_Deallocate(tVAddr VAddr)
+{
+       tPAddr  phys;
+       
+       phys = MM_GetPhysAddr(VAddr);
+       if(!phys)       return ;
+       
+       MM_Unmap(VAddr);
+       
+       MM_DerefPhys(phys);
+}
+
 /**
  * \brief Get the physical address of a virtual location
  */
@@ -179,6 +208,9 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
        }
 }
 
+/**
+ * \brief Get the flags applied to a page
+ */
 Uint MM_GetFlags(tVAddr VAddr)
 {
        tPAddr  *ent;
@@ -208,3 +240,103 @@ Uint MM_GetFlags(tVAddr VAddr)
        
        return ret;
 }
+
+// --- Hardware Mappings ---
+/**
+ * \brief Map a range of hardware pages
+ */
+tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
+{
+       Log_KernelPanic("MM", "TODO: Implement MM_MapHWPages");
+       return 0;
+}
+
+/**
+ * \brief Free a range of hardware pages
+ */
+void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
+{
+       Log_KernelPanic("MM", "TODO: Implement MM_UnmapHWPages");
+}
+
+// --- Tempory Mappings ---
+tVAddr MM_MapTemp(tPAddr PAddr)
+{
+       Log_KernelPanic("MM", "TODO: Implement MM_MapTemp");
+       return 0;
+}
+
+void MM_FreeTemp(tVAddr VAddr)
+{
+       Log_KernelPanic("MM", "TODO: Implement MM_FreeTemp");
+       return ;
+}
+
+
+// --- Address Space Clone --
+tPAddr MM_Clone(void)
+{
+       tPAddr  ret;
+       
+       // #1 Create a copy of the PML4
+       ret = MM_AllocPhys();
+       if(!ret)        return 0;
+       
+       // #2 Alter the fractal pointer
+       // #3 Set Copy-On-Write to all user pages
+       // #4 Return
+       return 0;
+}
+
+void MM_ClearUser(void)
+{
+       tVAddr  addr = 0;
+       // #1 Traverse the structure < 2^47, Deref'ing all pages
+       // #2 Free tables/dirs/pdps once they have been cleared
+       
+       for( addr = 0; addr < 0x800000000000; )
+       {
+               if( PAGEMAPLVL4(addr >> PML4_SHIFT) & 1 )
+               {
+                       if( PAGEDIRPTR(addr >> PDP_SHIFT) & 1 )
+                       {
+                               if( PAGEDIR(addr >> PDIR_SHIFT) & 1 )
+                               {
+                                       // Page
+                                       if( PAGETABLE(addr >> PTAB_SHIFT) & 1 ) {
+                                               MM_DerefPhys( PAGETABLE(addr >> PTAB_SHIFT) & PADDR_MASK );
+                                               PAGETABLE(addr >> PTAB_SHIFT) = 0;
+                                       }
+                                       addr += 1 << PTAB_SHIFT;
+                                       // Dereference the PDIR Entry
+                                       if( (addr + (1 << PTAB_SHIFT)) >> PDIR_SHIFT != (addr >> PDIR_SHIFT) ) {
+                                               MM_DerefPhys( PAGEMAPLVL4(addr >> PDIR_SHIFT) & PADDR_MASK );
+                                               PAGEDIR(addr >> PDIR_SHIFT) = 0;
+                                       }
+                               }
+                               else {
+                                       addr += 1 << PDIR_SHIFT;
+                                       continue;
+                               }
+                               // Dereference the PDP Entry
+                               if( (addr + (1 << PDIR_SHIFT)) >> PDP_SHIFT != (addr >> PDP_SHIFT) ) {
+                                       MM_DerefPhys( PAGEMAPLVL4(addr >> PDP_SHIFT) & PADDR_MASK );
+                                       PAGEDIRPTR(addr >> PDP_SHIFT) = 0;
+                               }
+                       }
+                       else {
+                               addr += 1 << PDP_SHIFT;
+                               continue;
+                       }
+                       // Dereference the PML4 Entry
+                       if( (addr + (1 << PDP_SHIFT)) >> PML4_SHIFT != (addr >> PML4_SHIFT) ) {
+                               MM_DerefPhys( PAGEMAPLVL4(addr >> PML4_SHIFT) & PADDR_MASK );
+                               PAGEMAPLVL4(addr >> PML4_SHIFT) = 0;
+                       }
+               }
+               else {
+                       addr += (tVAddr)1 << PML4_SHIFT;
+                       continue;
+               }
+       }
+}

UCC git Repository :: git.ucc.asn.au