* Acess2
* Common Binary Loader
*/
-#define DEBUG 1
+#define DEBUG 0
#include <acess.h>
#include <binary.h>
#include <mm_virt.h>
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);
}
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);
// 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 ) )
// Else decrement pointer and try again
base -= BIN_GRANUALITY;
}
+ LOG("Allocated base %p", base);
}
// Error Check
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;
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 )
*/
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);
/**
* \}
*/
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
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));
// - 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)
{
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)