X-Git-Url: http://git.buserror.net/cgi-bin/gitweb.cgi?p=polintos%2Fscott%2Fpriv.git;a=blobdiff_plain;f=kernel%2Farch%2Fx86%2Fmisc.cc;h=664549addff6ec8a72c2f44cd93f67a7d413d2e6;hp=bb01a1622f2b0cabcdfa4ed0f5c5aaed87baea5c;hb=1ac390fe1e18444008857b056c947710be9621a8;hpb=7da27a216a7f4bb3331fe315cdbec69bfcf2c762 diff --git a/kernel/arch/x86/misc.cc b/kernel/arch/x86/misc.cc index bb01a16..664549a 100644 --- a/kernel/arch/x86/misc.cc +++ b/kernel/arch/x86/misc.cc @@ -2,31 +2,15 @@ // // This software is copyright (c) 2006 Scott Wood . // -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal with -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors or contributors be held liable for any damages +// arising from the use of this software. // -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimers. -// -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimers in the -// documentation and/or other materials provided with the distribution. -// -// * The names of the Software's authors and/or contributors -// may not be used to endorse or promote products derived from -// this Software without specific prior written permission. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE -// SOFTWARE. +// Permission is hereby granted to everyone, free of charge, to use, copy, +// modify, prepare derivative works of, publish, distribute, perform, +// sublicense, and/or sell copies of the Software, provided that the above +// copyright notice and disclaimer of warranty be included in all copies or +// substantial portions of this software. #include #include @@ -35,12 +19,21 @@ #include #include #include +#include +#include #include #include +#include extern u32 x86_init_ptbl_l2[1024]; +struct X86ExTable { + ulong faultaddr, handler; +}; + +extern X86ExTable extable_start, extable_end; + struct X86InitStack { u8 stack[4096 - ::Threads::thread_size]; ::Threads::Thread thread; @@ -50,35 +43,43 @@ namespace Arch { namespace Priv { void set_idt(); - void show_regs(u32 *stack) { + void show_regs(Regs *regs) + { + u32 esp = regs->cs & 3 ? regs->user_esp : + (u32)regs + (u32)sizeof(regs); + printf("eax: 0x%08x ecx: 0x%08x edx: 0x%08x ebx: 0x%08x\n" "esp: 0x%08x ebp: 0x%08x esi: 0x%08x edi: 0x%08x\n" - "eflags: 0x%08x\n", - stack[0], - stack[1], - stack[2], - stack[3], - stack[9] & 3 ? stack[11] : (u32)stack + 11 * 4, - stack[5], - stack[6], - stack[7], - stack[10]); - + "eflags: 0x%08x ds: %04x es: %04x ss: %04x\n", + regs->eax, regs->ecx, regs->edx, regs->ebx, esp, + regs->ebp, regs->esi, regs->edi, regs->eflags, + regs->ds, regs->es, regs->cs & 3 ? regs->user_ss : regs->ds); + printf("Stack trace: "); - u32 *frame = (u32 *)stack[5]; + u32 *frame = (u32 *)regs->ebp; for (int i = 2; i < 32; i++) { - u32 stackptr = frame[1]; - frame = (u32 *)frame[0]; - if ((u32)frame < 0x80000000UL) break; + u32 stackptr = frame[1]; + frame = (u32 *)frame[0]; + if (!(i % 7)) printf("\n"); printf("0x%08x ", stackptr); } + + printf("\nStack dump: "); + + for (int i = 2; i < 32; i++) { + if (!(i % 7)) + printf("\n"); + + printf("0x%08x ", ((u32 *)esp)[i-2]); + } + } struct TimerInt : public IRQ::Interrupt { @@ -90,6 +91,22 @@ namespace Arch { }; TimerInt timer_int; + + bool check_extable(Regs *regs, int cause) + { + X86ExTable *ext; + assert((regs->cs & 3) == 0); + + for (ext = &extable_start; ext < &extable_end; ext++) { + if (ext->faultaddr == regs->eip) { + regs->eip = ext->handler; + regs->edx = cause; + return true; + } + } + + return false; + } } using IRQ::i8259; @@ -110,8 +127,8 @@ namespace Arch { Priv::tss.ss0 = 8; asm volatile("ltr %w0" : : "r" (0x18) : "memory"); - init_thread->addr_space = new Mem::AddrSpace(x86_init_ptbl_l2); - init_thread->active_addr_space = init_thread->addr_space; + init_thread->aspace = new Mem::ProcAddrSpace(x86_init_ptbl_l2); + init_thread->active_aspace = init_thread->aspace; } void timer_init() @@ -119,53 +136,43 @@ namespace Arch { IRQ::InterruptSlot *timer = i8259.get_slot(0); i8259.request_int(timer, &Priv::timer_int); } - - void ArchThread::init(void *entry, void *arg) - { - void **stack = reinterpret_cast(this); - - *--stack = arg; - *--stack = entry; - - esp = stack; - ebp = 0; - jump_to_init = 1; - } } using Arch::Priv::show_regs; +using Arch::Priv::Regs; -extern "C" void x86_do_diverr(u32 *stack) +extern "C" void x86_do_diverr(Regs *regs) { - printf("Division error at 0x%04x:0x%08x\n", stack[9], stack[8]); - show_regs(stack); + printf("Division error at 0x%04x:0x%08x\n", regs->cs, regs->eip); + show_regs(regs); for(;;); } -extern "C" void x86_do_debug(u32 *stack) +extern "C" void x86_do_debug(Regs *regs) { - printf("Debug exception at 0x%04x:0x%08x\n", stack[9], stack[8]); - show_regs(stack); + printf("Debug exception at 0x%04x:0x%08x\n", regs->cs, regs->eip); + show_regs(regs); for(;;); } -extern "C" void x86_do_breakpoint(u32 *stack) +extern "C" void x86_do_breakpoint(Regs *regs) { - printf("Breakpoint at 0x%04x:0x%08x\n", stack[9], stack[8]); - show_regs(stack); + printf("Breakpoint at 0x%04x:0x%08x\n", regs->cs, regs->eip); + show_regs(regs); for(;;); } -extern "C" void x86_do_invalid_insn(u32 *stack) +extern "C" void x86_do_invalid_insn(Regs *regs) { - printf("Invalid instruction at 0x%04x:0x%08x\n", stack[9], stack[8]); - show_regs(stack); + printf("Invalid instruction at 0x%04x:0x%08x\n", regs->cs, regs->eip); + show_regs(regs); for(;;); } -extern "C" void x86_do_page_fault(u32 *stack, u32 fault_addr, u32 error_code) +extern "C" void x86_do_page_fault(Regs *regs, u32 fault_addr, u32 error_code) { Mem::AddrSpace *as; + int cause; if (in_fault) for(;;); @@ -182,11 +189,11 @@ extern "C" void x86_do_page_fault(u32 *stack, u32 fault_addr, u32 error_code) // accomplish much other than decreasing the odds that the fault message // gets out. - if (!(stack[10] & 0x200)) + if (!(regs->eflags & 0x200)) goto bad_fault; // Don't allow fault-ins using a borrowed addr-space. - as = curthread->addr_space; + as = curthread->aspace; if (!as || curthread == Arch::init_thread) goto bad_fault; @@ -194,8 +201,14 @@ extern "C" void x86_do_page_fault(u32 *stack, u32 fault_addr, u32 error_code) ll_ints_on(); // FIXME: no-exec - if (as->handle_fault(fault_addr, error_code & 2, - false /* error_code & 16 */, error_code & 4)) + cause = as->handle_fault(fault_addr, error_code & 2, + false /* error_code & 16 */, + error_code & 4); + + if (cause < 0) + return; + + if (!(error_code & 4) && check_extable(regs, cause)) return; // FIXME: throw exception to user @@ -205,14 +218,14 @@ bad_fault: in_fault++; printf("Page fault at 0x%04x:0x%08x for 0x%08x, error code: 0x%04x\n", - stack[9], stack[8], fault_addr, error_code); + regs->cs, regs->eip, fault_addr, error_code); - show_regs(stack); + show_regs(regs); for(;;); } -extern "C" void x86_do_gpf(u32 *stack, u32 error_code) +extern "C" void x86_do_gpf(Regs *regs, u32 error_code) { if (in_fault) for(;;); @@ -220,9 +233,9 @@ extern "C" void x86_do_gpf(u32 *stack, u32 error_code) in_fault++; printf("General protection fault at 0x%04x:0x%08x, error code: 0x%04x\n", - stack[9], stack[8], error_code); + regs->cs, regs->eip, error_code); - show_regs(stack); + show_regs(regs); for(;;); } @@ -231,3 +244,57 @@ extern "C" void x86_do_irq(int irq) { IRQ::i8259.handle_irq(irq - 0x20); } + +namespace Arch { +namespace Priv { + struct OrbRegs { + u32 ds, es; + + union { + System::RunTime::ParamInfoBlock *pib; + ulong exptr; + }; + + union { + ulong caller; + ulong exlen; + }; + + ulong eip, cs, eflags, user_esp, user_ss; + }; +}} + +extern "C" void x86_invoke_method(Arch::Priv::OrbRegs *regs) +{ + assert(regs->cs & 3); + printf("x86_invoke_method %p\n", regs->pib); + + try { + ORB::invoke_method(regs->pib, regs->user_esp); + } + + catch (SystemException &se) { + // Copy exception to user + // If an exception is thrown during dispatch, it must be + // with the caller's address space, and user_esp must be + // the caller's. + + printf("sys exception\n"); + + typedef System::Exceptions::NativeCodeExceptionOriginInfo OriginInfo; + OriginInfo *oi = OriginInfo::downcast(se.origin); + + if (oi) + printf("PC %llx\n", oi->pc); + } + + catch (...) { + printf("other exception\n"); + } +} + +extern "C" void x86_return_from_method(Arch::Priv::OrbRegs *regs) +{ + assert(regs->cs & 3); + regs->user_esp = ORB::return_from_method(regs->exptr, regs->exlen); +}