72d0c64e93bbfbf7cd1c24b37c700fd9fcf6cfc7
[akaros.git] / kern / arch / x86 / trap.c
1 #include <arch/mmu.h>
2 #include <arch/x86.h>
3 #include <arch/arch.h>
4 #include <arch/console.h>
5 #include <arch/apic.h>
6 #include <arch/perfmon.h>
7 #include <ros/common.h>
8 #include <smp.h>
9 #include <assert.h>
10 #include <pmap.h>
11 #include <trap.h>
12 #include <monitor.h>
13 #include <process.h>
14 #include <mm.h>
15 #include <stdio.h>
16 #include <slab.h>
17 #include <syscall.h>
18 #include <kdebug.h>
19 #include <kmalloc.h>
20 #include <ex_table.h>
21 #include <arch/mptables.h>
22 #include <ros/procinfo.h>
23
24 taskstate_t ts;
25
26 /* Interrupt descriptor table.  64 bit needs 16 byte alignment (i think). */
27 gatedesc_t __attribute__((aligned (16))) idt[256] = { { 0 } };
28 pseudodesc_t idt_pd;
29
30 /* interrupt handler table, each element is a linked list of handlers for a
31  * given IRQ.  Modification requires holding the lock (TODO: RCU) */
32 struct irq_handler *irq_handlers[NUM_IRQS];
33 spinlock_t irq_handler_wlock = SPINLOCK_INITIALIZER_IRQSAVE;
34
35 static bool try_handle_exception_fixup(struct hw_trapframe *hw_tf)
36 {
37         if (in_kernel(hw_tf)) {
38                 uintptr_t fixup_ip = get_fixup_ip(hw_tf->tf_rip);
39
40                 if (fixup_ip != 0) {
41                         hw_tf->tf_rip = fixup_ip;
42                         return true;
43                 }
44         }
45
46         return false;
47 }
48
49 const char *x86_trapname(int trapno)
50 {
51         static const char *const excnames[] = {
52                 "Divide error",
53                 "Debug",
54                 "Non-Maskable Interrupt",
55                 "Breakpoint",
56                 "Overflow",
57                 "BOUND Range Exceeded",
58                 "Invalid Opcode",
59                 "Device Not Available",
60                 "Double Fault",
61                 "Coprocessor Segment Overrun",
62                 "Invalid TSS",
63                 "Segment Not Present",
64                 "Stack Fault",
65                 "General Protection",
66                 "Page Fault",
67                 "(unknown trap)",
68                 "x87 FPU Floating-Point Error",
69                 "Alignment Check",
70                 "Machine-Check",
71                 "SIMD Floating-Point Exception"
72         };
73
74         if (trapno < sizeof(excnames)/sizeof(excnames[0]))
75                 return excnames[trapno];
76         if (trapno == T_SYSCALL)
77                 return "System call";
78         return "(unknown trap)";
79 }
80
81 /* Set stacktop for the current core to be the stack the kernel will start on
82  * when trapping/interrupting from userspace.  Don't use this til after
83  * smp_percpu_init().  We can probably get the TSS by reading the task register
84  * and then the GDT.  Still, it's a pain. */
85 void set_stack_top(uintptr_t stacktop)
86 {
87         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
88         /* No need to reload the task register, this takes effect immediately */
89         x86_set_stacktop_tss(pcpui->tss, stacktop);
90         /* Also need to make sure sysenters come in correctly */
91         x86_set_sysenter_stacktop(stacktop);
92 }
93
94 /* Note the check implies we only are on a one page stack (or the first page) */
95 uintptr_t get_stack_top(void)
96 {
97         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
98         uintptr_t stacktop;
99         /* so we can check this in interrupt handlers (before smp_boot()) */
100         /* TODO: These are dangerous - it assumes we're on a one-page stack.  If we
101          * change it to KSTKSIZE, then we assume stacks are KSTKSIZE-aligned */
102         if (!pcpui->tss)
103                 return ROUNDUP(read_sp(), PGSIZE);
104         stacktop = x86_get_stacktop_tss(pcpui->tss);
105         if (stacktop != ROUNDUP(read_sp(), PGSIZE))
106                 panic("Bad stacktop: %p esp one is %p\n", stacktop,
107                       ROUNDUP(read_sp(), PGSIZE));
108         return stacktop;
109 }
110
111 /* Sends a non-maskable interrupt; the handler will print a trapframe. */
112 void send_nmi(uint32_t os_coreid)
113 {
114         /* NMI / IPI for x86 are limited to 8 bits */
115         uint8_t hw_core = (uint8_t)get_hw_coreid(os_coreid);
116         __send_nmi(hw_core);
117 }
118
119 void idt_init(void)
120 {
121         /* This table is made in trapentry$BITS.S by each macro in that file.
122          * It is layed out such that the ith entry is the ith's traphandler's
123          * (uintptr_t) trap addr, then (uint32_t) trap number. */
124         struct trapinfo { uintptr_t trapaddr; uint32_t trapnumber; }
125                __attribute__((packed));
126         extern struct trapinfo trap_tbl[];
127         extern struct trapinfo trap_tbl_end[];
128         int i, trap_tbl_size = trap_tbl_end - trap_tbl;
129         extern void ISR_default(void);
130         extern void ISR_syscall(void);
131
132         /* set all to default, to catch everything */
133         for (i = 0; i < 256; i++)
134                 SETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
135
136         /* set all entries that have real trap handlers
137          * we need to stop short of the last one, since the last is the default
138          * handler with a fake interrupt number (500) that is out of bounds of
139          * the idt[] */
140         for (i = 0; i < trap_tbl_size - 1; i++)
141                 SETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
142         /* Sanity check */
143         assert((uintptr_t)ISR_syscall ==
144                ((uintptr_t)idt[T_SYSCALL].gd_off_63_32 << 32 |
145                 (uintptr_t)idt[T_SYSCALL].gd_off_31_16 << 16 |
146                 (uintptr_t)idt[T_SYSCALL].gd_off_15_0));
147         /* turn on trap-based syscall handling and other user-accessible ints
148          * DPL 3 means this can be triggered by the int instruction */
149         idt[T_SYSCALL].gd_dpl = 3;
150         idt[T_BRKPT].gd_dpl = 3;
151
152         /* Set up our kernel stack when changing rings */
153         /* Note: we want 16 byte aligned kernel stack frames (AMD 2:8.9.3) */
154         x86_set_stacktop_tss(&ts, (uintptr_t)bootstacktop);
155         x86_sysenter_init((uintptr_t)bootstacktop);
156
157 #ifdef CONFIG_KTHREAD_POISON
158         *kstack_bottom_addr((uintptr_t)bootstacktop) = 0xdeadbeef;
159 #endif /* CONFIG_KTHREAD_POISON */
160
161         /* Initialize the TSS field of the gdt.  The size of the TSS desc differs
162          * between 64 and 32 bit, hence the pointer acrobatics */
163         syssegdesc_t *ts_slot = (syssegdesc_t*)&gdt[GD_TSS >> 3];
164         *ts_slot = (syssegdesc_t)SEG_SYS_SMALL(STS_T32A, (uintptr_t)&ts,
165                                                sizeof(taskstate_t), 0);
166
167         /* Init the IDT PD.  Need to do this before ltr for some reason.  (Doing
168          * this between ltr and lidt causes the machine to reboot... */
169         idt_pd.pd_lim = sizeof(idt) - 1;
170         idt_pd.pd_base = (uintptr_t)idt;
171
172         ltr(GD_TSS);
173
174         asm volatile("lidt %0" : : "m"(idt_pd));
175
176         pic_remap();
177         pic_mask_all();
178
179         int ncleft = MAX_NUM_CORES;
180         int num_cores_mpacpi;
181
182         ncleft = mpsinit(ncleft);
183         ncleft = mpacpi(ncleft);
184         num_cores_mpacpi = MAX_NUM_CORES - ncleft;
185         printk("MP and ACPI found %d cores\n", num_cores_mpacpi);
186         if (num_cores != num_cores_mpacpi)
187                 warn("Topology (%d) and MP/ACPI (%d) differ on num_cores!", num_cores,
188                      num_cores_mpacpi);
189
190         apiconline();
191         ioapiconline();
192
193         /* the lapic IRQs need to be unmasked on a per-core basis */
194         register_irq(IdtLAPIC_TIMER, timer_interrupt, NULL,
195                      MKBUS(BusLAPIC, 0, 0, 0));
196         register_irq(IdtLAPIC_ERROR, handle_lapic_error, NULL,
197                      MKBUS(BusLAPIC, 0, 0, 0));
198         register_irq(IdtLAPIC_PCINT, perfmon_interrupt, NULL,
199                      MKBUS(BusLAPIC, 0, 0, 0));
200         register_irq(I_KERNEL_MSG, handle_kmsg_ipi, NULL, MKBUS(BusIPI, 0, 0, 0));
201 }
202
203 static void handle_fperr(struct hw_trapframe *hw_tf)
204 {
205         uint16_t fpcw, fpsw;
206         uint32_t mxcsr;
207         asm volatile ("fnstcw %0" : "=m"(fpcw));
208         asm volatile ("fnstsw %0" : "=m"(fpsw));
209         asm volatile ("stmxcsr %0" : "=m"(mxcsr));
210         print_trapframe(hw_tf);
211         printk("Core %d: FP ERR, CW: 0x%04x, SW: 0x%04x, MXCSR 0x%08x\n", core_id(),
212                fpcw, fpsw, mxcsr);
213         printk("Core %d: The following faults are unmasked:\n", core_id());
214         if (fpsw & ~fpcw & FP_EXCP_IE) {
215                 printk("\tInvalid Operation: ");
216                 if (fpsw & FP_SW_SF) {
217                         if (fpsw & FP_SW_C1)
218                                 printk("Stack overflow\n");
219                         else
220                                 printk("Stack underflow\n");
221                 } else {
222                         printk("invalid arithmetic operand\n");
223                 }
224         }
225         if (fpsw & ~fpcw & FP_EXCP_DE)
226                 printk("\tDenormalized operand\n");
227         if (fpsw & ~fpcw & FP_EXCP_ZE)
228                 printk("\tDivide by zero\n");
229         if (fpsw & ~fpcw & FP_EXCP_OE)
230                 printk("\tNumeric Overflow\n");
231         if (fpsw & ~fpcw & FP_EXCP_UE)
232                 printk("\tNumeric Underflow\n");
233         if (fpsw & ~fpcw & FP_EXCP_PE)
234                 printk("\tInexact result (precision)\n");
235         printk("Killing the process.\n");
236         proc_destroy(current);
237 }
238
239 static bool __handler_user_page_fault(struct hw_trapframe *hw_tf,
240                                       uintptr_t fault_va, int prot)
241 {
242         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
243         int err;
244
245         assert(pcpui->owning_proc == pcpui->cur_proc);
246         enable_irq();
247         err = handle_page_fault(pcpui->owning_proc, fault_va, prot);
248         disable_irq();
249         if (err) {
250                 if (err == -EAGAIN)
251                         hw_tf->tf_err |= PF_VMR_BACKED;
252                 return FALSE;
253         }
254         return TRUE;
255 }
256
257 static bool __handler_kernel_page_fault(struct hw_trapframe *hw_tf,
258                                         uintptr_t fault_va, int prot)
259 {
260         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
261         int err;
262
263         /* In general, if there's no cur_proc, a KPF is a bug. */
264         if (!pcpui->cur_proc) {
265                 /* This only runs from test_uaccess(), where it is expected to fail. */
266                 if (try_handle_exception_fixup(hw_tf))
267                         return TRUE;
268                 print_trapframe(hw_tf);
269                 backtrace_hwtf(hw_tf);
270                 panic("Proc-less Page Fault in the Kernel at %p!", fault_va);
271         }
272         /* TODO - handle kernel page faults.  This is dangerous, since we might be
273          * holding locks in the kernel and could deadlock when we HPF.  For now, I'm
274          * just disabling the lock checker, since it'll flip out when it sees there
275          * is a kernel trap.  Will need to think about this a bit, esp when we
276          * properly handle bad addrs and whatnot. */
277         pcpui->__lock_checking_enabled--;
278         /* It is a bug for the kernel to access user memory while holding locks that
279          * are used by handle_page_fault.  At a minimum, this includes p->vmr_lock
280          * and memory allocation locks.
281          *
282          * In an effort to reduce the number of locks (both now and in the future),
283          * the kernel will not attempt to handle faults on file-back VMRs.  We
284          * probably can turn that on in the future, but I'd rather keep things safe
285          * for now.  (We'll probably need to change this when we stop
286          * MAP_POPULATE | MAP_LOCKED entire binaries).
287          *
288          * Note that we do not enable IRQs here, unlike in the user case.  Again,
289          * this is to limit the locks we could be grabbing. */
290         err = handle_page_fault_nofile(pcpui->cur_proc, fault_va, prot);
291         pcpui->__lock_checking_enabled++;
292         if (err) {
293                 if (try_handle_exception_fixup(hw_tf))
294                         return TRUE;
295                 print_trapframe(hw_tf);
296                 backtrace_hwtf(hw_tf);
297                 /* Turn this on to help debug bad function pointers */
298                 printd("rsp %p\n\t 0(rsp): %p\n\t 8(rsp): %p\n\t 16(rsp): %p\n"
299                        "\t24(rsp): %p\n", hw_tf->tf_rsp,
300                        *(uintptr_t*)(hw_tf->tf_rsp +  0),
301                        *(uintptr_t*)(hw_tf->tf_rsp +  8),
302                        *(uintptr_t*)(hw_tf->tf_rsp + 16),
303                        *(uintptr_t*)(hw_tf->tf_rsp + 24));
304                 panic("Proc-ful Page Fault in the Kernel at %p!", fault_va);
305                 /* if we want to do something like kill a process or other code, be
306                  * aware we are in a sort of irq-like context, meaning the main
307                  * kernel code we 'interrupted' could be holding locks - even
308                  * irqsave locks. */
309         }
310         return TRUE;
311 }
312
313 static bool __handle_page_fault(struct hw_trapframe *hw_tf, unsigned long *aux)
314 {
315         uintptr_t fault_va = rcr2();
316         int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
317
318         *aux = fault_va;
319         if (in_kernel(hw_tf))
320                 return __handler_kernel_page_fault(hw_tf, fault_va, prot);
321         else
322                 return __handler_user_page_fault(hw_tf, fault_va, prot);
323 }
324
325 /* Certain traps want IRQs enabled, such as the syscall.  Others can't handle
326  * it, like the page fault handler.  Turn them on on a case-by-case basis. */
327 static void trap_dispatch(struct hw_trapframe *hw_tf)
328 {
329         struct per_cpu_info *pcpui;
330         bool handled = TRUE;
331         unsigned long aux = 0;
332         uintptr_t fixup_ip;
333
334         // Handle processor exceptions.
335         switch(hw_tf->tf_trapno) {
336                 case T_NMI:
337                         /* Temporarily disable deadlock detection when we print.  We could
338                          * deadlock if we were printing when we NMIed. */
339                         pcpui = &per_cpu_info[core_id()];
340                         pcpui->__lock_checking_enabled--;
341                         /* This is a bit hacky, but we don't have a decent API yet */
342                         extern bool mon_verbose_trace;
343                         if (mon_verbose_trace) {
344                                 print_trapframe(hw_tf);
345                                 backtrace_hwtf(hw_tf);
346                         }
347                         char *fn_name = get_fn_name(get_hwtf_pc(hw_tf));
348
349                         printk("Core %d is at %p (%s)\n", core_id(), get_hwtf_pc(hw_tf),
350                                fn_name);
351                         kfree(fn_name);
352                         print_kmsgs(core_id());
353                         pcpui->__lock_checking_enabled++;
354                         break;
355                 case T_BRKPT:
356                         enable_irq();
357                         monitor(hw_tf);
358                         disable_irq();
359                         break;
360                 case T_ILLOP:
361                 {
362                         /* TODO: this can PF if there is a concurrent unmap/PM removal. */
363                         uintptr_t ip = get_hwtf_pc(hw_tf);
364                         pcpui = &per_cpu_info[core_id()];
365                         pcpui->__lock_checking_enabled--;               /* for print debugging */
366                         /* We will muck with the actual TF.  If we're dealing with
367                          * userspace, we need to make sure we edit the actual TF that will
368                          * get restarted (pcpui), and not the TF on the kstack (which aren't
369                          * the same).  See set_current_ctx() for more info. */
370                         if (!in_kernel(hw_tf))
371                                 hw_tf = &pcpui->cur_ctx->tf.hw_tf;
372                         printd("bad opcode, eip: %p, next 3 bytes: %x %x %x\n", ip,
373                                *(uint8_t*)(ip + 0),
374                                *(uint8_t*)(ip + 1),
375                                *(uint8_t*)(ip + 2));
376                         /* rdtscp: 0f 01 f9 */
377                         if (*(uint8_t*)(ip + 0) == 0x0f,
378                             *(uint8_t*)(ip + 1) == 0x01,
379                             *(uint8_t*)(ip + 2) == 0xf9) {
380                                 x86_fake_rdtscp(hw_tf);
381                                 pcpui->__lock_checking_enabled++;       /* for print debugging */
382                                 return;
383                         }
384                         enable_irq();
385                         monitor(hw_tf);
386                         disable_irq();
387                         pcpui->__lock_checking_enabled++;               /* for print debugging */
388                         break;
389                 }
390                 case T_PGFLT:
391                         handled = __handle_page_fault(hw_tf, &aux);
392                         break;
393                 case T_FPERR:
394                         handled = try_handle_exception_fixup(hw_tf);
395                         if (!handled)
396                                 handle_fperr(hw_tf);
397                         break;
398                 case T_SYSCALL:
399                         enable_irq();
400                         // check for userspace, for now
401                         assert(hw_tf->tf_cs != GD_KT);
402                         /* Set up and run the async calls */
403                         /* TODO: this is using the wrong reg1 for traps for 32 bit */
404                         prep_syscalls(current,
405                                       (struct syscall*)x86_get_systrap_arg0(hw_tf),
406                                                   (unsigned int)x86_get_systrap_arg1(hw_tf));
407                         disable_irq();
408                         break;
409                 default:
410                         if (hw_tf->tf_cs == GD_KT) {
411                                 handled = try_handle_exception_fixup(hw_tf);
412                                 if (!handled) {
413                                         print_trapframe(hw_tf);
414                                         panic("Damn Damn!  Unhandled trap in the kernel!");
415                                 }
416                         } else {
417                                 handled = FALSE;
418                         }
419         }
420
421         if (!handled)
422                 reflect_unhandled_trap(hw_tf->tf_trapno, hw_tf->tf_err, aux);
423 }
424
425 /* Helper.  For now, this copies out the TF to pcpui.  Eventually, we should
426  * consider doing this in trapentry.S
427  *
428  * TODO: consider having this return the tf used, so we can set tf in trap and
429  * irq handlers to edit the TF that will get restarted.  Right now, the kernel
430  * uses and restarts tf, but userspace restarts the old pcpui tf.  It is
431  * tempting to do this, but note that tf stays on the stack of the kthread,
432  * while pcpui->cur_ctx is for the core we trapped in on.  Meaning if we ever
433  * block, suddenly cur_ctx is pointing to some old clobbered state that was
434  * already returned to and can't be trusted.  Meanwhile tf can always be trusted
435  * (like with an in_kernel() check).  The only types of traps from the user that
436  * can be expected to have editable trapframes are ones that don't block. */
437 static void set_current_ctx_hw(struct per_cpu_info *pcpui,
438                                struct hw_trapframe *hw_tf)
439 {
440         assert(!irq_is_enabled());
441         pcpui->actual_ctx.type = ROS_HW_CTX;
442         pcpui->actual_ctx.tf.hw_tf = *hw_tf;
443         pcpui->cur_ctx = &pcpui->actual_ctx;
444 }
445
446 static void set_current_ctx_sw(struct per_cpu_info *pcpui,
447                                struct sw_trapframe *sw_tf)
448 {
449         assert(!irq_is_enabled());
450         pcpui->actual_ctx.type = ROS_SW_CTX;
451         pcpui->actual_ctx.tf.sw_tf = *sw_tf;
452         pcpui->cur_ctx = &pcpui->actual_ctx;
453 }
454
455 static void set_current_ctx_vm(struct per_cpu_info *pcpui,
456                                struct vm_trapframe *vm_tf)
457 {
458         assert(!irq_is_enabled());
459         pcpui->actual_ctx.type = ROS_VM_CTX;
460         pcpui->actual_ctx.tf.vm_tf = *vm_tf;
461         pcpui->cur_ctx = &pcpui->actual_ctx;
462 }
463
464 void trap(struct hw_trapframe *hw_tf)
465 {
466         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
467         /* Copy out the TF for now */
468         if (!in_kernel(hw_tf)) {
469                 set_current_ctx_hw(pcpui, hw_tf);
470                 /* ignoring state for nested kernel traps.  should be rare. */
471                 __set_cpu_state(pcpui, CPU_STATE_KERNEL);
472         } else {
473                 inc_ktrap_depth(pcpui);
474         }
475         printd("Incoming TRAP %d on core %d, TF at %p\n", hw_tf->tf_trapno,
476                core_id(), hw_tf);
477         if ((hw_tf->tf_cs & ~3) != GD_UT && (hw_tf->tf_cs & ~3) != GD_KT) {
478                 print_trapframe(hw_tf);
479                 panic("Trapframe with invalid CS!");
480         }
481         trap_dispatch(hw_tf);
482         /* Return to the current process, which should be runnable.  If we're the
483          * kernel, we should just return naturally.  Note that current and tf need
484          * to still be okay (might not be after blocking) */
485         if (in_kernel(hw_tf)) {
486                 dec_ktrap_depth(pcpui);
487                 return;
488         }
489         proc_restartcore();
490         assert(0);
491 }
492
493 static bool vector_is_irq(int apic_vec)
494 {
495         /* arguably, we could limit them to MaxIdtIOAPIC */
496         return (IdtPIC <= apic_vec) && (apic_vec <= IdtMAX);
497 }
498
499 static void irq_dispatch(struct hw_trapframe *hw_tf)
500 {
501         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
502         struct irq_handler *irq_h;
503
504         if (!in_irq_ctx(pcpui))
505                 __set_cpu_state(pcpui, CPU_STATE_IRQ);
506         inc_irq_depth(pcpui);
507         //if (core_id())
508         if (hw_tf->tf_trapno != IdtLAPIC_TIMER) /* timer irq */
509         if (hw_tf->tf_trapno != I_KERNEL_MSG)
510         if (hw_tf->tf_trapno != 65)     /* qemu serial tends to get this one */
511                 printd("Incoming IRQ, ISR: %d on core %d\n", hw_tf->tf_trapno,
512                        core_id());
513         /* TODO: RCU read lock */
514         irq_h = irq_handlers[hw_tf->tf_trapno];
515         if (!irq_h) {
516                 warn_once("Received IRQ %d, had no handler registered!",
517                           hw_tf->tf_trapno);
518                 /* If we don't have an IRQ handler, we don't know how to EOI.  Odds are,
519                  * it's a LAPIC IRQ, such as I_TESTING */
520                 if (!lapic_check_spurious(hw_tf->tf_trapno))
521                         lapic_send_eoi(hw_tf->tf_trapno);
522                 goto out_no_eoi;
523         }
524         if (irq_h->check_spurious(hw_tf->tf_trapno))
525                 goto out_no_eoi;
526         /* Can now be interrupted/nested by higher priority IRQs, but not by our
527          * current IRQ vector, til we EOI. */
528         enable_irq();
529         while (irq_h) {
530                 irq_h->isr(hw_tf, irq_h->data);
531                 irq_h = irq_h->next;
532         }
533         // if we're a general purpose IPI function call, down the cpu_list
534         extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
535         if ((I_SMP_CALL0 <= hw_tf->tf_trapno) &&
536             (hw_tf->tf_trapno <= I_SMP_CALL_LAST))
537                 down_checklist(handler_wrappers[hw_tf->tf_trapno & 0x0f].cpu_list);
538         disable_irq();
539         /* Keep in sync with ipi_is_pending */
540         irq_handlers[hw_tf->tf_trapno]->eoi(hw_tf->tf_trapno);
541         /* Fall-through */
542 out_no_eoi:
543         dec_irq_depth(pcpui);
544         if (!in_irq_ctx(pcpui))
545                 __set_cpu_state(pcpui, CPU_STATE_KERNEL);
546 }
547
548 /* Note IRQs are disabled unless explicitly turned on.
549  *
550  * In general, we should only get trapno's >= PIC1_OFFSET (32).  Anything else
551  * should be a trap.  Even if we don't use the PIC, that should be the standard.
552  * It is possible to get a spurious LAPIC IRQ with vector 15 (or similar), but
553  * the spurious check should catch that.
554  *
555  * Note that from hardware's perspective (PIC, etc), IRQs start from 0, but they
556  * are all mapped up at PIC1_OFFSET for the cpu / irq_handler. */
557 void handle_irq(struct hw_trapframe *hw_tf)
558 {
559         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
560
561         /* Copy out the TF for now */
562         if (!in_kernel(hw_tf))
563                 set_current_ctx_hw(pcpui, hw_tf);
564         irq_dispatch(hw_tf);
565         /* Return to the current process, which should be runnable.  If we're the
566          * kernel, we should just return naturally.  Note that current and tf need
567          * to still be okay (might not be after blocking) */
568         if (in_kernel(hw_tf))
569                 return;
570         proc_restartcore();
571         assert(0);
572 }
573
574 /* The irq field may be ignored based on the type of Bus. */
575 int register_irq(int irq, isr_t handler, void *irq_arg, uint32_t tbdf)
576 {
577         struct irq_handler *irq_h;
578         int vector;
579         irq_h = kzmalloc(sizeof(struct irq_handler), 0);
580         assert(irq_h);
581         irq_h->dev_irq = irq;
582         irq_h->tbdf = tbdf;
583         vector = bus_irq_setup(irq_h);
584         if (vector == -1) {
585                 kfree(irq_h);
586                 return -1;
587         }
588         printk("IRQ %d, vector %d (0x%x), type %s\n", irq, vector, vector,
589                irq_h->type);
590         assert(irq_h->check_spurious && irq_h->eoi);
591         irq_h->isr = handler;
592         irq_h->data = irq_arg;
593         irq_h->apic_vector = vector;
594         /* RCU write lock */
595         spin_lock_irqsave(&irq_handler_wlock);
596         irq_h->next = irq_handlers[vector];
597         wmb();  /* make sure irq_h is done before publishing to readers */
598         irq_handlers[vector] = irq_h;
599         spin_unlock_irqsave(&irq_handler_wlock);
600         /* Most IRQs other than the BusIPI should need their irq unmasked.
601          * Might need to pass the irq_h, in case unmask needs more info.
602          * The lapic IRQs need to be unmasked on a per-core basis */
603         if (irq_h->unmask && strcmp(irq_h->type, "lapic"))
604                 irq_h->unmask(irq_h, vector);
605         return 0;
606 }
607
608 /* These routing functions only allow the routing of an irq to a single core.
609  * If we want to route to multiple cores, we'll probably need to set up logical
610  * groups or something and take some additional parameters. */
611 static int route_irq_h(struct irq_handler *irq_h, int os_coreid)
612 {
613         int hw_coreid;
614         if (!irq_h->route_irq) {
615                 printk("[kernel] apic_vec %d, type %s cannot be routed\n",
616                        irq_h->apic_vector, irq_h->type);
617                 return -1;
618         }
619         if (os_coreid >= MAX_NUM_CORES) {
620                 printk("[kernel] os_coreid %d out of range!\n", os_coreid);
621                 return -1;
622         }
623         hw_coreid = get_hw_coreid(os_coreid);
624         if (hw_coreid == -1) {
625                 printk("[kernel] os_coreid %d not a valid hw core!\n", os_coreid);
626                 return -1;
627         }
628         irq_h->route_irq(irq_h, irq_h->apic_vector, hw_coreid);
629         return 0;
630 }
631
632 /* Routes all irqs for a given apic_vector to os_coreid.  Returns 0 if all of
633  * them succeeded.  -1 if there were none or if any of them failed.  We don't
634  * share IRQs often (if ever anymore), so this shouldn't be an issue. */
635 int route_irqs(int apic_vec, int os_coreid)
636 {
637         struct irq_handler *irq_h;
638         int ret = -1;
639         if (!vector_is_irq(apic_vec)) {
640                 printk("[kernel] vector %d is not an IRQ vector!\n", apic_vec);
641                 return -1;
642         }
643         irq_h = irq_handlers[apic_vec];
644         while (irq_h) {
645                 assert(irq_h->apic_vector == apic_vec);
646                 ret = route_irq_h(irq_h, os_coreid);
647                 irq_h = irq_h->next;
648         }
649         return ret;
650 }
651
652 /* It's a moderate pain in the ass to put these in bit-specific files (header
653  * hell with the set_current_ helpers) */
654 void sysenter_callwrapper(struct syscall *sysc, unsigned long count,
655                           struct sw_trapframe *sw_tf)
656 {
657         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
658         set_current_ctx_sw(pcpui, sw_tf);
659         __set_cpu_state(pcpui, CPU_STATE_KERNEL);
660         /* Once we've set_current_ctx, we can enable interrupts.  This used to be
661          * mandatory (we had immediate KMSGs that would muck with cur_ctx).  Now it
662          * should only help for sanity/debugging. */
663         enable_irq();
664         /* Set up and run the async calls.  This may block, and we could migrate to
665          * another core.  If you use pcpui again, you need to reread it. */
666         prep_syscalls(current, sysc, count);
667         disable_irq();
668         proc_restartcore();
669 }
670
671 /* Declared in x86/arch.h */
672 void send_ipi(uint32_t os_coreid, uint8_t vector)
673 {
674         int hw_coreid = get_hw_coreid(os_coreid);
675         if (hw_coreid == -1) {
676                 panic("Unmapped OS coreid (OS %d)!\n", os_coreid);
677                 return;
678         }
679         __send_ipi(hw_coreid, vector);
680 }
681
682 /****************** VM exit handling ******************/
683
684 static bool handle_vmexit_cpuid(struct vm_trapframe *tf)
685 {
686         uint32_t eax, ebx, ecx, edx;
687
688         cpuid(tf->tf_rax, tf->tf_rcx, &eax, &ebx, &ecx, &edx);
689         tf->tf_rax = eax;
690         tf->tf_rbx = ebx;
691         tf->tf_rcx = ecx;
692         tf->tf_rdx = edx;
693         tf->tf_rip += 2;
694         return TRUE;
695 }
696
697 static bool handle_vmexit_ept_fault(struct vm_trapframe *tf)
698 {
699         int prot = 0;
700         int ret;
701
702         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_READ ? PROT_READ : 0;
703         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_WRITE ? PROT_WRITE : 0;
704         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_INS ? PROT_EXEC : 0;
705         ret = handle_page_fault(current, tf->tf_guest_pa, prot);
706         if (ret) {
707                 /* TODO: maybe put ret in the TF somewhere */
708                 return FALSE;
709         }
710         return TRUE;
711 }
712
713 static bool handle_vmexit_nmi(struct vm_trapframe *tf)
714 {
715         /* Sanity checks, make sure we really got an NMI.  Feel free to remove. */
716         assert((tf->tf_intrinfo2 & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR);
717         assert((tf->tf_intrinfo2 & INTR_INFO_VECTOR_MASK) == T_NMI);
718         /* our NMI handler from trap.c won't run.  but we don't need the lock
719          * disabling stuff. */
720         extern bool mon_verbose_trace;
721
722         if (mon_verbose_trace) {
723                 print_vmtrapframe(tf);
724                 /* TODO: a backtrace of the guest would be nice here. */
725         }
726         printk("Core %d is at %p\n", core_id(), get_vmtf_pc(tf));
727         return TRUE;
728 }
729
730 bool handle_vmexit_msr(struct vm_trapframe *tf)
731 {
732         bool ret;
733
734         ret = vmm_emulate_msr(&tf->tf_rcx, &tf->tf_rdx, &tf->tf_rax,
735                               (tf->tf_exit_reason == EXIT_REASON_MSR_READ
736                                                    ? VMM_MSR_EMU_READ : VMM_MSR_EMU_WRITE));
737         if (ret)
738                 tf->tf_rip += 2;
739         return ret;
740 }
741
742 bool handle_vmexit_extirq(struct vm_trapframe *tf)
743 {
744         struct hw_trapframe hw_tf;
745
746         /* For now, we just handle external IRQs.  I think guest traps should go to
747          * the guest, based on our vmctls */
748         assert((tf->tf_intrinfo2 & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_EXT_INTR);
749         /* TODO: Our IRQ handlers all expect TFs.  Let's fake one.  A bunch of
750          * handlers (e.g. backtrace/perf) will probably be unhappy about a user TF
751          * that is really a VM, so this all needs work. */
752         hw_tf.tf_gsbase = 0;
753         hw_tf.tf_fsbase = 0;
754         hw_tf.tf_rax = tf->tf_rax;
755         hw_tf.tf_rbx = tf->tf_rbx;
756         hw_tf.tf_rcx = tf->tf_rcx;
757         hw_tf.tf_rdx = tf->tf_rdx;
758         hw_tf.tf_rbp = tf->tf_rbp;
759         hw_tf.tf_rsi = tf->tf_rsi;
760         hw_tf.tf_rdi = tf->tf_rdi;
761         hw_tf.tf_r8 = tf->tf_r8;
762         hw_tf.tf_r9 = tf->tf_r9;
763         hw_tf.tf_r10 = tf->tf_r10;
764         hw_tf.tf_r11 = tf->tf_r11;
765         hw_tf.tf_r12 = tf->tf_r12;
766         hw_tf.tf_r13 = tf->tf_r13;
767         hw_tf.tf_r14 = tf->tf_r14;
768         hw_tf.tf_r15 = tf->tf_r15;
769         hw_tf.tf_trapno = tf->tf_intrinfo2 & INTR_INFO_VECTOR_MASK;
770         hw_tf.tf_err = 0;
771         hw_tf.tf_rip = tf->tf_rip;
772         hw_tf.tf_cs = GD_UT;    /* faking a user TF, even though it's a VM */
773         hw_tf.tf_rflags = tf->tf_rflags;
774         hw_tf.tf_rsp = tf->tf_rsp;
775         hw_tf.tf_ss = GD_UD;
776
777         irq_dispatch(&hw_tf);
778         /* Consider returning whether or not there was a handler registered */
779         return TRUE;
780 }
781
782 static bool handle_vmexit_xsetbv(struct vm_trapframe *tf)
783 {
784         // The VM's requested-feature bitmap is represented by edx:eax
785         uint64_t vm_rfbm = (tf->tf_rdx << 32) | tf->tf_rax;
786
787         // If the VM tries to set xcr0 to a superset
788         // of Akaros's default value, kill the VM.
789
790         // Bit in vm_rfbm and x86_default_xcr0:        Ok. Requested and allowed.
791         // Bit in vm_rfbm but not x86_default_xcr0:    Bad! Requested, not allowed.
792         // Bit not in vm_rfbm but in x86_default_xcr0: Ok. Not requested.
793
794         // vm_rfbm & (~x86_default_xcr0) is nonzero if any bits
795         // are set in vm_rfbm but not x86_default_xcr0
796
797         if (vm_rfbm & (~__proc_global_info.x86_default_xcr0))
798                 return FALSE;
799
800
801         // If attempting to use vm_rfbm for xsetbv
802         // causes a fault, we reflect to the VMM.
803         if (safe_lxcr0(vm_rfbm))
804                 return FALSE;
805
806
807         // If no fault, advance the instruction pointer
808         // and return TRUE to make the VM resume.
809         tf->tf_rip += 3; // XSETBV is a 3-byte instruction
810         return TRUE;
811 }
812
813 static void vmexit_dispatch(struct vm_trapframe *tf)
814 {
815         bool handled = FALSE;
816
817         /* Do not block in any of these functions.
818          *
819          * If we block, we'll probably need to finalize the context.  If we do, then
820          * there's a chance the guest pcore can start somewhere else, and then we
821          * can't get the GPC loaded again.  Plus, they could be running a GPC with
822          * an unresolved vmexit.  It's just mess.
823          *
824          * If we want to enable IRQs, we can do so on a case-by-case basis.  Don't
825          * do it for external IRQs - the irq_dispatch code will handle it. */
826         switch (tf->tf_exit_reason) {
827         case EXIT_REASON_VMCALL:
828                 if (current->vmm.flags & VMM_VMCALL_PRINTF) {
829                         printk("%c", tf->tf_rdi);
830                         tf->tf_rip += 3;
831                         handled = TRUE;
832                 }
833                 break;
834         case EXIT_REASON_CPUID:
835                 handled = handle_vmexit_cpuid(tf);
836                 break;
837         case EXIT_REASON_EPT_VIOLATION:
838                 handled = handle_vmexit_ept_fault(tf);
839                 break;
840         case EXIT_REASON_EXCEPTION_NMI:
841                 handled = handle_vmexit_nmi(tf);
842                 break;
843         case EXIT_REASON_MSR_READ:
844         case EXIT_REASON_MSR_WRITE:
845                 handled = handle_vmexit_msr(tf);
846                 break;
847         case EXIT_REASON_EXTERNAL_INTERRUPT:
848                 handled = handle_vmexit_extirq(tf);
849                 break;
850         case EXIT_REASON_XSETBV:
851                 handled = handle_vmexit_xsetbv(tf);
852                 break;
853         default:
854                 printd("Unhandled vmexit: reason 0x%x, exit qualification 0x%x\n",
855                        tf->tf_exit_reason, tf->tf_exit_qual);
856         }
857         if (!handled) {
858                 tf->tf_flags |= VMCTX_FL_HAS_FAULT;
859                 if (reflect_current_context()) {
860                         /* VM contexts shouldn't be in vcore context, so this should be
861                          * pretty rare (unlike SCPs or VC ctx page faults). */
862                         printk("[kernel] Unable to reflect VM Exit\n");
863                         print_vmtrapframe(tf);
864                         proc_destroy(current);
865                 }
866         }
867 }
868
869 void handle_vmexit(struct vm_trapframe *tf)
870 {
871         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
872
873         tf->tf_rip = vmcs_read(GUEST_RIP);
874         tf->tf_rflags = vmcs_read(GUEST_RFLAGS);
875         tf->tf_rsp = vmcs_read(GUEST_RSP);
876         tf->tf_cr2 = rcr2();
877         tf->tf_cr3 = vmcs_read(GUEST_CR3);
878         tf->tf_guest_pcoreid = pcpui->guest_pcoreid;
879         tf->tf_flags |= VMCTX_FL_PARTIAL;
880         tf->tf_exit_reason = vmcs_read(VM_EXIT_REASON);
881         tf->tf_exit_qual = vmcs_read(EXIT_QUALIFICATION);
882         tf->tf_intrinfo1 = vmcs_read(GUEST_INTERRUPTIBILITY_INFO);
883         tf->tf_intrinfo2 = vmcs_read(VM_EXIT_INTR_INFO);
884         tf->tf_guest_va = vmcs_read(GUEST_LINEAR_ADDRESS);
885         tf->tf_guest_pa = vmcs_read(GUEST_PHYSICAL_ADDRESS);
886
887         set_current_ctx_vm(pcpui, tf);
888         tf = &pcpui->cur_ctx->tf.vm_tf;
889         vmexit_dispatch(tf);
890         /* We're either restarting a partial VM ctx (vmcs was launched, loaded on
891          * the core, etc) or a SW vc ctx for the reflected trap.  Or the proc is
892          * dying and we'll handle a __death KMSG shortly. */
893         proc_restartcore();
894 }
895
896 void x86_finalize_vmtf(struct vm_trapframe *tf)
897 {
898         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
899
900         x86_vmtf_clear_partial(tf);
901         unload_guest_pcore(pcpui->cur_proc, pcpui->guest_pcoreid);
902 }