#include <mm_virt.h>
#include <mm_phys.h>
#include <proc.h>
+#include <hal_proc.h>
#define TAB 22
typedef Uint32 tTabEnt;
// === IMPORTS ===
-extern void _UsertextEnd, _UsertextBase;
+extern char _UsertextEnd[], _UsertextBase[];
extern Uint32 gaInitPageDir[1024];
extern Uint32 gaInitPageTable[1024];
extern void Threads_SegFault(tVAddr Addr);
void MM_PreinitVirtual(void);
void MM_InstallVirtual(void);
void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
-void MM_DumpTables(tVAddr Start, tVAddr End);
-tVAddr MM_ClearUser(void);
+//void MM_DumpTables(tVAddr Start, tVAddr End);
+//void MM_ClearUser(void);
tPAddr MM_DuplicatePage(tVAddr VAddr);
// === GLOBALS ===
gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE;
}
- Log_Debug("MMVirt", "COW for %p", Addr);
+// Log_Debug("MMVirt", "COW for %p (%P)", Addr, gaPageTable[Addr>>12]);
INVLPG( Addr & ~0xFFF );
return;
}
+ __asm__ __volatile__ ("pushf; andw $0xFEFF, 0(%esp); popf");
+ Proc_GetCurThread()->bInstrTrace = 0;
+
// If it was a user, tell the thread handler
if(ErrorCode & 4) {
- Log_Warning("MMVirt", "%s %s %s memory%s",
- (ErrorCode&4?"User":"Kernel"),
+ Log_Warning("MMVirt", "User %s %s memory%s",
(ErrorCode&2?"write to":"read from"),
(ErrorCode&1?"bad/locked":"non-present"),
(ErrorCode&16?" (Instruction Fetch)":"")
);
- Warning("User Pagefault: Instruction at %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr);
+ Log_Warning("MMVirt", "Instruction %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr);
__asm__ __volatile__ ("sti"); // Restart IRQs
#if 1
Error_Backtrace(Regs->eip, Regs->ebp);
Warning("Reserved Bits Trashed!");
else
{
- Warning("%s %s %s memory%s",
- (ErrorCode&4?"User":"Kernel"),
+ Warning("Kernel %s %s memory%s",
(ErrorCode&2?"write to":"read from"),
(ErrorCode&1?"bad/locked":"non-present"),
(ErrorCode&16?" (Instruction Fetch)":"")
if( !(gaPageDir[curPos>>22] & PF_PRESENT)
|| !(gaPageTable[page] & PF_PRESENT)
|| (gaPageTable[page] & MASK) != expected
- || (tmpnode=NULL,MM_GetPageNode(curPos, &tmpnode), tmpnode != expected_node))
+ || (tmpnode=NULL,MM_GetPageNode(expected, &tmpnode), tmpnode != expected_node))
{
if(expected) {
tPAddr orig = gaPageTable[rangeStart>>12];
if( !(gaPageTable[curPos>>12] & PF_PRESENT) ) continue;
expected = (gaPageTable[page] & MASK);
- MM_GetPageNode(curPos, &expected_node);
+ MM_GetPageNode(expected, &expected_node);
rangeStart = curPos;
}
if(expected) expected += 0x1000;
}
/**
- * \fn tVAddr MM_ClearUser()
* \brief Clear user's address space
*/
-tVAddr MM_ClearUser(void)
+void MM_ClearUser(void)
{
Uint i, j;
INVLPG( &gaPageTable[i*1024] );
}
INVLPG( gaPageDir );
-
- return *gpPageCR3;
}
/**
* \fn tVAddr MM_NewWorkerStack()
* \brief Creates a new worker stack
*/
-tVAddr MM_NewWorkerStack()
+tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize)
{
- Uint esp, ebp;
- Uint oldstack;
Uint base, addr;
- int i, j;
- Uint *tmpPage;
- tPAddr pages[WORKER_STACK_SIZE>>12];
-
- // Get the old ESP and EBP
- __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp));
- __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp));
+ tVAddr tmpPage;
+ tPAddr page;
// TODO: Thread safety
// Find a free worker stack address
// Mapping Time!
for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 )
- //for( addr = WORKER_STACK_SIZE; addr; addr -= 0x1000 )
{
- pages[ addr >> 12 ] = MM_AllocPhys();
- gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3;
+ page = MM_AllocPhys();
+ gaTmpTable[ (base + addr) >> 12 ] = page | 3;
}
*gpTmpCR3 = 0;
// Release the temp mapping lock
Mutex_Release(&glTempFractal);
-
- // Copy the old stack
- 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)
- for(addr = 0; addr < esp; addr += 0x1000)
- {
- Uint *stack = (Uint*)( oldstack-(addr+0x1000) );
- tmpPage = (void*)MM_MapTemp( pages[i] );
- // Copy old stack
- for(j = 0; j < 1024; j++)
- {
- // Possible Stack address?
- if(oldstack-esp < stack[j] && stack[j] < oldstack)
- tmpPage[j] = base - (oldstack - stack[j]);
- else // Seems not, best leave it alone
- tmpPage[j] = stack[j];
- }
- MM_FreeTemp((tVAddr)tmpPage);
- i --;
- }
+
+ // NOTE: Max of 1 page
+ // `page` is the last allocated page from the previious for loop
+ tmpPage = MM_MapTemp( page );
+ memcpy( (void*)( tmpPage + (0x1000 - ContentsSize) ), StackContents, ContentsSize);
+ MM_FreeTemp(tmpPage);
//Log("MM_NewWorkerStack: RETURN 0x%x", base);
- return base;
+ return base + WORKER_STACK_SIZE;
}
/**
return ret;
}
+/**
+ * \brief Check if the provided buffer is valid
+ * \return Boolean valid
+ */
+int MM_IsValidBuffer(tVAddr Addr, size_t Size)
+{
+ int bIsUser;
+ int dir, tab;
+
+ Size += Addr & (PAGE_SIZE-1);
+ Addr &= ~(PAGE_SIZE-1);
+
+ dir = Addr >> 22;
+ tab = Addr >> 12;
+
+// Debug("Addr = %p, Size = 0x%x, dir = %i, tab = %i", Addr, Size, dir, tab);
+
+ if( !(gaPageDir[dir] & 1) ) return 0;
+ if( !(gaPageTable[tab] & 1) ) return 0;
+
+ bIsUser = !!(gaPageTable[tab] & PF_USER);
+
+ while( Size >= PAGE_SIZE )
+ {
+ if( (tab & 1023) == 0 )
+ {
+ dir ++;
+ if( !(gaPageDir[dir] & 1) ) return 0;
+ }
+
+ if( !(gaPageTable[tab] & 1) ) return 0;
+ if( bIsUser && !(gaPageTable[tab] & PF_USER) ) return 0;
+
+ tab ++;
+ Size -= PAGE_SIZE;
+ }
+ return 1;
+}
+
/**
* \fn tPAddr MM_DuplicatePage(tVAddr VAddr)
* \brief Duplicates a virtual page to a physical one