Kernel - Fixing binary loader and MMap
authorJohn Hodge <[email protected]>
Fri, 26 Aug 2011 03:15:17 +0000 (11:15 +0800)
committerJohn Hodge <[email protected]>
Fri, 26 Aug 2011 03:15:17 +0000 (11:15 +0800)
- Still some issues with what seems to be nodes going out of scope

Kernel/binary.c
Kernel/include/acess.h
Kernel/vfs/mmap.c

index fb31fc3..94c347f 100644 (file)
@@ -2,7 +2,7 @@
  * Acess2
  * Common Binary Loader
  */
-#define DEBUG  1
+#define DEBUG  0
 #include <acess.h>
 #include <binary.h>
 #include <mm_virt.h>
@@ -28,6 +28,7 @@ extern char   *Threads_GetName(int ID);
 extern tKernelSymbol   gKernelSymbols[];
 extern tKernelSymbol   gKernelSymbolsEnd[];
 extern tBinaryType     gELF_Info;
+extern void    MM_DumpTables(tVAddr, tVAddr);
 
 // === PROTOTYPES ===
  int   Proc_Execve(const char *File, const char **ArgV, const char **EnvP);
@@ -169,6 +170,9 @@ int Proc_Execve(const char *File, const char **ArgV, const char **EnvP)
        }
        
        LOG("entry = 0x%x, bases[0] = 0x%x", entry, bases[0]);
+
+       MM_DumpTables(0, KERNEL_BASE);
+
        LEAVE('-');
        // --- And... Jump to it
        Proc_StartUser(entry, bases, argc, argvSaved, envpSaved, argenvBytes);
@@ -293,6 +297,7 @@ tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr Lo
        // Check if base is free
        if(base != 0)
        {
+               LOG("Checking base %p", base);
                for(i=0;i<Binary->NumSections;i++)
                {
                        if( Binary_int_CheckMemFree( Binary->LoadSections[i].Virtual, Binary->LoadSections[i].MemSize ) )
@@ -322,6 +327,7 @@ tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr Lo
                        // Else decrement pointer and try again
                        base -= BIN_GRANUALITY;
                }
+               LOG("Allocated base %p", base);
        }
        
        // Error Check
