* 0xFF - System Calls / Kernel's User Code
*/
#define DEBUG 1
-#include <common.h>
+#include <acess.h>
#include <mm_phys.h>
#include <proc.h>
+#if USE_PAE
+# define TAB 21
+# define DIR 30
+#else
+# define TAB 22
+#endif
+
#define KERNEL_STACKS 0xF0000000
-#define KERNEL_STACK_SIZE 0x00002000
-#define KERNEL_STACKS_END 0xFD000000
+#define KERNEL_STACK_SIZE 0x00008000
+#define KERNEL_STACKS_END 0xFC000000
#define WORKER_STACKS 0x00100000 // Thread0 Only!
#define WORKER_STACK_SIZE KERNEL_STACK_SIZE
#define WORKER_STACKS_END 0xB0000000
#define NUM_WORKER_STACKS ((WORKER_STACKS_END-WORKER_STACKS)/WORKER_STACK_SIZE)
-#define PAGE_TABLE_ADDR 0xFD000000
-#define PAGE_DIR_ADDR 0xFD3F4000
-#define PAGE_CR3_ADDR 0xFD3F4FD0
-#define TMP_CR3_ADDR 0xFD3F4FD4 // Part of core instead of temp
-#define TMP_DIR_ADDR 0xFD3F5000 // Same
-#define TMP_TABLE_ADDR 0xFD400000
-#define HW_MAP_ADDR 0xFD800000
-#define HW_MAP_MAX 0xFEFF0000
+
+#define PAE_PAGE_TABLE_ADDR 0xFC000000 // 16 MiB
+#define PAE_PAGE_DIR_ADDR 0xFCFC0000 // 16 KiB
+#define PAE_PAGE_PDPT_ADDR 0xFCFC3F00 // 32 bytes
+#define PAE_TMP_PDPT_ADDR 0xFCFC3F20 // 32 bytes
+#define PAE_TMP_DIR_ADDR 0xFCFE0000 // 16 KiB
+#define PAE_TMP_TABLE_ADDR 0xFD000000 // 16 MiB
+
+#define PAGE_TABLE_ADDR 0xFC000000
+#define PAGE_DIR_ADDR 0xFC3F0000
+#define PAGE_CR3_ADDR 0xFC3F0FC0
+#define TMP_CR3_ADDR 0xFC3F0FC4 // Part of core instead of temp
+#define TMP_DIR_ADDR 0xFC3F1000 // Same
+#define TMP_TABLE_ADDR 0xFC400000
+
+#define HW_MAP_ADDR 0xFE000000
+#define HW_MAP_MAX 0xFFEF0000
#define NUM_HW_PAGES ((HW_MAP_MAX-HW_MAP_ADDR)/0x1000)
-#define TEMP_MAP_ADDR 0xFEFF0000 // Allows 16 "temp" pages
+#define TEMP_MAP_ADDR 0xFFEF0000 // Allows 16 "temp" pages
#define NUM_TEMP_PAGES 16
+#define LAST_BLOCK_ADDR 0xFFFF0000 // Free space for kernel provided user code/ *(-1) protection
#define PF_PRESENT 0x1
#define PF_WRITE 0x2
#define INVLPG(addr) __asm__ __volatile__ ("invlpg (%0)"::"r"(addr))
+#if USE_PAE
+typedef Uint64 tTabEnt;
+#else
+typedef Uint32 tTabEnt;
+#endif
+
// === IMPORTS ===
extern Uint32 gaInitPageDir[1024];
extern Uint32 gaInitPageTable[1024];
tPAddr MM_DuplicatePage(tVAddr VAddr);
// === GLOBALS ===
-tPAddr *gaPageTable = (void*)PAGE_TABLE_ADDR;
-tPAddr *gaPageDir = (void*)PAGE_DIR_ADDR;
-tPAddr *gaPageCR3 = (void*)PAGE_CR3_ADDR;
-tPAddr *gaTmpTable = (void*)TMP_TABLE_ADDR;
-tPAddr *gaTmpDir = (void*)TMP_DIR_ADDR;
-tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR;
+#define gaPageTable ((tTabEnt*)PAGE_TABLE_ADDR)
+#define gaPageDir ((tTabEnt*)PAGE_DIR_ADDR)
+#define gaTmpTable ((tTabEnt*)TMP_TABLE_ADDR)
+#define gaTmpDir ((tTabEnt*)TMP_DIR_ADDR)
+#define gpPageCR3 ((tTabEnt*)PAGE_CR3_ADDR)
+#define gpTmpCR3 ((tTabEnt*)TMP_CR3_ADDR)
+
+#define gaPAE_PageTable ((tTabEnt*)PAE_PAGE_TABLE_ADDR)
+#define gaPAE_PageDir ((tTabEnt*)PAE_PAGE_DIR_ADDR)
+#define gaPAE_MainPDPT ((tTabEnt*)PAE_PAGE_PDPT_ADDR)
+#define gaPAE_TmpTable ((tTabEnt*)PAE_TMP_DIR_ADDR)
+#define gaPAE_TmpDir ((tTabEnt*)PAE_TMP_DIR_ADDR)
+#define gaPAE_TmpPDPT ((tTabEnt*)PAE_TMP_PDPT_ADDR)
+ int gbUsePAE = 0;
int gilTempMappings = 0;
int gilTempFractal = 0;
-Uint32 gWorkerStacks[NUM_WORKER_STACKS/32];
+Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32];
int giLastUsedWorker = 0;
// === CODE ===
*/
void MM_PreinitVirtual()
{
+ #if USE_PAE
+ gaInitPDPT[ 0 ] = 0;
+ gaInitPageDir[ ((PAGE_TABLE_ADDR >> TAB)-3*512+3)*2 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3;
+ #else
gaInitPageDir[ 0 ] = 0;
- gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((Uint)&gaInitPageDir - KERNEL_BASE) | 3;
+ gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3;
+ #endif
+ INVLPG( PAGE_TABLE_ADDR );
}
/**
{
int i;
+ #if USE_PAE
+ // --- Pre-Allocate kernel tables
+ for( i = KERNEL_BASE >> TAB; i < 1024*4; i ++ )
+ {
+ if( gaPAE_PageDir[ i ] ) continue;
+
+ // Skip stack tables, they are process unique
+ if( i > KERNEL_STACKS >> TAB && i < KERNEL_STACKS_END >> TAB) {
+ gaPAE_PageDir[ i ] = 0;
+ continue;
+ }
+ // Preallocate table
+ gaPAE_PageDir[ i ] = MM_AllocPhys() | 3;
+ INVLPG( &gaPAE_PageTable[i*512] );
+ memset( &gaPAE_PageTable[i*512], 0, 0x1000 );
+ }
+ #else
// --- Pre-Allocate kernel tables
for( i = KERNEL_BASE>>22; i < 1024; i ++ )
{
INVLPG( &gaPageTable[i*1024] );
memset( &gaPageTable[i*1024], 0, 0x1000 );
}
+ #endif
}
/**
if( gaPageDir[Addr>>22] & PF_PRESENT )
Log("gaPageTable[0x%x] = 0x%x", Addr>>12, gaPageTable[Addr>>12]);
- MM_DumpTables(0, -1);
+ //MM_DumpTables(0, -1);
- Panic("Page Fault at 0x%x\n", Regs->eip);
+ Panic("Page Fault at 0x%x (Accessed 0x%x)", Regs->eip, Addr);
}
/**
tPAddr MM_Allocate(tVAddr VAddr)
{
tPAddr paddr;
+ //ENTER("xVAddr", VAddr);
+ //__asm__ __volatile__ ("xchg %bx,%bx");
// Check if the directory is mapped
if( gaPageDir[ VAddr >> 22 ] == 0 )
{
// Allocate directory
paddr = MM_AllocPhys();
+ //LOG("paddr = 0x%llx (new table)", paddr);
if( paddr == 0 ) {
Warning("MM_Allocate - Out of Memory (Called by %p)", __builtin_return_address(0));
+ LEAVE('i',0);
return 0;
}
// Map
if(VAddr < MM_USER_MAX) gaPageDir[ VAddr >> 22 ] |= PF_USER;
INVLPG( &gaPageDir[ VAddr >> 22 ] );
+ //LOG("Clearing new table");
memsetd( &gaPageTable[ (VAddr >> 12) & ~0x3FF ], 0, 1024 );
}
// Check if the page is already allocated
else if( gaPageTable[ VAddr >> 12 ] != 0 ) {
Warning("MM_Allocate - Allocating to used address (%p)", VAddr);
+ //LEAVE('X', gaPageTable[ VAddr >> 12 ] & ~0xFFF);
return gaPageTable[ VAddr >> 12 ] & ~0xFFF;
}
// Allocate
paddr = MM_AllocPhys();
+ //LOG("paddr = 0x%llx", paddr);
if( paddr == 0 ) {
Warning("MM_Allocate - Out of Memory when allocating at %p (Called by %p)",
VAddr, __builtin_return_address(0));
+ //LEAVE('i',0);
return 0;
}
// Map
// Invalidate Cache for address
INVLPG( VAddr & ~0xFFF );
+ //LEAVE('X', paddr);
return paddr;
}
return (gaPageTable[Addr >> 12] & ~0xFFF) | (Addr & 0xFFF);
}
+
+/**
+ * \fn int MM_IsUser(tVAddr VAddr)
+ * \brief Checks if a page is user accessable
+ */
+int MM_IsUser(tVAddr VAddr)
+{
+ if( !(gaPageDir[VAddr >> 22] & 1) )
+ return 0;
+ if( !(gaPageTable[VAddr >> 12] & 1) )
+ return 0;
+ if( !(gaPageTable[VAddr >> 12] & PF_USER) )
+ return 0;
+ return 1;
+}
+
/**
* \fn void MM_SetCR3(tPAddr CR3)
* \brief Sets the current process space
}
INVLPG( gaPageDir );
- return *gaPageCR3;
+ return *gpPageCR3;
}
/**
LOCK( &gilTempFractal );
// Create Directory Table
- *gTmpCR3 = MM_AllocPhys() | 3;
+ *gpTmpCR3 = MM_AllocPhys() | 3;
INVLPG( gaTmpDir );
- //LOG("Allocated Directory (%x)", *gTmpCR3);
+ //LOG("Allocated Directory (%x)", *gpTmpCR3);
memsetd( gaTmpDir, 0, 1024 );
// Copy Tables
{
// Fractal
if( i == (PAGE_TABLE_ADDR >> 22) ) {
- gaTmpDir[ PAGE_TABLE_ADDR >> 22 ] = *gTmpCR3;
+ gaTmpDir[ PAGE_TABLE_ADDR >> 22 ] = *gpTmpCR3;
continue;
}
}
}
- ret = *gTmpCR3 & ~0xFFF;
+ ret = *gpTmpCR3 & ~0xFFF;
RELEASE( &gilTempFractal );
//LEAVE('x', ret);
if( gWorkerStacks[base/32] & (1 << base) ) {
continue;
}
+ break;
}
if(base >= NUM_WORKER_STACKS) {
Warning("Uh-oh! Out of worker stacks");
giLastUsedWorker = base;
// We have one
base = WORKER_STACKS + base * WORKER_STACK_SIZE;
+ //Log(" MM_NewWorkerStack: base = 0x%x", base);
// Acquire the lock for the temp fractal mappings
LOCK(&gilTempFractal);
// Set the temp fractals to TID0's address space
- *gTmpCR3 = (Uint)gaInitPageDir | 3;
+ *gpTmpCR3 = ((Uint)gaInitPageDir - KERNEL_BASE) | 3;
+ //Log(" MM_NewWorkerStack: *gpTmpCR3 = 0x%x", *gpTmpCR3);
INVLPG( gaTmpDir );
+
// Check if the directory is mapped (we are assuming that the stacks
- // will fit neatly in a directory
+ // will fit neatly in a directory)
+ //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]);
if(gaTmpDir[ base >> 22 ] == 0) {
gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3;
- INVLPG( &gaTmpTable[ (base>>22) & ~0x3FF ] );
+ INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] );
}
// Mapping Time!
pages[ addr >> 12 ] = MM_AllocPhys();
gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3;
}
+ *gpTmpCR3 = 0;
// Release the temp mapping lock
RELEASE(&gilTempFractal);
oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1);
esp = oldstack - esp; // ESP as an offset in the stack
+ // Make `base` be the top of the stack
+ base += WORKER_STACK_SIZE;
+
i = (WORKER_STACK_SIZE>>12) - 1;
// Copy the contents of the old stack to the new one, altering the addresses
// `addr` is refering to bytes from the stack base (mem downwards)
else // Seems not, best leave it alone
tmpPage[j] = stack[j];
}
- MM_FreeTemp((Uint)tmpPage);
+ MM_FreeTemp((tVAddr)tmpPage);
i --;
}
+ //Log("MM_NewWorkerStack: RETURN 0x%x", base);
return base;
}
*/
void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
{
- tPAddr *ent;
+ tTabEnt *ent;
if( !(gaPageDir[VAddr >> 22] & 1) ) return ;
if( !(gaPageTable[VAddr >> 12] & 1) ) return ;
}
// Slow Allocate
- phys = MM_AllocPhysRange(Pages);
+ phys = MM_AllocPhysRange(Pages, MaxBits);
// - Was it allocated?
if(phys == 0) {
LEAVE('i', 0);
return 0;
}
- // - Check if the memory is OK
- if(phys + (Pages-1)*0x1000 > maxCheck)
- {
- // Deallocate and return 0
- for(;Pages--;phys+=0x1000)
- MM_DerefPhys(phys);
- LEAVE('i', 0);
- return 0;
- }
// Allocated successfully, now map
ret = MM_MapHWPage(phys, Pages);