void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, const char **ArgV, int DataSize) { int i; const char **envp; tVAddr delta; // Log_Debug("Proc", "Proc_StartUser: (Entrypoint=%p, Base=%p, ArgC=%i, ArgV=%p, DataSize=0x%x)", // Entrypoint, Base, ArgC, ArgV, DataSize); // Write data to the user's stack Uint32 *usr_sp = (void*)MM_NewUserStack(); if( !usr_sp ) { Log_KernelPanic("Proc", "Creation of user stack failed"); } usr_sp -= (DataSize+3)/4; memcpy(usr_sp, ArgV, DataSize); free(ArgV); // Adjust user's copy of the arguments delta = (tVAddr)usr_sp - (tVAddr)ArgV; ArgV = (void*)usr_sp; for(i = 0; ArgV[i]; i ++) ArgV[i] += delta; envp = &ArgV[i+1]; for(i = 0; envp[i]; i ++) envp[i] += delta; *--usr_sp = (Uint32)envp; *--usr_sp = (Uint32)ArgV; *--usr_sp = (Uint32)ArgC; *--usr_sp = Base; // Drop to user code Log_Debug("Proc", "Proc_int_DropToUser(%p, %p)", Entrypoint, usr_sp); Proc_int_DropToUser(Entrypoint, (Uint32)usr_sp); }
/** * \fn int VFS_Init(void) * \brief Initialises the VFS for use by the kernel and user */ int VFS_Init(void) { // Core Drivers gVFS_Drivers = &gRootFS_Info; gVFS_Drivers->Next = &gDevFS_Info; VFS_UpdateDriverFile(); // Register with SysFS giVFS_MountFileID = SysFS_RegisterFile("VFS/Mounts", NULL, 0); giVFS_DriverFileID = SysFS_RegisterFile("VFS/Drivers", NULL, 0); if( VFS_Mount("root", "/", "rootfs", "") != 0 ) { Log_KernelPanic("VFS", "Unable to mount root (Where the **** is rootfs?)"); return -1; } VFS_MkDir("/Devices"); VFS_MkDir("/Mount"); VFS_Mount("dev", "/Devices", "devfs", ""); // Set default max user file count // - Applies to PID0, but propagated to all children *Threads_GetMaxFD(NULL) = 32; return 0; }
/** * \brief Clone a page from an entry * \param Ent Pointer to the entry in the PML4/PDP/PD/PT * \param NextLevel Pointer to contents of the entry * \param Addr Dest address * \note Used in COW */ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable ) { tPAddr curpage = *Ent & PADDR_MASK; int bCopied = 0; if( MM_GetRefCount( curpage ) <= 0 ) { Log_KernelPanic("MMVirt", "Page %P still marked COW, but unreferenced", curpage); } if( MM_GetRefCount( curpage ) == 1 ) { *Ent &= ~PF_COW; *Ent |= PF_PRESENT|PF_WRITE; #if TRACE_COW Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage); #endif } else { void *tmp; tPAddr paddr; if( !(paddr = MM_AllocPhys()) ) { Threads_SegFault(Addr); return ; } ASSERT(paddr != curpage); tmp = MM_MapTemp(paddr); memcpy( tmp, NextLevel, 0x1000 ); MM_FreeTemp( tmp ); #if TRACE_COW Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr); #endif MM_DerefPhys( curpage ); *Ent &= PF_USER; *Ent |= paddr|PF_PRESENT|PF_WRITE; bCopied = 1; } INVLPG( (tVAddr)NextLevel ); // Mark COW on contents if it's a PDPT, Dir or Table if(bTable) { Uint64 *dp = NextLevel; int i; for( i = 0; i < 512; i ++ ) { if( !(dp[i] & PF_PRESENT) ) continue; if( bCopied ) MM_RefPhys( dp[i] & PADDR_MASK ); if( dp[i] & PF_WRITE ) { dp[i] &= ~PF_WRITE; dp[i] |= PF_COW; } } } }
// === CODE === int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt *Map, const int MapSize, tPAddr KStart, tPAddr KEnd) { int nPMemMapEnts = 0; ENTER("pMBInfo pMapOffset pMap iMapSize PKStart PKEnd", MBInfo, MapOffset, Map, MapSize, KStart, KEnd); // Check that the memory map is present if( MBInfo->Flags & (1 << 6) ) { tMBoot_MMapEnt *ent = (void*)((tVAddr)MBInfo->MMapAddr + MapOffset); tMBoot_MMapEnt *last = (void*)((tVAddr)ent + MBInfo->MMapLength); // Build up memory map nPMemMapEnts = 0; while( ent < last && nPMemMapEnts < MapSize ) { tPMemMapEnt *nent = &Map[nPMemMapEnts]; if( !MM_GetPhysAddr(ent) ) Log_KernelPanic("MBoot", "MBoot Map entry %i addres bad (%p)", nPMemMapEnts, ent); LOG("%llx+%llx", ent->Base, ent->Length); nent->Start = ent->Base; nent->Length = ent->Length; switch(ent->Type) { case 1: nent->Type = PMEMTYPE_FREE; break; default: nent->Type = PMEMTYPE_RESERVED; break; } nent->NUMADomain = 0; nPMemMapEnts ++; ent = (void*)( (tVAddr)ent + ent->Size + 4 ); } if( ent < last ) { Log_Warning("MBoot", "Memory map has >%i entries, internal version is truncated", MapSize); } } else if( MBInfo->Flags & (1 << 0) ) { Log_Warning("MBoot", "No memory map passed, using mem_lower and mem_upper"); ASSERT(MapSize >= 2); nPMemMapEnts = 2; Map[0].Start = 0; Map[0].Length = MBInfo->LowMem * 1024; Map[0].Type = PMEMTYPE_FREE; Map[0].NUMADomain = 0; Map[1].Start = 0x100000; Map[1].Length = MBInfo->HighMem * 1024; Map[1].Type = PMEMTYPE_FREE; Map[1].NUMADomain = 0; } else { Log_KernelPanic("MBoot", "Multiboot didn't pass memory information"); } // Ensure it's valid LOG("Validating"); nPMemMapEnts = PMemMap_ValidateMap(Map, nPMemMapEnts, MapSize); // TODO: Error handling // Replace kernel with PMEMTYPE_USED LOG("Marking kernel"); nPMemMapEnts = PMemMap_MarkRangeUsed( Map, nPMemMapEnts, MapSize, KStart, KEnd - KStart ); LOG("Dumping"); PMemMap_DumpBlocks(Map, nPMemMapEnts); // Check if boot modules were passed if( MBInfo->Flags & (1 << 3) ) { // Replace modules with PMEMTYPE_USED nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize, MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module) ); LOG("MBInfo->Modules = %x", MBInfo->Modules); tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset); for( int i = 0; i < MBInfo->ModuleCount; i ++ ) { LOG("&mods[%i] = %p", i, &mods[i]); LOG("mods[i] = {0x%x -> 0x%x}", mods[i].Start, mods[i].End); nPMemMapEnts = PMemMap_MarkRangeUsed( Map, nPMemMapEnts, MapSize, mods[i].Start, mods[i].End - mods[i].Start ); } } // Debug - Output map PMemMap_DumpBlocks(Map, nPMemMapEnts); LEAVE('i', nPMemMapEnts); return nPMemMapEnts; }