1 // arch/x86/misc.cc -- Misc. arch-specific stuff
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following conditions:
12 // * Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimers.
15 // * Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimers in the
17 // documentation and/or other materials provided with the distribution.
19 // * The names of the Software's authors and/or contributors
20 // may not be used to endorse or promote products derived from
21 // this Software without specific prior written permission.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
31 #include <kern/types.h>
32 #include <kern/libc.h>
33 #include <kern/arch.h>
34 #include <kern/i8259.h>
35 #include <kern/time.h>
36 #include <kern/thread.h>
39 #include <arch/addrs.h>
40 #include <arch/multiboot.h>
42 extern u32 x86_init_ptbl_l2[1024];
45 u8 stack[4096 - ::Threads::thread_size];
46 ::Threads::Thread thread;
47 } __attribute__((aligned(4096))) x86_init_stack;
53 void show_regs(u32 *stack) {
54 printf("eax: 0x%08x ecx: 0x%08x edx: 0x%08x ebx: 0x%08x\n"
55 "esp: 0x%08x ebp: 0x%08x esi: 0x%08x edi: 0x%08x\n"
61 stack[9] & 3 ? stack[11] : (u32)stack + 11 * 4,
67 printf("Stack trace: ");
68 u32 *frame = (u32 *)stack[5];
70 for (int i = 2; i < 32; i++) {
71 u32 stackptr = frame[1];
72 frame = (u32 *)frame[0];
74 if ((u32)frame < 0x80000000UL)
80 printf("0x%08x ", stackptr);
84 struct TimerInt : public IRQ::Interrupt {
87 Time::monotonic_timers->run();
96 ::Threads::Thread *init_thread;
100 init_thread = &x86_init_stack.thread;
101 Priv::early_adjust_mappings();
103 Priv::MultiBoot::process_info();
106 u32 tss_addr = reinterpret_cast<u32>(&Priv::tss);
107 x86_gdt[3].base_low = tss_addr & 0xffff;
108 x86_gdt[3].base_mid = (tss_addr & 0xff0000) >> 16;
109 x86_gdt[3].base_high = (tss_addr & 0xff000000) >> 24;
112 asm volatile("ltr %w0" : : "r" (0x18) : "memory");
113 init_thread->addr_space = new Mem::AddrSpace(x86_init_ptbl_l2);
114 init_thread->active_addr_space = init_thread->addr_space;
119 IRQ::InterruptSlot *timer = i8259.get_slot(0);
120 i8259.request_int(timer, &Priv::timer_int);
123 void ArchThread::init(void *entry, void *arg)
125 void **stack = reinterpret_cast<void **>(this);
136 using Arch::Priv::show_regs;
138 extern "C" void x86_do_diverr(u32 *stack)
140 printf("Division error at 0x%04x:0x%08x\n", stack[9], stack[8]);
145 extern "C" void x86_do_debug(u32 *stack)
147 printf("Debug exception at 0x%04x:0x%08x\n", stack[9], stack[8]);
152 extern "C" void x86_do_breakpoint(u32 *stack)
154 printf("Breakpoint at 0x%04x:0x%08x\n", stack[9], stack[8]);
159 extern "C" void x86_do_invalid_insn(u32 *stack)
161 printf("Invalid instruction at 0x%04x:0x%08x\n", stack[9], stack[8]);
166 extern "C" void x86_do_page_fault(u32 *stack, u32 fault_addr, u32 error_code)
173 // A reserved bit was set in the PTE; this is always a bug.
177 // Don't try to fix up a page fault if interrupts were disabled. It is an
178 // error to access non-locked pages with interrupts disabled. Trying to
179 // fix it up in the case of an access that would be legitimate if interrupts
180 // were enabled would simply mask the loss of atomicity, and trying to grab
181 // locks to look up the address if it is a completely bad reference won't
182 // accomplish much other than decreasing the odds that the fault message
185 if (!(stack[10] & 0x200))
188 // Don't allow fault-ins using a borrowed addr-space.
189 as = curthread->addr_space;
191 if (!as || curthread == Arch::init_thread)
197 if (as->handle_fault(fault_addr, error_code & 2,
198 false /* error_code & 16 */, error_code & 4))
201 // FIXME: throw exception to user
207 printf("Page fault at 0x%04x:0x%08x for 0x%08x, error code: 0x%04x\n",
208 stack[9], stack[8], fault_addr, error_code);
215 extern "C" void x86_do_gpf(u32 *stack, u32 error_code)
222 printf("General protection fault at 0x%04x:0x%08x, error code: 0x%04x\n",
223 stack[9], stack[8], error_code);
230 extern "C" void x86_do_irq(int irq)
232 IRQ::i8259.handle_irq(irq - 0x20);