From c1b768104a3458d08e7c7240aaac82fc7e70e3df Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Mon, 26 Nov 2012 16:05:26 +0800 Subject: [PATCH] Kernel/x86_64 - Debugging GUI errors (and a wild goose chase) --- KernelLand/Kernel/arch/x86_64/desctab.asm | 22 +++++-- KernelLand/Kernel/arch/x86_64/errors.c | 4 ++ .../Kernel/arch/x86_64/include/mm_virt.h | 2 +- KernelLand/Kernel/arch/x86_64/mm_virt.c | 64 ++++++++++++++----- KernelLand/Kernel/arch/x86_64/proc.asm | 2 + KernelLand/Kernel/arch/x86_64/proc.c | 23 ++++++- KernelLand/Kernel/libc.c | 7 +- KernelLand/Kernel/syscalls.c | 13 ++-- KernelLand/Kernel/threads.c | 2 +- KernelLand/Modules/Display/BochsGA/bochsvbe.c | 2 - 10 files changed, 105 insertions(+), 36 deletions(-) diff --git a/KernelLand/Kernel/arch/x86_64/desctab.asm b/KernelLand/Kernel/arch/x86_64/desctab.asm index 22b41be0..e8331735 100644 --- a/KernelLand/Kernel/arch/x86_64/desctab.asm +++ b/KernelLand/Kernel/arch/x86_64/desctab.asm @@ -276,17 +276,23 @@ DEFIRQ i %assign i i+1 %endrep +[extern Proc_int_SetIRQIP] + [global IrqCommon] IrqCommon: PUSH_GPR push gs push fs - + + mov rdi, [rsp+(16+2+2)*8] ; 2SReg + GPRs + Int/Errcode = RIP + call Proc_int_SetIRQIP + push rax + ; mov rdi, csIRQ_Fired ; mov rsi, [rsp+(16+2)*8] ; call Log - mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs) + mov ebx, [rsp+(1+2+16)*8] ; Get interrupt number (16 GPRS + 2 SRs) shl ebx, 2 ; *4 mov rax, gaIRQ_Handlers lea rbx, [rax+rbx*8] @@ -300,7 +306,7 @@ IrqCommon: test rax, rax ; Check if it exists jz .skip.%[i] ; Set RDI to IRQ number - mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number + mov rdi, [rsp+(16+2+1+1)*8] ; Get IRQ number mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs] call rax ; Call .skip.%[i]: @@ -311,12 +317,15 @@ IrqCommon: ; ACK mov al, 0x20 - mov rdi, [rsp+(16+2)*8] ; Get IRQ number + mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number cmp rdi, 8 jb .skipAckSecondary out 0xA0, al .skipAckSecondary: out 0x20, al + + pop rdi + call Proc_int_SetIRQIP pop fs pop gs @@ -398,7 +407,10 @@ SyscallStub: mov [rsp+0x28], r10 ; Arg4 mov [rsp+0x30], r8 ; Arg5 mov [rsp+0x38], r9 ; Arg6 - + + mov rdi, rcx + call Proc_int_SetIRQIP + mov rdi, rsp sub rsp, 8 call SyscallHandler diff --git a/KernelLand/Kernel/arch/x86_64/errors.c b/KernelLand/Kernel/arch/x86_64/errors.c index e7812c3e..fda31139 100644 --- a/KernelLand/Kernel/arch/x86_64/errors.c +++ b/KernelLand/Kernel/arch/x86_64/errors.c @@ -13,6 +13,7 @@ extern int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs); extern void Error_Backtrace(Uint IP, Uint BP); extern void Proc_EnableSSE(void); +extern void Threads_Dump(void); extern void Proc_RestoreSSE(Uint32 Data); // === PROTOTYPES === @@ -98,6 +99,9 @@ void Error_Handler(tRegs *Regs) *(Uint8*)(Regs->RIP+2), *(Uint8*)(Regs->RIP+3) ); break; + case 2: // NMI + Threads_Dump(); + break; } __asm__ __volatile__ ("cli"); diff --git a/KernelLand/Kernel/arch/x86_64/include/mm_virt.h b/KernelLand/Kernel/arch/x86_64/include/mm_virt.h index 6cf25f02..120afb3f 100644 --- a/KernelLand/Kernel/arch/x86_64/include/mm_virt.h +++ b/KernelLand/Kernel/arch/x86_64/include/mm_virt.h @@ -84,7 +84,7 @@ // === FUNCTIONS === void MM_FinishVirtualInit(void); tVAddr MM_NewKStack(void); -tVAddr MM_Clone(void); +tVAddr MM_Clone(int bCopyUser); tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize); #endif diff --git a/KernelLand/Kernel/arch/x86_64/mm_virt.c b/KernelLand/Kernel/arch/x86_64/mm_virt.c index e1e59c08..de7ae521 100644 --- a/KernelLand/Kernel/arch/x86_64/mm_virt.c +++ b/KernelLand/Kernel/arch/x86_64/mm_virt.c @@ -722,43 +722,73 @@ int MM_IsValidBuffer(tVAddr Addr, size_t Size) Size += Addr & (PAGE_SIZE-1); Addr &= ~(PAGE_SIZE-1); - Addr &= ((1UL << 48)-1); // Clap to address space + // NC addr + if( ((Addr >> 47) & 1) != ((Addr>>48) == 0xFFFF)) + return 0; + Addr &= ((1UL << 48)-1); // Clamp to address space pml4 = Addr >> 39; pdp = Addr >> 30; dir = Addr >> 21; tab = Addr >> 12; - if( !(PAGEMAPLVL4(pml4) & 1) ) return 0; - if( !(PAGEDIRPTR(pdp) & 1) ) return 0; - if( !(PAGEDIR(dir) & 1) ) return 0; - if( !(PAGETABLE(tab) & 1) ) return 0; + if( !(PAGEMAPLVL4(pml4) & 1) ) { + Log_Debug("MMVirt", "PML4E %i NP", pml4); + return 0; + } + if( !(PAGEDIRPTR(pdp) & 1) ) { + Log_Debug("MMVirt", "PDPE %i NP", pdp); + return 0; + } + if( !(PAGEDIR(dir) & 1) ) { + Log_Debug("MMVirt", "PDE %i NP", dir); + return 0; + } + if( !(PAGETABLE(tab) & 1) ) { + Log_Debug("MMVirt", "PTE %i NP", tab); + return 0; + } bIsUser = !!(PAGETABLE(tab) & PF_USER); while( Size >= PAGE_SIZE ) { + tab ++; + Size -= PAGE_SIZE; + if( (tab & 511) == 0 ) { dir ++; - if( ((dir >> 9) & 511) == 0 ) + if( (dir & 511) == 0 ) { pdp ++; - if( ((pdp >> 18) & 511) == 0 ) + if( (pdp & 511) == 0 ) { pml4 ++; - if( !(PAGEMAPLVL4(pml4) & 1) ) return 0; + if( !(PAGEMAPLVL4(pml4) & 1) ) { + Log_Debug("MMVirt", "IsValidBuffer - PML4E %x NP, Size=%x", pml4, Size); + return 0; + } + } + if( !(PAGEDIRPTR(pdp) & 1) ) { + Log_Debug("MMVirt", "IsValidBuffer - PDPE %x NP", pdp); + return 0; } - if( !(PAGEDIRPTR(pdp) & 1) ) return 0; } - if( !(PAGEDIR(dir) & 1) ) return 0; + if( !(PAGEDIR(dir) & 1) ) { + Log_Debug("MMVirt", "IsValidBuffer - PDE %x NP", dir); + return 0; + } } - if( !(PAGETABLE(tab) & 1) ) return 0; - if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) return 0; - - tab ++; - Size -= PAGE_SIZE; + if( !(PAGETABLE(tab) & 1) ) { + Log_Debug("MMVirt", "IsValidBuffer - PTE %x NP", tab); + return 0; + } + if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) { + Log_Debug("MMVirt", "IsValidBuffer - PTE %x Not user", tab); + return 0; + } } return 1; } @@ -894,7 +924,7 @@ void MM_FreeTemp(void *Ptr) // --- Address Space Clone -- -tPAddr MM_Clone(void) +tPAddr MM_Clone(int bNoUserCopy) { tPAddr ret; int i; @@ -910,7 +940,7 @@ tPAddr MM_Clone(void) INVLPG_ALL(); // #3 Set Copy-On-Write to all user pages - if( Threads_GetPID() != 0 ) + if( Threads_GetPID() != 0 && !bNoUserCopy ) { for( i = 0; i < 256; i ++) { diff --git a/KernelLand/Kernel/arch/x86_64/proc.asm b/KernelLand/Kernel/arch/x86_64/proc.asm index f44d65b0..f3b3a28a 100644 --- a/KernelLand/Kernel/arch/x86_64/proc.asm +++ b/KernelLand/Kernel/arch/x86_64/proc.asm @@ -39,6 +39,8 @@ Proc_CloneInt: PUSH_GPR ; Save RSP mov [rdi], rsp + ; Call MM_Clone (with bNoUserCopy flag) + mov rdi, rdx call MM_Clone ; Save CR3 mov rsi, [rsp+0x30] ; Saved version of RSI diff --git a/KernelLand/Kernel/arch/x86_64/proc.c b/KernelLand/Kernel/arch/x86_64/proc.c index 884babb3..46e2b21c 100644 --- a/KernelLand/Kernel/arch/x86_64/proc.c +++ b/KernelLand/Kernel/arch/x86_64/proc.c @@ -37,7 +37,7 @@ extern void APStartup(void); // 16-bit AP startup code extern Uint GetRIP(void); // start.asm extern Uint SaveState(Uint *RSP, Uint *Regs); -extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3); +extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3, int bCopyUserVM); extern void NewTaskHeader(void); // Actually takes cdecl args extern void Proc_InitialiseSSE(void); extern void Proc_SaveSSE(Uint DestPtr); @@ -75,6 +75,7 @@ void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NO //void Proc_DumpThreadCPUState(tThread *Thread); //void Proc_Reschedule(void); void Proc_Scheduler(int CPU, Uint RSP, Uint RIP); +Uint Proc_int_SetIRQIP(Uint RIP); // === GLOBALS === //!\brief Used by desctab.asm in SyscallStub @@ -507,7 +508,7 @@ tTID Proc_Clone(Uint Flags) if(!newThread) return -1; // Save core machine state - rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3); + rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER)); if(rip == 0) return 0; // Child newThread->KernelStack = cur->KernelStack; newThread->SavedState.RIP = rip; @@ -725,7 +726,14 @@ void Proc_CallFaultHandler(tThread *Thread) void Proc_DumpThreadCPUState(tThread *Thread) { - Log(" At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP); + if( Thread->CurCPU == GetCPUNum() ) { + // TODO: Backtrace to IRQ + Log(" IRQ %016llx", Thread->SavedState.UserRIP); + } + else { + Log(" At %016llx, SP=%016llx", Thread->SavedState.RIP, Thread->SavedState.RSP); + Log(" User %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP); + } } void Proc_Reschedule(void) @@ -825,5 +833,14 @@ void Proc_Scheduler(int CPU, Uint RSP, Uint RIP) #endif } +Uint Proc_int_SetIRQIP(Uint RIP) +{ + int cpu = GetCPUNum(); + tThread *thread = gaCPUs[cpu].Current; + Uint rv = thread->SavedState.UserRIP; + thread->SavedState.UserRIP = RIP; + return rv; +} + // === EXPORTS === EXPORT(Proc_SpawnWorker); diff --git a/KernelLand/Kernel/libc.c b/KernelLand/Kernel/libc.c index 1b6f3716..c6df2cd6 100644 --- a/KernelLand/Kernel/libc.c +++ b/KernelLand/Kernel/libc.c @@ -226,7 +226,9 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) if(c == 'p') { Uint ptr = va_arg(args, Uint); PUTCH('*'); PUTCH('0'); PUTCH('x'); - for( len = BITS/4; len --; ) + for( len = BITS/4; len -- && ((ptr>>(len*4))&15) == 0; ) + ; + for( len ++; len --; ) PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] ); continue ; } @@ -738,7 +740,8 @@ void *memmove(void *__dest, const void *__src, size_t len) } -// NOTE: Strictly not libc, but lib.c is used by userland code too +// NOTE: Strictly not libc, but lib.c is used by userland code too and hence these two +// can't be in it. /** * \name Memory Validation * \{ diff --git a/KernelLand/Kernel/syscalls.c b/KernelLand/Kernel/syscalls.c index 5a1d5967..82389bbb 100644 --- a/KernelLand/Kernel/syscalls.c +++ b/KernelLand/Kernel/syscalls.c @@ -13,13 +13,13 @@ #include #define CHECK_NUM_NULLOK(v,size) \ - if((v)&&!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;} + if((v)&&!Syscall_Valid((size),(v))){LOG("CHECK_NUM_NULLOK: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;} #define CHECK_STR_NULLOK(v) \ - if((v)&&!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;} + if((v)&&!Syscall_ValidString((v))){LOG("CHECK_STR_NULLOK: %p FAIL",v);ret=-1;err=-EINVAL;break;} #define CHECK_NUM_NONULL(v,size) \ - if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;} + if(!(v)||!Syscall_Valid((size),(v))){LOG("CHECK_NUM_NONULL: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;} #define CHECK_STR_NONULL(v) \ - if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;} + if(!(v)||!Syscall_ValidString((v))){LOG("CHECK_STR_NONULL: %p FAIL",v);ret=-1;err=-EINVAL;break;} #define CHECK_STR_ARRAY(arr) do {\ int i;\ char **tmp = (char**)arr; \ @@ -400,7 +400,10 @@ int Syscall_ValidString(const char *Addr) */ int Syscall_Valid(int Size, const void *Addr) { - if(!MM_IsUser( (tVAddr)Addr )) return 0; + if(!MM_IsUser( (tVAddr)Addr )) { + Log_Debug("Syscalls", "Syscall_Valid - %p not user", Addr); + return 0; + } return CheckMem( Addr, Size ); } diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 17cccca1..a21db4af 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -1079,7 +1079,7 @@ void Threads_int_DumpThread(tThread *thread) default: break; } Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum); - Log(" KStack 0x%x", thread->KernelStack); + Log(" KStack %p", thread->KernelStack); if( thread->bInstrTrace ) Log(" Tracing Enabled"); Proc_DumpThreadCPUState(thread); diff --git a/KernelLand/Modules/Display/BochsGA/bochsvbe.c b/KernelLand/Modules/Display/BochsGA/bochsvbe.c index 70f0c915..84473df7 100644 --- a/KernelLand/Modules/Display/BochsGA/bochsvbe.c +++ b/KernelLand/Modules/Display/BochsGA/bochsvbe.c @@ -47,8 +47,6 @@ enum { VBE_DISPI_INDEX_Y_OFFSET }; -extern void MM_DumpTables(tVAddr Start, tVAddr End); - // === PROTOTYPES === // Driver int BGA_Install(char **Arguments); -- 2.20.1