#include <mm_virt.h>
#include <pmemmap.h>
#include <hal_proc.h>
+#include <semaphore.h>
//#define USE_STACK 1
#define TRACE_ALLOCS 0 // Print trace messages on AllocPhys/DerefPhys
// === CODE ===
void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges)
{
- Uint i;
Uint64 maxAddr = 0;
// --- Find largest address
- for( i = 0; i < NPMemRanges; i ++ )
+ for( Uint i = 0; i < NPMemRanges; i ++ )
{
tPMemMapEnt *ent = &PMemRanges[i];
// If entry is RAM and is above `maxAddr`, change `maxAddr`
giTotalMemorySize += ent->Length >> 12;
}
}
+ LOG("giTotalMemorySize = %lli KiB", giTotalMemorySize*4);
+ LOG("maxAddr = 0x%X", maxAddr);
+
+ // Clip to 32-bits
+ if( maxAddr > (1ULL << 32) ) {
+ maxAddr = (1ULL << 32);
+ }
giPageCount = maxAddr >> 12;
giLastPossibleFree = giPageCount - 1;
-
memsetd(gaPageBitmap, 0xFFFFFFFF, giPageCount/32);
// Set up allocateable space
- for( i = 0; i < NPMemRanges; i ++ )
+ for( Uint i = 0; i < NPMemRanges; i ++ )
{
tPMemMapEnt *ent = &PMemRanges[i];
if( ent->Type == PMEMTYPE_FREE )
{
Uint64 startpg = ent->Start / PAGE_SIZE;
Uint64 pgcount = ent->Length / PAGE_SIZE;
+ // Ignore start addresses >32 bits
+ if( startpg > (1 << 20) )
+ continue ;
+ // Clip lengths to 32-bit address space
+ if( startpg + pgcount > (1<<20) )
+ pgcount = (1<<20) - startpg;
+
while( startpg % 32 && pgcount ) {
gaPageBitmap[startpg/32] &= ~(1U << (startpg%32));
startpg ++;
}
else if( ent->Type == PMEMTYPE_USED )
{
+ // TODO: Clip?
giPhysAlloc += ent->Length / PAGE_SIZE;
}
}
// Fill Superpage bitmap
// - A set bit means that there are no free pages in this block of 32
- for( i = 0; i < (giPageCount+31)/32; i ++ )
+ for( Uint i = 0; i < (giPageCount+31)/32; i ++ )
{
if( gaPageBitmap[i] + 1 == 0 ) {
gaSuperBitmap[i/32] |= (1 << i%32);
// Release Spinlock
Mutex_Release( &glPhysAlloc );
- LEAVE('X', ret);
+ LEAVE('P', ret);
#if TRACE_ALLOCS
if( now() > 4000 ) {
*/
void MM_InstallVirtual(void)
{
- int i;
-
// --- Pre-Allocate kernel tables
- for( i = KERNEL_BASE>>22; i < 1024; i ++ )
+ for( int i = KERNEL_BASE>>22; i < 1024; i ++ )
{
if( gaPageDir[ i ] ) continue;
// Skip stack tables, they are process unique
}
// Unset kernel on the User Text pages
- for( i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) {
+ for( int i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) {
MM_SetFlags( (tVAddr)&_UsertextBase + i*4096, 0, MM_PFLAG_KERNEL );
}
*/
tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize)
{
- Uint base, addr;
- tVAddr tmpPage;
+ Uint base;
tPAddr page;
+ LOG("(StackContents=%p,ContentsSize=%i)", StackContents, ContentsSize);
// TODO: Thread safety
// Find a free worker stack address
for(base = giLastUsedWorker; base < NUM_WORKER_STACKS; base++)
break;
}
if(base >= NUM_WORKER_STACKS) {
- Warning("Uh-oh! Out of worker stacks");
+ Log_Error("MMVirt", "Uh-oh! Out of worker stacks");
return 0;
}
+ LOG("base=0x%x", base);
// It's ours now!
gWorkerStacks[base/32] |= (1 << base);
// We have one
base = WORKER_STACKS + base * WORKER_STACK_SIZE;
//Log(" MM_NewWorkerStack: base = 0x%x", base);
+ LOG("base=%p (top)", base);
// Set the temp fractals to TID0's address space
GET_TEMP_MAPPING( ((Uint)gaInitPageDir - KERNEL_BASE) );
// Check if the directory is mapped (we are assuming that the stacks
// will fit neatly in a directory)
- //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]);
+ LOG("gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]);
if(gaTmpDir[ base >> 22 ] == 0) {
gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3;
INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] );
}
// Mapping Time!
- for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 )
+ for( Uint addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 )
{
page = MM_AllocPhys();
gaTmpTable[ (base + addr) >> 12 ] = page | 3;
}
+ LOG("mapped");
// Release temporary fractal
REL_TEMP_MAPPING();
// NOTE: Max of 1 page
// `page` is the last allocated page from the previious for loop
- tmpPage = (tVAddr)MM_MapTemp( page );
- memcpy( (void*)( tmpPage + (0x1000 - ContentsSize) ), StackContents, ContentsSize);
- MM_FreeTemp( (void*)tmpPage );
+ LOG("Mapping first page");
+ char *tmpPage = MM_MapTemp( page );
+ LOG("tmpPage=%p", tmpPage);
+ memcpy( tmpPage + (0x1000 - ContentsSize), StackContents, ContentsSize);
+ MM_FreeTemp( tmpPage );
//Log("MM_NewWorkerStack: RETURN 0x%x", base);
+ LOG("return %p", base+WORKER_STACK_SIZE);
return base + WORKER_STACK_SIZE;
}
* \brief Create a temporary memory mapping
* \todo Show Luigi Barone (C Lecturer) and see what he thinks
*/
-void * MM_MapTemp(tPAddr PAddr)
+void *MM_MapTemp(tPAddr PAddr)
{
- //ENTER("XPAddr", PAddr);
+ ENTER("PPAddr", PAddr);
PAddr &= ~0xFFF;
- //LOG("glTempMappings = %i", glTempMappings);
-
if( Semaphore_Wait(&gTempMappingsSem, 1) != 1 )
return NULL;
+ LOG("Semaphore good");
Mutex_Acquire( &glTempMappings );
for( int i = 0; i < NUM_TEMP_PAGES; i ++ )
{
+ Uint32 *pte = &gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ];
+ LOG("%i: %x", i, *pte);
// Check if page used
- if(gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] & 1) continue;
+ if(*pte & 1) continue;
// Mark as used
- gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] = PAddr | 3;
+ *pte = PAddr | 3;
INVLPG( TEMP_MAP_ADDR + (i << 12) );
- //LEAVE('p', TEMP_MAP_ADDR + (i << 12));
+ LEAVE('p', TEMP_MAP_ADDR + (i << 12));
Mutex_Release( &glTempMappings );
return (void*)( TEMP_MAP_ADDR + (i << 12) );
}
/*
- * AcessOS Microkernel Version
+ * Acess2 Kernel (x86)
+ * - By John Hodge (thePowersGang)
+ *
* proc.c
+ * - Low level thread management
*/
+#define DEBUG 0
#include <acess.h>
#include <threads.h>
#include <proc.h>
*/
tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
- tThread *new;
Uint stack_contents[4];
+ LOG("(Fcn=%p,Data=%p)", Fcn, Data);
// Create new thread
- new = Threads_CloneThreadZero();
+ tThread *new = Threads_CloneThreadZero();
+ LOG("new=%p", new);
if(!new) {
Warning("Proc_SpawnWorker - Out of heap space!\n");
return NULL;
// Create a new worker stack (in PID0's address space)
new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
+ LOG("new->KernelStack = %p", new->KernelStack);
// Save core machine state
new->SavedState.ESP = new->KernelStack - sizeof(stack_contents);
// Mark as active
new->Status = THREAD_STAT_PREINIT;
Threads_AddActive( new );
+ LOG("Added to active");
return new;
}