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;fp=kernel%2Farch%2Fx86%2Fmisc.cc;h=664549addff6ec8a72c2f44cd93f67a7d413d2e6;hp=a1b6e18b2dc2fb5d2171a05ac8fb9eac1da7bc6f;hb=1ac390fe1e18444008857b056c947710be9621a8;hpb=6e64b28821757af60447c790ae52a91831a9d4f0 diff --git a/kernel/arch/x86/misc.cc b/kernel/arch/x86/misc.cc index a1b6e18..664549a 100644 --- a/kernel/arch/x86/misc.cc +++ b/kernel/arch/x86/misc.cc @@ -28,6 +28,12 @@ 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; @@ -39,29 +45,41 @@ namespace Arch { 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 ds: %04x es: %04x ss: %04x\n", - regs->eax, regs->ecx, regs->edx, regs->ebx, - regs->cs & 3 ? regs->user_esp : (u32)regs + (u32)sizeof(regs), + 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 *)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 { @@ -73,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; @@ -93,8 +127,8 @@ namespace Arch { Priv::tss.ss0 = 8; asm volatile("ltr %w0" : : "r" (0x18) : "memory"); - init_thread->addr_space = new Mem::ProcAddrSpace(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() @@ -102,18 +136,6 @@ 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; @@ -150,6 +172,7 @@ extern "C" void x86_do_invalid_insn(Regs *regs) extern "C" void x86_do_page_fault(Regs *regs, u32 fault_addr, u32 error_code) { Mem::AddrSpace *as; + int cause; if (in_fault) for(;;); @@ -170,7 +193,7 @@ extern "C" void x86_do_page_fault(Regs *regs, u32 fault_addr, u32 error_code) 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; @@ -178,8 +201,14 @@ extern "C" void x86_do_page_fault(Regs *regs, 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 @@ -219,6 +248,8 @@ extern "C" void x86_do_irq(int irq) namespace Arch { namespace Priv { struct OrbRegs { + u32 ds, es; + union { System::RunTime::ParamInfoBlock *pib; ulong exptr; @@ -236,7 +267,30 @@ namespace Priv { extern "C" void x86_invoke_method(Arch::Priv::OrbRegs *regs) { assert(regs->cs & 3); - ORB::invoke_method(regs->pib, regs->user_esp); + 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)