Working on MP build (now can run, just crashes due to CPUs treading on each other...
[tpg/acess2.git] / Kernel / arch / x86 / mm_virt.c
index 4f272e7..8902837 100644 (file)
@@ -9,8 +9,10 @@
  * 0xFE - Unused
  * 0xFF - System Calls / Kernel's User Code
  */
-#define DEBUG  1
+#define DEBUG  0
+#define SANITY 1
 #include <acess.h>
+#include <mm_virt.h>
 #include <mm_phys.h>
 #include <proc.h>
 
@@ -65,14 +67,15 @@ typedef Uint32      tTabEnt;
 #endif
 
 // === IMPORTS ===
+extern void    _UsertextEnd, _UsertextBase;
 extern Uint32  gaInitPageDir[1024];
 extern Uint32  gaInitPageTable[1024];
 extern void    Threads_SegFault(tVAddr Addr);
 extern void    Error_Backtrace(Uint eip, Uint ebp);
 
 // === PROTOTYPES ===
-void   MM_PreinitVirtual();
-void   MM_InstallVirtual();
+void   MM_PreinitVirtual(void);
+void   MM_InstallVirtual(void);
 void   MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
 void   MM_DumpTables(tVAddr Start, tVAddr End);
 tPAddr MM_DuplicatePage(tVAddr VAddr);
@@ -99,26 +102,24 @@ Uint32     gWorkerStacks[(NUM_WORKER_STACKS+31)/32];
 
 // === CODE ===
 /**
- * \fn void MM_PreinitVirtual()
+ * \fn void MM_PreinitVirtual(void)
  * \brief Maps the fractal mappings
  */
-void MM_PreinitVirtual()
+void MM_PreinitVirtual(void)
 {
        #if USE_PAE
-       gaInitPDPT[ 0 ] = 0;
        gaInitPageDir[ ((PAGE_TABLE_ADDR >> TAB)-3*512+3)*2 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3;
        #else
-       gaInitPageDir[ 0 ] = 0;
        gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3;
        #endif
        INVLPG( PAGE_TABLE_ADDR );
 }
 
 /**
- * \fn void MM_InstallVirtual()
+ * \fn void MM_InstallVirtual(void)
  * \brief Sets up the constant page mappings
  */
-void MM_InstallVirtual()
+void MM_InstallVirtual(void)
 {
         int    i;
        
@@ -154,6 +155,23 @@ void MM_InstallVirtual()
                memset( &gaPageTable[i*1024], 0, 0x1000 );
        }
        #endif
+       
+       // Unset kernel on the User Text pages
+       for( i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) {
+               MM_SetFlags( (tVAddr)&_UsertextBase + i*4096, 0, MM_PFLAG_KERNEL );
+       }
+}
+
+/**
+ * \brief Cleans up the SMP required mappings
+ */
+void MM_FinishVirtualInit(void)
+{
+       #if USE_PAE
+       gaInitPDPT[ 0 ] = 0;
+       #else
+       gaInitPageDir[ 0 ] = 0;
+       #endif
 }
 
 /**
@@ -177,6 +195,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
                }
                else
                {
+                       //Log("MM_PageFault: COW - MM_DuplicatePage(0x%x)", Addr);
                        paddr = MM_DuplicatePage( Addr );
                        MM_DerefPhys( gaPageTable[Addr>>12] & ~0xFFF );
                        gaPageTable[Addr>>12] &= PF_USER;
@@ -196,12 +215,14 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
                        (ErrorCode&1?"bad/locked":"non-present"),
                        (ErrorCode&16?" (Instruction Fetch)":"")
                        );
-               Warning("User Pagefault: Instruction at %p accessed %p", Regs->eip, Addr);
+               Warning("User Pagefault: Instruction at %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr);
                __asm__ __volatile__ ("sti");   // Restart IRQs
                Threads_SegFault(Addr);
                return ;
        }
        
+       Debug_KernelPanic();
+       
        // -- Check Error Code --
        if(ErrorCode & 8)
                Warning("Reserved Bits Trashed!");
@@ -225,6 +246,19 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
        
        //MM_DumpTables(0, -1); 
        
+       // Register Dump
+       Log("EAX %08x ECX %08x EDX %08x EBX %08x", Regs->eax, Regs->ecx, Regs->edx, Regs->ebx);
+       Log("ESP %08x EBP %08x ESI %08x EDI %08x", Regs->esp, Regs->ebp, Regs->esi, Regs->edi);
+       //Log("SS:ESP %04x:%08x", Regs->ss, Regs->esp);
+       Log("CS:EIP %04x:%08x", Regs->cs, Regs->eip);
+       Log("DS %04x ES %04x FS %04x GS %04x", Regs->ds, Regs->es, Regs->fs, Regs->gs);
+       {
+               Uint    dr0, dr1;
+               __ASM__ ("mov %%dr0, %0":"=r"(dr0):);
+               __ASM__ ("mov %%dr1, %0":"=r"(dr1):);
+               Log("DR0 %08x DR1 %08x", dr0, dr1);
+       }
+       
        Panic("Page Fault at 0x%x (Accessed 0x%x)", Regs->eip, Addr);
 }
 
@@ -318,7 +352,7 @@ tPAddr MM_Allocate(tVAddr VAddr)
                //LOG("paddr = 0x%llx (new table)", paddr);
                if( paddr == 0 ) {
                        Warning("MM_Allocate - Out of Memory (Called by %p)", __builtin_return_address(0));
-                       LEAVE('i',0);
+                       //LEAVE('i',0);
                        return 0;
                }
                // Map
@@ -391,27 +425,11 @@ tPAddr MM_GetPhysAddr(tVAddr Addr)
        return (gaPageTable[Addr >> 12] & ~0xFFF) | (Addr & 0xFFF);
 }
 
-
-/**
- * \fn int MM_IsUser(tVAddr VAddr)
- * \brief Checks if a page is user accessable
- */
-int MM_IsUser(tVAddr VAddr)
-{
-       if( !(gaPageDir[VAddr >> 22] & 1) )
-               return 0;
-       if( !(gaPageTable[VAddr >> 12] & 1) )
-               return 0;
-       if( !(gaPageTable[VAddr >> 12] & PF_USER) )
-               return 0;
-       return 1;
-}
-
 /**
- * \fn void MM_SetCR3(tPAddr CR3)
+ * \fn void MM_SetCR3(Uint CR3)
  * \brief Sets the current process space
  */
-void MM_SetCR3(tPAddr CR3)
+void MM_SetCR3(Uint CR3)
 {
        __asm__ __volatile__ ("mov %0, %%cr3"::"r"(CR3));
 }
@@ -473,7 +491,7 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr)
  * \fn tVAddr MM_ClearUser()
  * \brief Clear user's address space
  */
