1 // arch/x86/misc.cc -- Misc. arch-specific stuff
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
15 #include <kern/types.h>
16 #include <kern/libc.h>
17 #include <kern/arch.h>
18 #include <kern/i8259.h>
19 #include <kern/time.h>
20 #include <kern/thread.h>
22 #include <kern/process.h>
25 #include <arch/addrs.h>
26 #include <arch/multiboot.h>
27 #include <arch/regs.h>
29 extern u32 x86_init_ptbl_l2[1024];
32 ulong faultaddr, handler;
35 extern X86ExTable extable_start, extable_end;
38 u8 stack[4096 - ::Threads::thread_size];
39 ::Threads::Thread thread;
40 } __attribute__((aligned(4096))) x86_init_stack;
46 void show_regs(Regs *regs)
48 u32 esp = regs->cs & 3 ? regs->user_esp :
49 (u32)regs + (u32)sizeof(regs);
51 printf("eax: 0x%08x ecx: 0x%08x edx: 0x%08x ebx: 0x%08x\n"
52 "esp: 0x%08x ebp: 0x%08x esi: 0x%08x edi: 0x%08x\n"
53 "eflags: 0x%08x ds: %04x es: %04x ss: %04x\n",
54 regs->eax, regs->ecx, regs->edx, regs->ebx, esp,
55 regs->ebp, regs->esi, regs->edi, regs->eflags,
56 regs->ds, regs->es, regs->cs & 3 ? regs->user_ss : regs->ds);
58 printf("Stack trace: ");
59 u32 *frame = (u32 *)regs->ebp;
61 for (int i = 2; i < 32; i++) {
62 if ((u32)frame < 0x80000000UL)
65 u32 stackptr = frame[1];
66 frame = (u32 *)frame[0];
71 printf("0x%08x ", stackptr);
74 printf("\nStack dump: ");
76 for (int i = 2; i < 32; i++) {
80 printf("0x%08x ", ((u32 *)esp)[i-2]);
85 struct TimerInt : public IRQ::Interrupt {
88 Time::monotonic_timers->run();
95 bool check_extable(Regs *regs, int cause)
98 assert((regs->cs & 3) == 0);
100 for (ext = &extable_start; ext < &extable_end; ext++) {
101 if (ext->faultaddr == regs->eip) {
102 regs->eip = ext->handler;
113 ::Threads::Thread *init_thread;
117 init_thread = &x86_init_stack.thread;
118 Priv::early_adjust_mappings();
120 Priv::MultiBoot::process_info();
123 u32 tss_addr = reinterpret_cast<u32>(&Priv::tss);
124 x86_gdt[3].base_low = tss_addr & 0xffff;
125 x86_gdt[3].base_mid = (tss_addr & 0xff0000) >> 16;
126 x86_gdt[3].base_high = (tss_addr & 0xff000000) >> 24;
129 asm volatile("ltr %w0" : : "r" (0x18) : "memory");
130 init_thread->aspace = new Mem::ProcAddrSpace(x86_init_ptbl_l2);
131 init_thread->active_aspace = init_thread->aspace;
136 IRQ::InterruptSlot *timer = i8259.get_slot(0);
137 i8259.request_int(timer, &Priv::timer_int);
141 using Arch::Priv::show_regs;
142 using Arch::Priv::Regs;
144 extern "C" void x86_do_diverr(Regs *regs)
146 printf("Division error at 0x%04x:0x%08x\n", regs->cs, regs->eip);
151 extern "C" void x86_do_debug(Regs *regs)
153 printf("Debug exception at 0x%04x:0x%08x\n", regs->cs, regs->eip);
158 extern "C" void x86_do_breakpoint(Regs *regs)
160 printf("Breakpoint at 0x%04x:0x%08x\n", regs->cs, regs->eip);
165 extern "C" void x86_do_invalid_insn(Regs *regs)
167 printf("Invalid instruction at 0x%04x:0x%08x\n", regs->cs, regs->eip);
172 extern "C" void x86_do_page_fault(Regs *regs, u32 fault_addr, u32 error_code)
180 // A reserved bit was set in the PTE; this is always a bug.
184 // Don't try to fix up a page fault if interrupts were disabled. It is an
185 // error to access non-locked pages with interrupts disabled. Trying to
186 // fix it up in the case of an access that would be legitimate if interrupts
187 // were enabled would simply mask the loss of atomicity, and trying to grab
188 // locks to look up the address if it is a completely bad reference won't
189 // accomplish much other than decreasing the odds that the fault message
192 if (!(regs->eflags & 0x200))
195 // Don't allow fault-ins using a borrowed addr-space.
196 as = curthread->aspace;
198 if (!as || curthread == Arch::init_thread)
204 cause = as->handle_fault(fault_addr, error_code & 2,
205 false /* error_code & 16 */,
211 if (!(error_code & 4) && check_extable(regs, cause))
214 // FIXME: throw exception to user
220 printf("Page fault at 0x%04x:0x%08x for 0x%08x, error code: 0x%04x\n",
221 regs->cs, regs->eip, fault_addr, error_code);
228 extern "C" void x86_do_gpf(Regs *regs, u32 error_code)
235 printf("General protection fault at 0x%04x:0x%08x, error code: 0x%04x\n",
236 regs->cs, regs->eip, error_code);
243 extern "C" void x86_do_irq(int irq)
245 IRQ::i8259.handle_irq(irq - 0x20);
254 System::RunTime::ParamInfoBlock *pib;
265 ulong eip, cs, eflags, user_esp, user_ss;
269 extern "C" void x86_invoke_method(Arch::Priv::OrbRegs *regs)
271 assert(regs->cs & 3);
272 printf("x86_invoke_method %p\n", regs->pib);
275 ORB::invoke_method(regs->pib, regs->user_esp);
278 catch (SystemException &se) {
279 // Copy exception to user
280 // If an exception is thrown during dispatch, it must be
281 // with the caller's address space, and user_esp must be
284 printf("sys exception\n");
286 typedef System::Exceptions::NativeCodeExceptionOriginInfo OriginInfo;
287 OriginInfo *oi = OriginInfo::downcast(se.origin);
290 printf("PC %llx\n", oi->pc);
294 printf("other exception\n");
298 extern "C" void x86_return_from_method(Arch::Priv::OrbRegs *regs)
300 assert(regs->cs & 3);
301 regs->user_esp = ORB::return_from_method(regs->exptr, regs->exlen);
304 extern "C" void x86_new_object(Arch::Priv::OrbRegs *regs)
306 assert(regs->cs & 3);
310 extern "C" void x86_get_iface_hash(Arch::Priv::OrbRegs *regs)
312 assert(regs->cs & 3);