1 // arch/x64/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 condition:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
23 #include <kern/types.h>
24 #include <kern/libc.h>
25 #include <kern/arch.h>
26 #include <kern/i8259.h>
27 #include <kern/time.h>
28 #include <kern/thread.h>
31 #include <arch/addrs.h>
32 #include <arch/multiboot.h>
34 extern u64 x64_init_ptbl_l4[512];
37 u8 stack[4096 - ::Threads::thread_size];
38 ::Threads::Thread thread;
39 } __attribute__((aligned(4096))) x64_init_stack;
45 void show_regs(u64 *stack) {
46 for (int i = 0; i < 16; i += 4)
47 printf("r%02d 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
48 i, stack[i], stack[i + 1], stack[i + 2], stack[i + 3]);
50 printf("orig rsp: 0x%016llx rflags: 0x%016llx\n",
51 stack[19], stack[18]);
53 printf("Thread %p (%s)\n", curthread, curthread->name);
55 printf("Stack trace: ");
56 u64 *frame = (u64 *)stack[5];
58 for (int i = 1; i < 32; i++) {
59 u64 stackptr = frame[1];
60 frame = (u64 *)frame[0];
62 if ((u64)frame < 0xffff800000000000)
68 printf("0x%016llx ", stackptr);
72 struct TimerInt : public IRQ::Interrupt {
75 Time::monotonic_timers->run();
84 ::Threads::Thread *init_thread;
88 init_thread = &x64_init_stack.thread;
89 Priv::early_adjust_mappings();
91 Priv::MultiBoot::process_info();
94 u64 tss_addr = reinterpret_cast<u64>(&Priv::tss) + 4;
95 x64_gdt[4].base_low = tss_addr & 0xffff;
96 x64_gdt[4].base_mid = (tss_addr & 0xff0000) >> 16;
97 x64_gdt[4].base_high = (tss_addr & 0xff000000) >> 24;
99 asm volatile("ltr %w0" : : "r" (0x20) : "memory");
100 init_thread->addr_space = new Mem::AddrSpace(x64_init_ptbl_l4);
101 init_thread->active_addr_space = init_thread->addr_space;
106 IRQ::InterruptSlot *timer = i8259.get_slot(0);
107 i8259.request_int(timer, &Priv::timer_int);
110 void ArchThread::init(void *entry, void *arg)
112 void **stack = reinterpret_cast<void **>(this);
123 using Arch::Priv::show_regs;
125 extern "C" void x64_do_diverr(u64 *stack)
127 printf("Division error at 0x%04llx:0x%016llx\n", stack[17], stack[16]);
132 extern "C" void x64_do_invalid_insn(u64 *stack)
134 printf("Invalid instruction at 0x%04llx:0x%016llx\n", stack[17], stack[16]);
139 extern "C" void x64_do_page_fault(u64 *stack, u64 fault_addr, u32 error_code)
146 // A reserved bit was set in the PTE; this is always a bug.
150 // Don't try to fix up a page fault if interrupts were disabled. It is an
151 // error to access non-locked pages with interrupts disabled. Trying to
152 // fix it up in the case of an access that would be legitimate if interrupts
153 // were enabled would simply mask the loss of atomicity, and trying to grab
154 // locks to look up the address if it is a completely bad reference won't
155 // accomplish much other than decreasing the odds that the fault message
158 if (!(stack[18] & 0x200))
161 // Don't allow fault-ins using a borrowed addr-space.
162 as = curthread->addr_space;
164 if (!as || curthread == Arch::init_thread)
170 if (as->handle_fault(fault_addr, error_code & 2,
171 false /* error_code & 16 */, error_code & 4))
174 // FIXME: throw exception to user
180 printf("Page fault at 0x%04llx:0x%016llx for 0x%016llx\n",
181 stack[17], stack[16], fault_addr);
182 printf("Error code: 0x%04x\n", error_code);
189 extern "C" void x64_do_gpf(u64 *stack, u32 error_code)
196 printf("General protection fault at 0x%04llx:0x%016llx, "
197 "Error code: 0x%04x\n",
198 stack[17], stack[16], error_code);
205 extern "C" void x64_do_irq(int irq)
207 IRQ::i8259.handle_irq(irq - 0x20);