}
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 {
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);
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
.endm
.macro popvolatiles
+ exitkernel
popl %edx
popl %ecx
popl %eax
.macro pushall
pushl %esi
pushl %ebp
- pushl %esp
pushl %ebx
pushl %edx
pushl %ecx
pushl %eax
+ enterkernel %esi
.endm
.macro pushallnoerr
.endm
.macro popall
+ exitkernel
popl %eax
popl %ecx
popl %edx
popl %ebx
- addl $4, %esp
popl %ebp
popl %esi
popl %edi
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
.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
#include <kern/thread.h>
#include <kern/mem.h>
#include <kern/process.h>
+#include <kern/orb.h>
#include <arch/addrs.h>
#include <arch/multiboot.h>
+#include <arch/regs.h>
extern u32 x86_init_ptbl_l2[1024];
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];
}
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;
// 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.
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(;;);
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(;;);
}
{
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);
+}
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;
+ }
}