From: John Hodge Date: Fri, 26 Aug 2011 03:15:17 +0000 (+0800) Subject: Kernel - Fixing binary loader and MMap X-Git-Tag: rel0.11~119 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=d82586eccb8bc74aec2b2d6cf4ee2b4ed844e957;p=tpg%2Facess2.git Kernel - Fixing binary loader and MMap - Still some issues with what seems to be nodes going out of scope --- diff --git a/Kernel/binary.c b/Kernel/binary.c index fb31fc3b..94c347ff 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -2,7 +2,7 @@ * Acess2 * Common Binary Loader */ -#define DEBUG 1 +#define DEBUG 0 #include #include #include @@ -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;iNumSections;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 ) diff --git a/Kernel/include/acess.h b/Kernel/include/acess.h index f0e537aa..6373cec5 100644 --- a/Kernel/include/acess.h +++ b/Kernel/include/acess.h @@ -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); /** * \} */ diff --git a/Kernel/vfs/mmap.c b/Kernel/vfs/mmap.c index 709686bb..9593562b 100644 --- a/Kernel/vfs/mmap.c +++ b/Kernel/vfs/mmap.c @@ -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)