-tVAddr MM_ClearUser()
+tVAddr MM_ClearUser(void)
 {
        Uint    i, j;
        
@@ -504,10 +522,10 @@ tVAddr MM_ClearUser()
 }
 
 /**
- * \fn tPAddr MM_Clone()
+ * \fn tPAddr MM_Clone(void)
  * \brief Clone the current address space
  */
-tPAddr MM_Clone()
+tPAddr MM_Clone(void)
 {
        Uint    i, j;
        tVAddr  ret;
@@ -524,7 +542,7 @@ tPAddr MM_Clone()
        memsetd( gaTmpDir, 0, 1024 );
        
        // Copy Tables
-       for(i=0;i<768;i++)
+       for( i = 0; i < 768; i ++)
        {
                // Check if table is allocated
                if( !(gaPageDir[i] & PF_PRESENT) ) {
@@ -630,10 +648,10 @@ tPAddr MM_Clone()
 }
 
 /**
- * \fn tVAddr MM_NewKStack()
+ * \fn tVAddr MM_NewKStack(void)
  * \brief Create a new kernel stack
  */
-tVAddr MM_NewKStack()
+tVAddr MM_NewKStack(void)
 {
        tVAddr  base = KERNEL_STACKS;
        Uint    i;
@@ -767,15 +785,25 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
        // Read-Only
        if( Mask & MM_PFLAG_RO )
        {
-               if( Flags & MM_PFLAG_RO )       *ent &= ~PF_WRITE;
-               else    *ent |= PF_WRITE;
+               if( Flags & MM_PFLAG_RO ) {
+                       *ent &= ~PF_WRITE;
+               }
+               else {
+                       gaPageDir[VAddr >> 22] |= PF_WRITE;
+                       *ent |= PF_WRITE;
+               }
        }
        
        // Kernel
        if( Mask & MM_PFLAG_KERNEL )
        {
-               if( Flags & MM_PFLAG_KERNEL )   *ent &= ~PF_USER;
-               else    *ent |= PF_USER;
+               if( Flags & MM_PFLAG_KERNEL ) {
+                       *ent &= ~PF_USER;
+               }
+               else {
+                       gaPageDir[VAddr >> 22] |= PF_USER;
+                       *ent |= PF_USER;
+               }
        }
        
        // Copy-On-Write
@@ -790,6 +818,33 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
                        *ent |= PF_WRITE;
                }
        }
+       
+       //Log("MM_SetFlags: *ent = 0x%08x, gaPageDir[%i] = 0x%08x",
+       //      *ent, VAddr >> 22, gaPageDir[VAddr >> 22]);
+}
+
+/**
+ * \brief Get the flags on a page
+ */
+Uint MM_GetFlags(tVAddr VAddr)
+{
+       tTabEnt *ent;
+       Uint    ret = 0;
+       
+       // Validity Check
+       if( !(gaPageDir[VAddr >> 22] & 1) )     return 0;
+       if( !(gaPageTable[VAddr >> 12] & 1) )   return 0;
+       
+       ent = &gaPageTable[VAddr >> 12];
+       
+       // Read-Only
+       if( !(*ent & PF_WRITE) )        ret |= MM_PFLAG_RO;
+       // Kernel
+       if( !(*ent & PF_USER) ) ret |= MM_PFLAG_KERNEL;
+       // Copy-On-Write
+       if( *ent & PF_COW )     ret |= MM_PFLAG_COW;
+       
+       return ret;
 }
 
 /**
@@ -802,6 +857,8 @@ tPAddr MM_DuplicatePage(tVAddr VAddr)
        Uint    temp;
         int    wasRO = 0;
        
+       //ENTER("xVAddr", VAddr);
+       
        // Check if mapped
        if( !(gaPageDir  [VAddr >> 22] & PF_PRESENT) )  return 0;
        if( !(gaPageTable[VAddr >> 12] & PF_PRESENT) )  return 0;
@@ -826,6 +883,7 @@ tPAddr MM_DuplicatePage(tVAddr VAddr)
        if(!wasRO)      gaPageTable[VAddr >> 12] |= PF_WRITE;
        INVLPG(VAddr);
        
+       //LEAVE('X', ret);
        return ret;
 }
 
@@ -880,10 +938,10 @@ void MM_FreeTemp(tVAddr VAddr)
 }
 
 /**
- * \fn tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number)
+ * \fn tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
  * \brief Allocates a contigous number of pages
  */
-tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number)
+tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
 {
         int    i, j;
        
@@ -947,7 +1005,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        {
                phys = MM_AllocPhys();
                *PhysAddr = phys;
-               ret = MM_MapHWPage(phys, 1);
+               ret = MM_MapHWPages(phys, 1);
                if(ret == 0) {
                        MM_DerefPhys(phys);
                        LEAVE('i', 0);
@@ -958,24 +1016,15 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        }
        
        // Slow Allocate
-       phys = MM_AllocPhysRange(Pages);
+       phys = MM_AllocPhysRange(Pages, MaxBits);
        // - Was it allocated?
        if(phys == 0) {
                LEAVE('i', 0);
                return 0;
        }
-       // - Check if the memory is OK
-       if(phys + (Pages-1)*0x1000 > maxCheck)
-       {
-               // Deallocate and return 0
-               for(;Pages--;phys+=0x1000)
-                       MM_DerefPhys(phys);
-               LEAVE('i', 0);
-               return 0;
-       }
        
        // Allocated successfully, now map
-       ret = MM_MapHWPage(phys, Pages);
+       ret = MM_MapHWPages(phys, Pages);
        if( ret == 0 ) {
                // If it didn't map, free then return 0
                for(;Pages--;phys+=0x1000)
@@ -990,23 +1039,27 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
 }
 
 /**
- * \fn void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
+ * \fn void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
  * \brief Unmap a hardware page
  */
-void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
+void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
 {
         int    i, j;
+       
+       //Log_Debug("VirtMem", "MM_UnmapHWPages: (VAddr=0x%08x, Number=%i)", VAddr, Number);
+       
        // Sanity Check
-       if(VAddr < HW_MAP_ADDR || VAddr-Number*0x1000 > HW_MAP_MAX)     return;
+       if(VAddr < HW_MAP_ADDR || VAddr+Number*0x1000 > HW_MAP_MAX)     return;
        
        i = VAddr >> 12;
        
        LOCK( &gilTempMappings );       // Temp and HW share a directory, so they share a lock
        
+       
        for( j = 0; j < Number; j++ )
        {
-               MM_DerefPhys( gaPageTable[ (HW_MAP_ADDR >> 12) + i + j ] );
-               gaPageTable[ (HW_MAP_ADDR >> 12) + i + j ] = 0;
+               MM_DerefPhys( gaPageTable[ i + j ] & ~0xFFF );
+               gaPageTable[ i + j ] = 0;
        }
        
        RELEASE( &gilTempMappings );
@@ -1016,6 +1069,6 @@ void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
 EXPORT(MM_GetPhysAddr);
 EXPORT(MM_Map);
 //EXPORT(MM_Unmap);
-EXPORT(MM_MapHWPage);
+EXPORT(MM_MapHWPages);
 EXPORT(MM_AllocDMA);
-EXPORT(MM_UnmapHWPage);
+EXPORT(MM_UnmapHWPages);

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