From c2bba6e776701404229ef2bebe10c8dc9046b026 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 26 Oct 2011 21:12:50 +0800 Subject: [PATCH] Kernel/armv7 - Bugfixes - Added .usertext for drop function - Fixed all (maybe) kernel permissions failures - Saved user SP on task switch - Fixed clearing VFS handles on MM_Clear, and not copying them in MM_Clone --- Kernel/arch/armv7/link.ld | 13 +++++++++++ Kernel/arch/armv7/mm_virt.c | 46 +++++++++++++++++++++++++++++-------- Kernel/arch/armv7/proc.S | 38 +++++++++++++++--------------- Kernel/arch/armv7/proc.c | 17 +++++++++++--- Kernel/arch/armv7/start.S | 14 ++++++----- 5 files changed, 92 insertions(+), 36 deletions(-) diff --git a/Kernel/arch/armv7/link.ld b/Kernel/arch/armv7/link.ld index b1ae2957..bf07b4cb 100644 --- a/Kernel/arch/armv7/link.ld +++ b/Kernel/arch/armv7/link.ld @@ -1,6 +1,7 @@ ENTRY (_start) _kernel_base = 0x80000000; +_usertext_vbase = 0xFFFFE000; SECTIONS { @@ -15,6 +16,18 @@ SECTIONS *(.text*) *(.rodata*) } + + + /* HACKS: User accesible .text section */ + . = ALIGN(0x1000); + gUsertextPhysStart = . - _kernel_base; + . = _usertext_vbase; + .usertext : AT( gUsertextPhysStart ) + { + *(.usertext) + } + . += gUsertextPhysStart + _kernel_base - _usertext_vbase; + /* 0x4000 (4 pages) alignment needed for root table */ .data ALIGN(0x4000) : AT( ADDR(.data) - _kernel_base ) { diff --git a/Kernel/arch/armv7/mm_virt.c b/Kernel/arch/armv7/mm_virt.c index 8689e096..3b4e5198 100644 --- a/Kernel/arch/armv7/mm_virt.c +++ b/Kernel/arch/armv7/mm_virt.c @@ -360,7 +360,7 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) if( MM_int_GetPageInfo(VAddr, &pi) ) return ; - curFlags = MM_GetPhysAddr(VAddr); + curFlags = MM_GetFlags(VAddr); if( (curFlags & Mask) == Flags ) return ; curFlags &= ~Mask; @@ -516,10 +516,26 @@ void MM_int_CloneTable(Uint32 *DestEnt, int Table) case 3: // Small page // - If full RW - Debug("%p cur[%i] & 0x230 = 0x%x", Table*256*0x1000, i, cur[i] & 0x230); - if( (cur[i] & 0x230) == 0x030 ) - cur[i] |= 0x200; // Set to full RO (Full RO=COW, User RO = RO) - tmp_map[i] = cur[i]; +// Debug("%p cur[%i] & 0x230 = 0x%x", Table*256*0x1000, i, cur[i] & 0x230); + if( (cur[i] & 0x230) == 0x010 ) + { + void *dst, *src; + tPAddr newpage; + newpage = MM_AllocPhys(); + src = (void*)( (Table*256+i)*0x1000 ); + dst = (void*)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 ); + tmp_map[i] = newpage | (cur[i] & 0xFFF); + } + else + { + if( (cur[i] & 0x230) == 0x030 ) + cur[i] |= 0x200; // Set to full RO (Full RO=COW, User RO = RO) + tmp_map[i] = cur[i]; + MM_RefPhys( tmp_map[i] & ~0xFFF ); + } break; } } @@ -638,12 +654,15 @@ tPAddr MM_Clone(void) void MM_ClearUser(void) { int i, j; + const int user_table_count = USER_STACK_TOP / (256*0x1000); Uint32 *cur = (void*)MM_TABLE0USER; Uint32 *tab; // MM_DumpTables(0, 0x80000000); - for( i = 0; i < 0x800-4; i ++ ) + Log("user_table_count = %i (as opposed to %i)", user_table_count, 0x800-4); + + for( i = 0; i < user_table_count; i ++ ) { switch( cur[i] & 3 ) { @@ -678,6 +697,9 @@ void MM_ClearUser(void) cur[i] = 0; } + // Final block of 4 tables are KStack + i = 0x800 - 4; + // Clear out unused stacks { register Uint32 __SP asm("sp"); @@ -869,8 +891,8 @@ tVAddr MM_NewUserStack(void) } MM_SetFlags(addr+ofs, 0, MM_PFLAG_KERNEL); } - Log("Return %p", addr + ofs); - MM_DumpTables(0, 0x80000000); +// Log("Return %p", addr + ofs); +// MM_DumpTables(0, 0x80000000); return addr + ofs; } @@ -943,7 +965,6 @@ void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch) // Check for COW if( rv == 0 && pi.AP == AP_RO_BOTH ) { - Log_Notice("MMVirt", "COW %p caused by %p", Addr, PC); pi.AP = AP_RW_BOTH; if( MM_GetRefCount(pi.PhysAddr) > 1 ) { @@ -961,8 +982,15 @@ void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch) memcpy( dst, src, PAGE_SIZE ); MM_FreeTemp( (tVAddr)dst ); + Log_Notice("MMVirt", "COW %p caused by %p, %P duped to %P", Addr, PC, + pi.PhysAddr, newpage); + + MM_DerefPhys(pi.PhysAddr); pi.PhysAddr = newpage; } + else { + Log_Notice("MMVirt", "COW %p caused by %p, took last reference to %P", Addr, PC, pi.PhysAddr); + } // Unset COW pi.AP = AP_RW_BOTH; MM_int_SetPageInfo(Addr, &pi); diff --git a/Kernel/arch/armv7/proc.S b/Kernel/arch/armv7/proc.S index 44ce9eea..4d7c89f7 100644 --- a/Kernel/arch/armv7/proc.S +++ b/Kernel/arch/armv7/proc.S @@ -27,14 +27,6 @@ KernelThreadHeader: bl Threads_Exit b . -.globl Proc_int_DropToUser -@ R0: User IP -@ R1: User SP -Proc_int_DropToUser: - cps #16 - mov sp, r1 - mov pc, r0 - .globl SwitchTask @ R0: New stack @ R1: Pointer to where to save old stack @@ -81,19 +73,29 @@ Proc_CloneInt: ldr r0, =Proc_CloneInt_new pop {r4-r12,pc} Proc_CloneInt_new: -@ cps #18 - -@ mov r0, #0 -@ mvn r1, #0 -@ bl MM_DumpTables - -@ ldr r0, =csProc_CloneInt_NewTaskMessage -@ bl Log - -@ cps #19 mov r0, #0 pop {r4-r12,pc} +@ R0: New user SP +@ Return: Old user SP +.globl Proc_int_SwapUserSP +Proc_int_SwapUserSP: + cps #31 @ Go to system mode + mov r1, sp + tst r0, r0 @ Only update if non-zero + movne sp, r0 + mov r0, r1 + cps #19 + mov pc, lr + +.section .usertext, "ax" +.globl Proc_int_DropToUser +@ R0: User IP +@ R1: User SP +Proc_int_DropToUser: + cps #16 + mov sp, r1 + mov pc, r0 .section .rodata csProc_CloneInt_NewTaskMessage: diff --git a/Kernel/arch/armv7/proc.c b/Kernel/arch/armv7/proc.c index 08257d99..605b156c 100644 --- a/Kernel/arch/armv7/proc.c +++ b/Kernel/arch/armv7/proc.c @@ -14,6 +14,7 @@ extern tThread gThreadZero; extern void SwitchTask(Uint32 NewSP, Uint32 *OldSP, Uint32 NewIP, Uint32 *OldIP, Uint32 MemPtr); extern void KernelThreadHeader(void); // Actually takes args on stack extern void Proc_int_DropToUser(Uint32 IP, Uint32 SP) NORETURN; +extern Uint32 Proc_int_SwapUserSP(Uint32 NewSP); extern Uint32 Proc_CloneInt(Uint32 *SP, Uint32 *MemPtr); extern tVAddr MM_NewKStack(int bGlobal); // TODO: Move out into a header extern tVAddr MM_NewUserStack(void); @@ -92,7 +93,12 @@ void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, int DataS // Drop to user code Log_Debug("Proc", "Proc_int_DropToUser(%p, %p)", Entrypoint, usr_sp); - Proc_int_DropToUser(Entrypoint, (Uint32)usr_sp); + + // Needed to get around relocation truncation + { + void (*drop)(Uint32, Uint32) NORETURN = Proc_int_DropToUser; + drop(Entrypoint, (Uint32)usr_sp); + } } tTID Proc_Clone(Uint Flags) @@ -112,6 +118,8 @@ tTID Proc_Clone(Uint Flags) new->SavedState.IP = pc; new->SavedState.SP = sp; + new->SavedState.UserSP = Proc_int_SwapUserSP(0); + new->SavedState.UserIP = Proc_GetCurThread()->SavedState.UserIP; new->MemState.Base = mem; Threads_AddActive(new); @@ -197,14 +205,17 @@ void Proc_Reschedule(void) if(!next) next = gpIdleThread; if(!next || next == cur) return; - Log("Switching to %p (%i %s) IP=%p SP=%p TTBR0=%p", + 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->MemState.Base + next->SavedState.IP, next->SavedState.SP, next->MemState.Base, + next->SavedState.UserSP ); Log("Requested by %p", __builtin_return_address(0)); gpCurrentThread = next; + cur->SavedState.UserSP = Proc_int_SwapUserSP( next->SavedState.UserSP ); + SwitchTask( next->SavedState.SP, &cur->SavedState.SP, next->SavedState.IP, &cur->SavedState.IP, diff --git a/Kernel/arch/armv7/start.S b/Kernel/arch/armv7/start.S index 3c0779fb..589ef19b 100644 --- a/Kernel/arch/armv7/start.S +++ b/Kernel/arch/armv7/start.S @@ -89,10 +89,10 @@ SVC_Handler: ldr r4, =SyscallHandler blx r4 - ldr r0, =csSyscallPrintRetAddr - ldr r1, [sp,#9*4+5*4] - ldr r4, =Log - blx r4 +@ ldr r0, =csSyscallPrintRetAddr +@ ldr r1, [sp,#9*4+5*4] +@ ldr r4, =Log +@ blx r4 pop {r2} @ errno pop {r0,r1} @ Ret/RetHi @@ -270,7 +270,7 @@ kernel_table1_map: @ Size = 4KiB .rept (0xF00+16)/4 .long 0 .endr - .long hwmap_table_0 - KERNEL_BASE + (1 << 4) + 3 + .long hwmap_table_0 - KERNEL_BASE + 0x13 .rept 0xFF8/4 - (0xF00+16)/4 - 1 .long 0 .endr @@ -295,9 +295,11 @@ kernel_exception_map: .long 0 .endr .long 0x212 @ Map first page for exceptions (Kernel RO, Execute) - .rept 15 + .rept 16-1-2 .long 0 .endr + .long gUsertextPhysStart + 0x22 @ User .text (User RO, Kernel RW, because both is COW) + .long 0 .section .padata stack: -- 2.20.1