tPAddr MM_AllocateZero(tVAddr VAddr);
tPAddr MM_AllocateRootTable(void);
void MM_int_CloneTable(Uint32 *DestEnt, int Table);
-tPAddr MM_Clone(void);
+tPAddr MM_Clone(int ClearUser);
tVAddr MM_NewKStack(int bGlobal);
void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info);
//void MM_DumpTables(tVAddr Start, tVAddr End);
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR);
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 SystemLR, Uint32 UserLR);
// === GLOBALS ===
tPAddr giMM_ZeroPage;
DestEnt[3] = table + 3*0x400 + 1;
}
-tPAddr MM_Clone(void)
+tPAddr MM_Clone(int EmptyUser)
{
- tPAddr ret;
- Uint32 *new_lvl1_1, *new_lvl1_2, *cur;
Uint32 *tmp_map;
- int i;
// MM_DumpTables(0, KERNEL_BASE);
- ret = MM_AllocateRootTable();
+ tPAddr ret = MM_AllocateRootTable();
- cur = (void*)MM_TABLE0USER;
- new_lvl1_1 = MM_MapTemp(ret);
- new_lvl1_2 = MM_MapTemp(ret+0x1000);
- tmp_map = new_lvl1_1;
- for( i = 0; i < 0x800-4; i ++ )
+ Uint32 *new_lvl1_1 = MM_MapTemp(ret);
+ Uint32 *new_lvl1_2 = MM_MapTemp(ret+0x1000);
+
+ if( !EmptyUser )
{
- // HACK! Ignore the original identity mapping
- if( i == 0 && Threads_GetTID() == 0 ) {
- tmp_map[0] = 0;
- continue;
- }
- if( i == 0x400 )
- tmp_map = &new_lvl1_2[-0x400];
- switch( cur[i] & 3 )
+ Uint32 *cur = (void*)MM_TABLE0USER;
+ tmp_map = new_lvl1_1;
+ for( int i = 0; i < 0x800-4; i ++ )
{
- case 0: tmp_map[i] = 0; break;
- case 1:
- MM_int_CloneTable(&tmp_map[i], i);
- i += 3; // Tables are alocated in blocks of 4
- break;
- case 2:
- case 3:
- Log_Error("MMVirt", "TODO: Support Sections/Supersections in MM_Clone (i=%i)", i);
- tmp_map[i] = 0;
- break;
+ // HACK! Ignore the original identity mapping
+ if( i == 0 && Threads_GetTID() == 0 ) {
+ tmp_map[0] = 0;
+ continue;
+ }
+ if( i == 0x400 )
+ tmp_map = &new_lvl1_2[-0x400];
+ switch( cur[i] & 3 )
+ {
+ case 0: tmp_map[i] = 0; break;
+ case 1:
+ MM_int_CloneTable(&tmp_map[i], i);
+ i += 3; // Tables are alocated in blocks of 4
+ break;
+ case 2:
+ case 3:
+ Log_Error("MMVirt", "TODO: Support Sections/Supersections in MM_Clone (i=%i)", i);
+ tmp_map[i] = 0;
+ break;
+ }
}
}
// Allocate Fractal table
{
- int j, num;
tPAddr tmp = MM_AllocPhys();
Uint32 *table = MM_MapTemp(tmp);
- Uint32 sp;
- register Uint32 __SP asm("sp");
// Map table to last 4MiB of user space
new_lvl1_2[0x3FC] = tmp + 0*0x400 + 1;
new_lvl1_2[0x3FF] = tmp + 3*0x400 + 1;
tmp_map = new_lvl1_1;
- for( j = 0; j < 512; j ++ )
+ int j = 0;
+ for( ; j < 512; j ++ )
{
if( j == 256 )
tmp_map = &new_lvl1_2[-0x400];
// Fractal
table[j++] = (ret + 0x0000) | 0x813;
table[j++] = (ret + 0x1000) | 0x813;
- // Nuke the rest
- for( ; j < 1024; j ++ )
+ // Clear the rest of the table
+ for( ; j < 1024; j ++ )
table[j] = 0;
// Get kernel stack bottom
- sp = __SP & ~(MM_KSTACK_SIZE-1);
+ register Uint32 __SP asm("sp");
+ Uint32 sp = __SP & ~(MM_KSTACK_SIZE-1);
j = (sp / 0x1000) % 1024;
- num = MM_KSTACK_SIZE/0x1000;
-// Log("num = %i, sp = %p, j = %i", num, sp, j);
-
// Copy stack pages
- for(; num--; j ++, sp += 0x1000)
+ for(int num = MM_KSTACK_SIZE/PAGE_SIZE; num--; j ++, sp += PAGE_SIZE)
{
tVAddr page;
void *tmp_page;
Log_Error("MMVirt", "Unable to create initial user stack, addr %p taken",
addr + PAGE_SIZE
);
+ MM_DumpTables(0,KERNEL_BASE);
return 0;
}
}
MM_SetFlags(addr+ofs, 0, MM_PFLAG_KERNEL);
}
-// Log("Return %p", addr + ofs);
+ Log("Return %p", addr + ofs);
// MM_DumpTables(0, 0x80000000);
return addr + ofs;
}
{
if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage )
{
- Debug("%p => %8s - 0x%7x D%i %x %s %s",
+ Debug("0x%08x => %8s - 0x%7x D%i %x %s %s",
Start, "ZERO", Len,
Info->Domain, Info->AP,
Info->bExecutable ? " X" : "nX",
}
else
{
- Debug("%p => %8x - 0x%7x D%i %x %s %s",
+ void *node;
+ MM_GetPageNode(Info->PhysAddr, &node);
+ Debug("0x%08x => %8x - 0x%7x D%i %x %s %s %p",
Start, Info->PhysAddr-Len, Len,
Info->Domain, Info->AP,
Info->bExecutable ? " X" : "nX",
- Info->bGlobal ? " G" : "nG"
+ Info->bGlobal ? " G" : "nG",
+ node
);
}
}
}
// NOTE: Runs in abort context, not much difference, just a smaller stack
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR)
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 SystemLR, Uint32 UserLR)
{
int rv;
tMM_PageInfo pi;
Log_Error("MMVirt", "Code at %p accessed %p (DFSR = 0x%x)%s", PC, Addr, DFSR,
(bPrefetch ? " - Prefetch" : "")
);
- Log_Error("MMVirt", "- User LR = 0x%x", UserLR);
+ Log_Error("MMVirt", "- User LR = 0x%x, System LR = 0x%x", UserLR, SystemLR);
const char * const dfsr_errors[] = {
/* 00000 */ "-", "Alignment Fault",
/* 00010 */ "Debug event", "Access Flag (Section)",
extern void KernelThreadHeader(void); // Actually takes args on stack
extern void Proc_int_DropToUser(Uint32 IP, Uint32 SP) NORETURN __attribute__((long_call));
extern Uint32 Proc_int_SwapUserSP(Uint32 NewSP);
-extern Uint32 Proc_CloneInt(Uint32 *SP, Uint32 *MemPtr);
+extern Uint32 Proc_CloneInt(Uint32 *SP, Uint32 *MemPtr, bool ClearUser);
extern tVAddr MM_NewKStack(int bGlobal); // TODO: Move out into a header
extern tVAddr MM_NewUserStack(void);
extern char kernel_table0[];
void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, const char **ArgV, int DataSize)
{
- Uint32 *usr_sp;
int i;
const char **envp;
tVAddr delta;
// Entrypoint, Base, ArgC, ArgV, DataSize);
// Write data to the user's stack
- usr_sp = (void*)MM_NewUserStack();
+ 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);
if(!new) return -1;
// Actual clone magic
- pc = Proc_CloneInt(&sp, &mem);
+ pc = Proc_CloneInt(&sp, &mem, (Flags & CLONE_NOUSER ? 1 : 0));
if(pc == 0) {
Log("Proc_Clone: In child");
return 0;
if(!next) next = gpIdleThread;
if(!next || next == cur) return;
- Log("Switching to %p (%i %s) IP=%p SP=%p TTBR0=%p UsrSP=%p",
- next, next->TID, next->ThreadName,
- next->SavedState.IP, next->SavedState.SP, next->Process->MemState.Base,
- next->SavedState.UserSP
- );
-
- Log("Requested by %p", __builtin_return_address(0));
+// Log("Switching to %p (%i %s) IP=%p SP=%p TTBR0=%p UsrSP=%p",
+// next, next->TID, next->ThreadName,
+// next->SavedState.IP, next->SavedState.SP, next->Process->MemState.Base,
+// next->SavedState.UserSP
+// );
+// Log("Requested by %p", __builtin_return_address(0));
gpCurrentThread = next;