From 0601614ebbcc48b961a2f0613281e6e629af29b1 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Tue, 17 Apr 2007 20:30:32 -0500 Subject: [PATCH] Regs struct, int98/99 --- kernel/arch/x86/descriptors.cc | 6 +- kernel/arch/x86/entry.S | 106 ++++++++++++++++++++++++++++----- kernel/arch/x86/misc.cc | 90 ++++++++++++++++++---------- kernel/include/arch-x86/regs.h | 21 +++++++ kernel/include/kern/orb.h | 3 + kernel/orb/invoke.cc | 36 ++++++----- 6 files changed, 199 insertions(+), 63 deletions(-) create mode 100644 kernel/include/arch-x86/regs.h diff --git a/kernel/arch/x86/descriptors.cc b/kernel/arch/x86/descriptors.cc index 8619e1c..e281895 100644 --- a/kernel/arch/x86/descriptors.cc +++ b/kernel/arch/x86/descriptors.cc @@ -152,7 +152,8 @@ static void set_int_gate(int num, void *addrptr, bool ints_off = false, } extern int x86_diverr, x86_debug, x86_breakpoint; -extern int x86_gpf, x86_page_fault, x86_invalid_insn, x86_int99_entry; +extern int x86_gpf, x86_page_fault, x86_invalid_insn; +extern int x86_int98_entry, x86_int99_entry; extern void *x86_irqs[256]; namespace Arch { @@ -170,7 +171,8 @@ namespace Priv { set_int_gate(6, &x86_invalid_insn); set_int_gate(13, &x86_gpf); set_int_gate(14, &x86_page_fault, true); - set_int_gate(0x99, &x86_int99_entry); + set_int_gate(0x98, &x86_int98_entry, false, true); + set_int_gate(0x99, &x86_int99_entry, false, true); for (int i = 0x20; i < 0x30; i++) set_int_gate(i, x86_irqs[i], true); diff --git a/kernel/arch/x86/entry.S b/kernel/arch/x86/entry.S index f8cf684..3483893 100644 --- a/kernel/arch/x86/entry.S +++ b/kernel/arch/x86/entry.S @@ -139,10 +139,25 @@ no_pentium_str: no_multiboot_str: .string "Unrecognized bootloader; a multiboot-compliant loader is required." + + .macro enterkernel, reg + pushl %es + pushl %ds + movl $8, \reg + cld + movl \reg, %ds + movl \reg, %es + .endm + + .macro exitkernel + popl %ds + popl %es + .endm .macro pushvolatilesnoeax pushl %ecx pushl %edx + enterkernel %ecx .endm .macro pushvolatiles @@ -151,6 +166,7 @@ no_multiboot_str: .endm .macro popvolatiles + exitkernel popl %edx popl %ecx popl %eax @@ -164,11 +180,11 @@ no_multiboot_str: .macro pushall pushl %esi pushl %ebp - pushl %esp pushl %ebx pushl %edx pushl %ecx pushl %eax + enterkernel %esi .endm .macro pushallnoerr @@ -177,11 +193,11 @@ no_multiboot_str: .endm .macro popall + exitkernel popl %eax popl %ecx popl %edx popl %ebx - addl $4, %esp popl %ebp popl %esi popl %edi @@ -261,17 +277,44 @@ x86_page_fault: popall iret + .global x86_int98_entry +x86_int98_entry: + pushl $0 + pushl %eax + enterkernel %ecx + + pushl %esp + call x86_invoke_method + addl $4, %esp + + exitkernel + popl %eax + xorl %ecx, %ecx + popl %edx + xorl %ebx, %ebx + xorl %ebp, %ebp + xorl %esi, %esi + xorl %edi, %edi + iret + .global x86_int99_entry x86_int99_entry: - pushl %edx - pushl 4(%esp) - pushl %edx pushl %ecx pushl %eax - call invoke_method - addl $16, %esp - xorl %ecx, %ecx - popl %edx + enterkernel %edx + + pushl %esp + call x86_return_from_method + addl $4, %esp + + exitkernel + popl %eax + popl %ecx + xorl %edx, %edx + xorl %ebx, %ebx + xorl %ebp, %ebp + xorl %esi, %esi + xorl %edi, %edi iret .global x86_irq @@ -342,16 +385,47 @@ x86_new_thread: .section ".roshared","x" - // The syscall pointer must be the first thing in roshared - // (at vaddr 0x7fff0000), so that user code can make method - // invocations to find out where other stuff is. + // The vsyscall table must be the first thing in roshared (at + // vaddr 0x7fff0000). + +#define PTR(x) (x - x86_syscall_ptr + 0x7fff0000) .global x86_syscall_ptr x86_syscall_ptr: - .long x86_shared_int99 - x86_syscall_ptr + 0x7fff0000 - - .global x86_shared_int99 + .long PTR(x86_shared_int98) + + .global x86_sysret_ptr +x86_sysret_ptr: + .long PTR(x86_shared_int99) + +x86_shared_int98: + // FIXME: This must be unpreemptible by traps + pushl %gs + pushl %fs + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + int $0x98 + popl %ebx + popl %esi + popl %edi + popl %ebp + popl %fs + popl %gs + ret + x86_shared_int99: int $0x99 - // FIXME: search for exception handler ret + + .section ".rwshared","" + + // Userspace must set this to an appropriate entry point + // prior to registering objects with the kernel. It should + // not be modified while an object is registered (the kernel + // won't mind, but there's no mechanism to wait until no more + // upcalls to the old entry point are in progress). + .global x86_upcall_entry +x86_upcall_entry: + .long 0 diff --git a/kernel/arch/x86/misc.cc b/kernel/arch/x86/misc.cc index 48bf24c..a1b6e18 100644 --- a/kernel/arch/x86/misc.cc +++ b/kernel/arch/x86/misc.cc @@ -20,9 +20,11 @@ #include #include #include +#include #include #include +#include extern u32 x86_init_ptbl_l2[1024]; @@ -35,22 +37,18 @@ namespace Arch { namespace Priv { void set_idt(); - void show_regs(u32 *stack) { + void show_regs(Regs *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, + regs->cs & 3 ? regs->user_esp : (u32)regs + (u32)sizeof(regs), + 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]; @@ -119,36 +117,37 @@ namespace Arch { } 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; @@ -167,7 +166,7 @@ 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. @@ -190,14 +189,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(;;); @@ -205,9 +204,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(;;); } @@ -216,3 +215,32 @@ extern "C" void x86_do_irq(int irq) { IRQ::i8259.handle_irq(irq - 0x20); } + +namespace Arch { +namespace Priv { + struct OrbRegs { + 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); + ORB::invoke_method(regs->pib, regs->user_esp); +} + +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); +} diff --git a/kernel/include/arch-x86/regs.h b/kernel/include/arch-x86/regs.h new file mode 100644 index 0000000..90c2177 --- /dev/null +++ b/kernel/include/arch-x86/regs.h @@ -0,0 +1,21 @@ +#ifndef _ARCH_REGS_H +#define _ARCH_REGS_H + +namespace Arch { +namespace Priv { + struct Regs { + u32 ds, es; + + union { + struct { + u32 eax, ecx, edx, ebx, ebp, esi, edi; + }; + + u32 gpr[8]; + }; + + u32 eip, cs, eflags, user_esp, user_ss; + }; +}}; + +#endif diff --git a/kernel/include/kern/orb.h b/kernel/include/kern/orb.h index f90d051..404e9c0 100644 --- a/kernel/include/kern/orb.h +++ b/kernel/include/kern/orb.h @@ -101,6 +101,9 @@ namespace ORB { ObjectHdr *get_local_hdr(Object *obj); Object *newobj(Mem::ProcAddrSpace *aspace, uintptr_t entry); }; + + void invoke_method(System::RunTime::ParamInfoBlock *pib, uintptr_t &stack); + uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen); } #endif diff --git a/kernel/orb/invoke.cc b/kernel/orb/invoke.cc index 102ea95..ffcd837 100644 --- a/kernel/orb/invoke.cc +++ b/kernel/orb/invoke.cc @@ -77,20 +77,28 @@ namespace ORB { return obj; } -} -extern "C" void invoke_method(ParamInfoBlock *user_pib, ulong ret_pc) -{ - ParamInfoBlock pib = Arch::copyin(user_pib); - CallFrame *frame = new_frame(curthread); - -// frame->object = objid; - frame->caller_user_pib = user_pib; - frame->ret_pc = ret_pc; - - printf("invoke_method: frame %p pib %p ret %lx\n", - frame, frame->caller_user_pib, - frame->ret_pc); - + void invoke_method(ParamInfoBlock *user_pib, uintptr_t &stack) + { + ParamInfoBlock pib = Arch::copyin(user_pib); + CallFrame *frame = new_frame(curthread); + +// if (pib->objlist_len == 0) + + +// frame->object = objid; + frame->caller_user_pib = user_pib; +// frame->ret_pc = ret_pc; + + printf("invoke_method: frame %p pib %p ret %lx\n", + frame, frame->caller_user_pib, + frame->ret_pc); + + + } + uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen) + { + return 0; + } } -- 2.39.2