@@ -338,7 +344,7 @@ tVAddr Binary_MapIn(tBinary *Binary, const char *Path, tVAddr LoadMin, tVAddr Lo
                tBinarySection  *sect = &Binary->LoadSections[i];
                Uint    protflags, mapflags;
                tVAddr  addr = sect->Virtual - Binary->Base + base;
-               LOG("%i - 0x%x to 0x%x", i, addr, sect->Offset);
+               LOG("%i - %p to 0x%llx (%x)", i, addr, sect->Offset, sect->Flags);
 
                protflags = MMAP_PROT_READ;
                mapflags = MMAP_MAP_FIXED;
@@ -761,6 +767,7 @@ Uint Binary_FindSymbol(void *Base, const char *Name, Uint *Val)
 int Binary_int_CheckMemFree( tVAddr _start, size_t _len )
 {
        _len += _start & (PAGE_SIZE-1);
+       _len = (_len + PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
        _start &= ~(PAGE_SIZE-1);
        for( ; _len > PAGE_SIZE; _len -= PAGE_SIZE, _start += PAGE_SIZE ) {
                if( MM_GetPhysAddr(_start) != 0 )
index f0e537a..6373cec 100644 (file)
@@ -280,25 +280,23 @@ extern void       MM_DerefPhys(tPAddr PAddr);
  */
 extern int     MM_GetRefCount(tPAddr PAddr);
 /**
- * \brief Set the node/offset associated with a page
+ * \brief Set the node associated with a page
  * \param PAddr        Physical address of page
  * \param Node Node pointer (tVFS_Node)
- * \param Offset       File offset
  * \return Boolean failure
  * \retval 0   Success
  * \retval 1   Page not allocated
  */
-extern int     MM_SetPageInfo(tPAddr PAddr, void *Node, Uint64 Offset);
+extern int     MM_SetPageNode(tPAddr PAddr, void *Node);
 /**
- * \brief Get the node/offset associated with a page
+ * \brief Get the node associated with a page
  * \param PAddr        Physical address of page
  * \param Node Node pointer (tVFS_Node) destination
- * \param Offset       File offset destination (pointer)
  * \return Boolean failure
  * \retval 0   Success
  * \retval 1   Page not allocated
  */
-extern int     MM_GetPageInfo(tPAddr PAddr, void **Node, Uint64 *Offset);
+extern int     MM_GetPageNode(tPAddr PAddr, void **Node);
 /**
  * \}
  */
index 709686b..9593562 100644 (file)
@@ -23,36 +23,45 @@ struct sVFS_MMapPageBlock
 void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset)
 {
        tVFS_Handle     *h;
-       tVAddr  mapping_dest;
+       tVAddr  mapping_dest, mapping_base;
         int    npages, pagenum;
        tVFS_MMapPageBlock      *pb, *prev;
 
        ENTER("pDestHint iLength xProtection xFlags xFD XOffset", DestHint, Length, Protection, Flags, FD, Offset);
-       
+
        npages = ((Offset & (PAGE_SIZE-1)) + Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
        pagenum = Offset / PAGE_SIZE;
 
-       mapping_dest = (tVAddr)DestHint;        
+       mapping_base = (tVAddr)DestHint;
+       mapping_dest = mapping_base & ~(PAGE_SIZE-1);
 
        // TODO: Locate space for the allocation
 
        // Handle anonymous mappings
        if( Flags & MMAP_MAP_ANONYMOUS )
        {
-               int i;
-               for( i = 0; i < npages; i ++ ) {
-                       tPAddr rv = MM_Allocate(mapping_dest + i * PAGE_SIZE);
-                       if( !rv ) {
-                               // TODO: Error
+               for( ; npages --; mapping_dest += PAGE_SIZE )
+               {
+                       if( MM_GetPhysAddr(mapping_dest) ) {
+                               // TODO: Set flags to COW if needed (well, if shared)
+                       }
+                       else {
+                               if( !MM_Allocate(mapping_dest) ) {
+                                       // TODO: Error
+                                       Log_Warning("VFS", "VFS_MMap: Anon alloc to %p failed", mapping_dest);
+                               }
+                               LOG("Anon map to %p", mapping_dest);
                        }
                }
-               LEAVE_RET('p', (void*)mapping_dest);
+               LEAVE_RET('p', (void*)mapping_base);
        }
 
        h = VFS_GetHandle(FD);
        if( !h || !h->Node )    LEAVE_RET('n', NULL);
 
        LOG("h = %p", h);
+       
+       Mutex_Acquire( &h->Node->Lock );
 
        // Search for existing mapping for each page
        // - Sorted list of 16 page blocks
@@ -62,12 +71,17 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                prev = pb, pb = pb->Next
                );
 
+       LOG("pb = %p, pb->BaseOffset = %X", pb, pb ? pb->BaseOffset : 0);
+
        // - Allocate a block if needed
        if( !pb || pb->BaseOffset > pagenum )
        {
                void    *old_pb = pb;
                pb = malloc( sizeof(tVFS_MMapPageBlock) );
-               if(!pb) LEAVE_RET('n', NULL);
+               if(!pb) {
+                       Mutex_Release( &h->Node->Lock );
+                       LEAVE_RET('n', NULL);
+               }
                pb->Next = old_pb;
                pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK;
                memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
@@ -80,29 +94,57 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
        // - Map (and allocate) pages
        while( npages -- )
        {
-               if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
+               if( MM_GetPhysAddr(mapping_dest) == 0 )
                {
-                       if( h->Node->MMap )
-                               h->Node->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
-                       else
+                       if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
                        {
-                               // Allocate pages and read data
-                               if( MM_Allocate(mapping_dest) == 0 ) {
-                                       // TODO: Unwrap
-                                       return NULL;
+                               if( h->Node->MMap )
+                                       h->Node->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
+                               else
+                               {
+                                       // Allocate pages and read data
+                                       if( MM_Allocate(mapping_dest) == 0 ) {
+                                               // TODO: Unwrap
+                                               Mutex_Release( &h->Node->Lock );
+                                               LEAVE('n');
+                                               return NULL;
+                                       }
+                                       h->Node->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
                                }
-                               h->Node->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
+                               pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
+                               MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node );
+                               LOG("Read and map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
+                                       pb->PhysAddrs[pagenum - pb->BaseOffset]);
+                       }
+                       else
+                       {
+                               MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
+                               LOG("Cached map %X to %p (%P)", pagenum*PAGE_SIZE, mapping_dest,
+                                       pb->PhysAddrs[pagenum - pb->BaseOffset]);
+                       }
+                       h->Node->ReferenceCount ++;
+               
+                       // Set flags
+                       if( !(Protection & MMAP_PROT_WRITE) ) {
+                               MM_SetFlags(mapping_dest, MM_PFLAG_RO, MM_PFLAG_RO);
+                       }
+                       else {
+                               MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
                        }
-                       pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
-//                     MM_SetPageInfo( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node, pagenum*PAGE_SIZE );
                }
                else
                {
-                       MM_Map( mapping_dest, pb->PhysAddrs[pagenum - pb->BaseOffset] );
+                       LOG("Flag update on %p", mapping_dest);
+                       if( (MM_GetFlags(mapping_dest) & MM_PFLAG_RO) && (Protection & MMAP_PROT_WRITE) )
+                       {
+                               MM_SetFlags(mapping_dest, 0, MM_PFLAG_RO);
+                       }
                }
+               if( Flags & MMAP_MAP_PRIVATE )
+                       MM_SetFlags(mapping_dest, MM_PFLAG_COW, MM_PFLAG_COW);
                pagenum ++;
                mapping_dest += PAGE_SIZE;
-               
+
                // Roll on to next block if needed
                if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK)
                {
@@ -120,9 +162,11 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                        pagenum = 0;
                }
        }
+       
+       Mutex_Release( &h->Node->Lock );
 
-       LEAVE('n');     
-       return NULL;
+       LEAVE('p', mapping_base);
+       return (void*)mapping_base;
 }
 
 int VFS_MUnmap(void *Addr, size_t Length)

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