#include <hal_proc.h>
#define TRACE_MAPS 0
+#define TRACE_COW 1
#define AP_KRW_ONLY 1 // Kernel page
#define AP_KRO_ONLY 5 // Kernel RO page
#define AP_RO_USER 2 // User RO Page
#define PADDR_MASK_LVL1 0xFFFFFC00
+const char * const caAPValueNames[] = {
+ "AP_NOACCESS", "AP_KRW_ONLY",
+ "AP_RO_USER", "AP_RW_BOTH",
+ "AP_???_4", "AP_KRO_ONLY",
+ "AP_???_6", "AP_RO_BOTH"
+};
+
// === IMPORTS ===
extern Uint32 kernel_table0[];
#define FRACTAL(table1, addr) ((table1)[ (0xFF8/4*1024) + ((addr)>>22)])
#define USRFRACTAL(addr) (*((Uint32*)(0x7FDFF000) + ((addr)>>22)))
#define TLBIALL() __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0))
-#define TLBIMVA(addr) __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 1;dsb;isb" : : "r" ((addr)&~0xFFF):"memory")
+#define TLBIMVA(addr) __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 1;dsb;isb" : : "r" (((addr)&~0xFFF)|1):"memory")
#define DCCMVAC(addr) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1" : : "r" ((addr)&~0xFFF))
// === PROTOTYPES ===
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);
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR);
// === GLOBALS ===
tPAddr giMM_ZeroPage;
*desc = 0;
TLBIMVA( VAddr );
DCCMVAC( (tVAddr) desc );
- #warning "HACK: TLBIALL"
- TLBIALL();
+// #warning "HACK: TLBIALL"
+// TLBIALL();
LEAVE('i', 0);
return 0;
}
*desc |= (pi->AP & 3) << 4; // AP
*desc |= ((pi->AP >> 2) & 1) << 9; // APX
TLBIMVA( VAddr );
- #warning "HACK: TLBIALL"
- TLBIALL();
+// #warning "HACK: TLBIALL"
+// TLBIALL();
DCCMVAC( (tVAddr) desc );
LEAVE('i', 0);
return 0;
}
// --- Exports ---
-tPAddr MM_GetPhysAddr(tVAddr VAddr)
+tPAddr MM_GetPhysAddr(const void *Ptr)
{
tMM_PageInfo pi;
- if( MM_int_GetPageInfo(VAddr, &pi) )
+ if( MM_int_GetPageInfo((tVAddr)Ptr, &pi) )
return 0;
- return pi.PhysAddr | (VAddr & ((1 << pi.Size)-1));
+ return pi.PhysAddr | ((tVAddr)Ptr & ((1 << pi.Size)-1));
}
Uint MM_GetFlags(tVAddr VAddr)
cur += 256*Table;
- tmp_map = (void*)MM_MapTemp(table);
+ tmp_map = MM_MapTemp(table);
for( i = 0; i < 1024; i ++ )
{
tPAddr newpage;
newpage = MM_AllocPhys();
src = (void*)( (Table*256+i)*0x1000 );
- dst = (void*)MM_MapTemp(newpage);
+ dst = MM_MapTemp(newpage);
// Debug("Taking a copy of kernel page %p (%P)", src, cur[i] & ~0xFFF);
memcpy(dst, src, PAGE_SIZE);
- MM_FreeTemp( (tVAddr)dst );
+ MM_FreeTemp( dst );
tmp_map[i] = newpage | (cur[i] & 0xFFF);
}
else
break;
}
}
- MM_FreeTemp( (tVAddr) tmp_map );
+ MM_FreeTemp( tmp_map );
DestEnt[0] = table + 0*0x400 + 1;
DestEnt[1] = table + 1*0x400 + 1;
ret = MM_AllocateRootTable();
cur = (void*)MM_TABLE0USER;
- new_lvl1_1 = (void*)MM_MapTemp(ret);
- new_lvl1_2 = (void*)MM_MapTemp(ret+0x1000);
+ 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 ++ )
{
{
int j, num;
tPAddr tmp = MM_AllocPhys();
- Uint32 *table = (void*)MM_MapTemp(tmp);
+ Uint32 *table = MM_MapTemp(tmp);
Uint32 sp;
register Uint32 __SP asm("sp");
// Log("page = %P", page);
table[j] = page | 0x813;
- tmp_page = (void*)MM_MapTemp(page);
+ tmp_page = MM_MapTemp(page);
memcpy(tmp_page, (void*)sp, 0x1000);
- MM_FreeTemp( (tVAddr) tmp_page );
+ MM_FreeTemp( tmp_page );
}
- MM_FreeTemp( (tVAddr)table );
+ MM_FreeTemp( table );
}
- MM_FreeTemp( (tVAddr)new_lvl1_1 );
- MM_FreeTemp( (tVAddr)new_lvl1_2 );
+ MM_FreeTemp( new_lvl1_1 );
+ MM_FreeTemp( new_lvl1_2 );
// Log("MM_Clone: ret = %P", ret);
// MM_DumpTables(0, 0x80000000);
}
-tVAddr MM_MapTemp(tPAddr PAddr)
+void *MM_MapTemp(tPAddr PAddr)
{
tVAddr ret;
tMM_PageInfo pi;
MM_RefPhys(PAddr); // Counter the MM_Deallocate in FreeTemp
MM_Map(ret, PAddr);
- return ret;
+ return (void*)ret;
}
Log_Warning("MMVirt", "MM_MapTemp: All slots taken");
return 0;
}
-void MM_FreeTemp(tVAddr VAddr)
+void MM_FreeTemp(void *Ptr)
{
+ tVAddr VAddr = (tVAddr)Ptr;
if( VAddr < MM_TMPMAP_BASE || VAddr >= MM_TMPMAP_END ) {
Log_Warning("MMVirt", "MM_FreeTemp: Passed an addr not from MM_MapTemp (%p)", VAddr);
return ;
tVAddr addr, ofs;
addr = USER_STACK_TOP - USER_STACK_SIZE;
- if( MM_GetPhysAddr(addr + PAGE_SIZE) ) {
+ if( MM_GetPhysAddr( (void*)(addr + PAGE_SIZE) ) ) {
Log_Error("MMVirt", "Unable to create initial user stack, addr %p taken",
addr + PAGE_SIZE
);
{
if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage )
{
- Debug("%p => %8s - 0x%7x %i %x %s",
+ Debug("%p => %8s - 0x%7x D%i %x %s %s",
Start, "ZERO", Len,
Info->Domain, Info->AP,
- Info->bGlobal ? "G" : "nG"
+ Info->bExecutable ? " X" : "nX",
+ Info->bGlobal ? " G" : "nG"
);
}
else
{
- Debug("%p => %8x - 0x%7x %i %x %s",
+ Debug("%p => %8x - 0x%7x D%i %x %s %s",
Start, Info->PhysAddr-Len, Len,
Info->Domain, Info->AP,
- Info->bGlobal ? "G" : "nG"
+ Info->bExecutable ? " X" : "nX",
+ Info->bGlobal ? " G" : "nG"
);
}
}
}
// NOTE: Runs in abort context, not much difference, just a smaller stack
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch)
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR)
{
int rv;
tMM_PageInfo pi;
Log_Error("MMVirt", "Unable to allocate new page for COW");
for(;;);
}
- dst = (void*)MM_MapTemp(newpage);
+ dst = MM_MapTemp(newpage);
src = (void*)(Addr & ~(PAGE_SIZE-1));
memcpy( dst, src, PAGE_SIZE );
- MM_FreeTemp( (tVAddr)dst );
+ MM_FreeTemp( dst );
#if TRACE_COW
Log_Notice("MMVirt", "COW %p caused by %p, %P duped to %P (RefCnt(%i)--)", Addr, PC,
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);
+ const char * const dfsr_errors[] = {
+ /* 00000 */ "-", "Alignment Fault",
+ /* 00010 */ "Debug event", "Access Flag (Section)",
+ /* 00100 */ "Instr Cache Maint", "Translation (Section)",
+ /* 00110 */ "Access Flag (Page)", "Translation (Page)",
+ /* 01000 */ "Sync. External abort", "Domain (Section)",
+ /* 01010 */ "-", "Domain (Page)",
+ /* 01100 */ "Table Walk sync ext (lvl 1)", "Permission (Section)",
+ /* 01110 */ "Table Walk sync ext (lvl 2)", "Permission (Page)",
+ // 0b10000
+ /* 10000 */ "-", "-",
+ /* 10010 */ "-", "-",
+ /* 10100 */ "IMPL (Lockdown)", "-",
+ /* 10110 */ "Async. Extern. Abort", "-",
+ /* 11000 */ "Mem. access async pairity error", "Mem. access async pairity error",
+ /* 11010 */ "IMPL (Coprocessor abort)", "-",
+ /* 11100 */ "Table Walk Sync parity (lvl 1)", "-",
+ /* 11110 */ "Table Walk Sync parity (lvl 2)", "-"
+ };
+ int errcode = (DFSR & 0xF) | (((DFSR >> 10) & 1) << 4);
+ Log_Error("MMVirt", "- Errcode 0b%05b", errcode);
+ Log_Error("MMVirt", "- Dom %i %s %s",
+ (DFSR >> 4) & 0xF, (DFSR & 0x800 ? "Write": "Read"),
+ dfsr_errors[errcode]
+ );
+ Log_Error("MMVirt", "- AP=%i(%s) %s", pi.AP, caAPValueNames[pi.AP], pi.bExecutable ? " Executable":"");
if( Addr < 0x80000000 )
MM_DumpTables(0, 0x80000000);
else