#include <proc.h>
#include <hal_proc.h>
#include <arch_int.h>
+#include <semaphore.h>
#define TAB 22
#define gaPAE_TmpPDPT ((tTabEnt*)PAE_TMP_PDPT_ADDR)
int gbUsePAE = 0;
tMutex glTempMappings;
+tSemaphore gTempMappingsSem;
tMutex glTempFractal;
Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32];
int giLastUsedWorker = 0;
{
gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3;
INVLPG( PAGE_TABLE_ADDR );
+
+ Semaphore_Init(&gTempMappingsSem, NUM_TEMP_PAGES, NUM_TEMP_PAGES, "MMVirt", "Temp Mappings");
}
/**
*/
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)
{
- int i;
-
- //ENTER("XPAddr", PAddr);
+ ENTER("PPAddr", PAddr);
PAddr &= ~0xFFF;
- //LOG("glTempMappings = %i", glTempMappings);
-
- for(;;)
+ if( Semaphore_Wait(&gTempMappingsSem, 1) != 1 )
+ return NULL;
+ LOG("Semaphore good");
+ Mutex_Acquire( &glTempMappings );
+ for( int i = 0; i < NUM_TEMP_PAGES; i ++ )
{
- Mutex_Acquire( &glTempMappings );
-
- for( i = 0; i < NUM_TEMP_PAGES; i ++ )
- {
- // Check if page used
- if(gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] & 1) continue;
- // Mark as used
- gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] = PAddr | 3;
- INVLPG( TEMP_MAP_ADDR + (i << 12) );
- //LEAVE('p', TEMP_MAP_ADDR + (i << 12));
- Mutex_Release( &glTempMappings );
- return (void*)( TEMP_MAP_ADDR + (i << 12) );
- }
+ Uint32 *pte = &gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ];
+ LOG("%i: %x", i, *pte);
+ // Check if page used
+ if(*pte & 1) continue;
+ // Mark as used
+ *pte = PAddr | 3;
+ INVLPG( TEMP_MAP_ADDR + (i << 12) );
+ LEAVE('p', TEMP_MAP_ADDR + (i << 12));
Mutex_Release( &glTempMappings );
- Threads_Yield(); // TODO: Use a sleep queue here instead
+ return (void*)( TEMP_MAP_ADDR + (i << 12) );
}
+ Mutex_Release( &glTempMappings );
+ Log_KernelPanic("MMVirt", "Semaphore suplied a mapping, but none are avaliable");
+ return NULL;
}
/**
int i = (tVAddr)VAddr >> 12;
//ENTER("xVAddr", VAddr);
- if(i >= (TEMP_MAP_ADDR >> 12))
+ if(i >= (TEMP_MAP_ADDR >> 12)) {
gaPageTable[ i ] = 0;
+ Semaphore_Signal(&gTempMappingsSem, 1);
+ }
//LEAVE('-');
}
*/
void *MM_MapHWPages(tPAddr PAddr, Uint Number)
{
- int i, j;
+ int j;
PAddr &= ~0xFFF;
-
+
+ if( PAddr < 1024*1024 && (1024*1024-PAddr) >= Number * PAGE_SIZE )
+ {
+ return (void*)(KERNEL_BASE + PAddr);
+ }
+
// Scan List
- for( i = 0; i < NUM_HW_PAGES; i ++ )
+ for( int i = 0; i < NUM_HW_PAGES; i ++ )
{
// Check if addr used
if( gaPageTable[ (HW_MAP_ADDR >> 12) + i ] & 1 )
int i, j;
//Log_Debug("VirtMem", "MM_UnmapHWPages: (VAddr=0x%08x, Number=%i)", VAddr, Number);
-
+
+ //
+ if( KERNEL_BASE <= VAddr && VAddr < KERNEL_BASE + 1024*1024 )
+ return ;
+
// Sanity Check
if(VAddr < HW_MAP_ADDR || VAddr+Number*0x1000 > HW_MAP_MAX) return;