Intercept CPUID calls to act like KVM
[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         /* 0x4000000 is taken from Linux; it is not documented but it signals the
689          * use of KVM. */
690         if (tf->tf_rax == 0x40000000) {
691                 /* Pretend to be KVM: Return the KVM signature by placing the following
692                  * constants in RAX, RBX, RCX and RDX. RAX is set to 0, while RBX to
693                  * RDX forms the string "KVMKVMKVMKVM\0\0\0". This can be placed in
694                  * 0x100 offsets from 0x40000000 to 0x40010000. */
695                 eax = 0;
696                 ebx = 0x4b4d564b;
697                 ecx = 0x564b4d56;
698                 edx = 0x0000004d;
699         } else {
700                 cpuid(tf->tf_rax, tf->tf_rcx, &eax, &ebx, &ecx, &edx);
701                 if (tf->tf_rax == 1) {
702                         /* Set the hypervisor bit to let the guest know it is virtualized */
703                         ecx |= 1 << 31;
704                 }
705         }
706         tf->tf_rax = eax;
707         tf->tf_rbx = ebx;
708         tf->tf_rcx = ecx;
709         tf->tf_rdx = edx;
710         tf->tf_rip += 2;
711         return TRUE;
712 }
713
714 static bool handle_vmexit_ept_fault(struct vm_trapframe *tf)
715 {
716         int prot = 0;
717         int ret;
718
719         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_READ ? PROT_READ : 0;
720         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_WRITE ? PROT_WRITE : 0;
721         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_INS ? PROT_EXEC : 0;
722         ret = handle_page_fault(current, tf->tf_guest_pa, prot);
723         if (ret) {
724                 /* TODO: maybe put ret in the TF somewhere */
725                 return FALSE;
726         }
727         return TRUE;
728 }
729
730 static bool handle_vmexit_nmi(struct vm_trapframe *tf)
731 {
732         /* Sanity checks, make sure we really got an NMI.  Feel free to remove. */
733         assert((tf->tf_intrinfo2 & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR);
734         assert((tf->tf_intrinfo2 & INTR_INFO_VECTOR_MASK) == T_NMI);
735         /* our NMI handler from trap.c won't run.  but we don't need the lock
736          * disabling stuff. */
737         extern bool mon_verbose_trace;
738
739         if (mon_verbose_trace) {
740                 print_vmtrapframe(tf);
741                 /* TODO: a backtrace of the guest would be nice here. */
742         }
743         printk("Core %d is at %p\n", core_id(), get_vmtf_pc(tf));
744         return TRUE;
745 }
746
747 bool handle_vmexit_msr(struct vm_trapframe *tf)
748 {
749         bool ret;
750
751         ret = vmm_emulate_msr(&tf->tf_rcx, &tf->tf_rdx, &tf->tf_rax,
752                               (tf->tf_exit_reason == EXIT_REASON_MSR_READ
753                                                    ? VMM_MSR_EMU_READ : VMM_MSR_EMU_WRITE));
754         if (ret)
755                 tf->tf_rip += 2;
756         return ret;
757 }
758
759 bool handle_vmexit_extirq(struct vm_trapframe *tf)
760 {
761         struct hw_trapframe hw_tf;
762
763         /* For now, we just handle external IRQs.  I think guest traps should go to
764          * the guest, based on our vmctls */
765         assert((tf->tf_intrinfo2 & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_EXT_INTR);
766         /* TODO: Our IRQ handlers all expect TFs.  Let's fake one.  A bunch of
767          * handlers (e.g. backtrace/perf) will probably be unhappy about a user TF
768          * that is really a VM, so this all needs work. */
769         hw_tf.tf_gsbase = 0;
770         hw_tf.tf_fsbase = 0;
771         hw_tf.tf_rax = tf->tf_rax;
772         hw_tf.tf_rbx = tf->tf_rbx;
773         hw_tf.tf_rcx = tf->tf_rcx;
774         hw_tf.tf_rdx = tf->tf_rdx;
775         hw_tf.tf_rbp = tf->tf_rbp;
776         hw_tf.tf_rsi = tf->tf_rsi;
777         hw_tf.tf_rdi = tf->tf_rdi;
778         hw_tf.tf_r8 = tf->tf_r8;
779         hw_tf.tf_r9 = tf->tf_r9;
780         hw_tf.tf_r10 = tf->tf_r10;
781         hw_tf.tf_r11 = tf->tf_r11;
782         hw_tf.tf_r12 = tf->tf_r12;
783         hw_tf.tf_r13 = tf->tf_r13;
784         hw_tf.tf_r14 = tf->tf_r14;
785         hw_tf.tf_r15 = tf->tf_r15;
786         hw_tf.tf_trapno = tf->tf_intrinfo2 & INTR_INFO_VECTOR_MASK;
787         hw_tf.tf_err = 0;
788         hw_tf.tf_rip = tf->tf_rip;
789         hw_tf.tf_cs = GD_UT;    /* faking a user TF, even though it's a VM */
790         hw_tf.tf_rflags = tf->tf_rflags;
791         hw_tf.tf_rsp = tf->tf_rsp;
792         hw_tf.tf_ss = GD_UD;
793
794         irq_dispatch(&hw_tf);
795         /* Consider returning whether or not there was a handler registered */
796         return TRUE;
797 }
798
799 static bool handle_vmexit_xsetbv(struct vm_trapframe *tf)
800 {
801         // The VM's requested-feature bitmap is represented by edx:eax
802         uint64_t vm_rfbm = (tf->tf_rdx << 32) | tf->tf_rax;
803
804         // If the VM tries to set xcr0 to a superset
805         // of Akaros's default value, kill the VM.
806
807         // Bit in vm_rfbm and x86_default_xcr0:        Ok. Requested and allowed.
808         // Bit in vm_rfbm but not x86_default_xcr0:    Bad! Requested, not allowed.
809         // Bit not in vm_rfbm but in x86_default_xcr0: Ok. Not requested.
810
811         // vm_rfbm & (~x86_default_xcr0) is nonzero if any bits
812         // are set in vm_rfbm but not x86_default_xcr0
813
814         if (vm_rfbm & (~__proc_global_info.x86_default_xcr0))
815                 return FALSE;
816
817
818         // If attempting to use vm_rfbm for xsetbv
819         // causes a fault, we reflect to the VMM.
820         if (safe_lxcr0(vm_rfbm))
821                 return FALSE;
822
823
824         // If no fault, advance the instruction pointer
825         // and return TRUE to make the VM resume.
826         tf->tf_rip += 3; // XSETBV is a 3-byte instruction
827         return TRUE;
828 }
829
830 static void vmexit_dispatch(struct vm_trapframe *tf)
831 {
832         bool handled = FALSE;
833
834         /* Do not block in any of these functions.
835          *
836          * If we block, we'll probably need to finalize the context.  If we do, then
837          * there's a chance the guest pcore can start somewhere else, and then we
838          * can't get the GPC loaded again.  Plus, they could be running a GPC with
839          * an unresolved vmexit.  It's just mess.
840          *
841          * If we want to enable IRQs, we can do so on a case-by-case basis.  Don't
842          * do it for external IRQs - the irq_dispatch code will handle it. */
843         switch (tf->tf_exit_reason) {
844         case EXIT_REASON_VMCALL:
845                 if (current->vmm.flags & VMM_VMCALL_PRINTF) {
846                         printk("%c", tf->tf_rdi);
847                         tf->tf_rip += 3;
848                         handled = TRUE;
849                 }
850                 break;
851         case EXIT_REASON_CPUID:
852                 handled = handle_vmexit_cpuid(tf);
853                 break;
854         case EXIT_REASON_EPT_VIOLATION:
855                 handled = handle_vmexit_ept_fault(tf);
856                 break;
857         case EXIT_REASON_EXCEPTION_NMI:
858                 handled = handle_vmexit_nmi(tf);
859                 break;
860         case EXIT_REASON_MSR_READ:
861         case EXIT_REASON_MSR_WRITE:
862                 handled = handle_vmexit_msr(tf);
863                 break;
864         case EXIT_REASON_EXTERNAL_INTERRUPT:
865                 handled = handle_vmexit_extirq(tf);
866                 break;
867         case EXIT_REASON_XSETBV:
868                 handled = handle_vmexit_xsetbv(tf);
869                 break;
870         default:
871                 printd("Unhandled vmexit: reason 0x%x, exit qualification 0x%x\n",
872                        tf->tf_exit_reason, tf->tf_exit_qual);
873         }
874         if (!handled) {
875                 tf->tf_flags |= VMCTX_FL_HAS_FAULT;
876                 if (reflect_current_context()) {
877                         /* VM contexts shouldn't be in vcore context, so this should be
878                          * pretty rare (unlike SCPs or VC ctx page faults). */
879                         printk("[kernel] Unable to reflect VM Exit\n");
880                         print_vmtrapframe(tf);
881                         proc_destroy(current);
882                 }
883         }
884 }
885
886 void handle_vmexit(struct vm_trapframe *tf)
887 {
888         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
889
890         tf->tf_rip = vmcs_read(GUEST_RIP);
891         tf->tf_rflags = vmcs_read(GUEST_RFLAGS);
892         tf->tf_rsp = vmcs_read(GUEST_RSP);
893         tf->tf_cr2 = rcr2();
894         tf->tf_cr3 = vmcs_read(GUEST_CR3);
895         tf->tf_guest_pcoreid = pcpui->guest_pcoreid;
896         tf->tf_flags |= VMCTX_FL_PARTIAL;
897         tf->tf_exit_reason = vmcs_read(VM_EXIT_REASON);
898         tf->tf_exit_qual = vmcs_read(EXIT_QUALIFICATION);
899         tf->tf_intrinfo1 = vmcs_read(GUEST_INTERRUPTIBILITY_INFO);
900         tf->tf_intrinfo2 = vmcs_read(VM_EXIT_INTR_INFO);
901         tf->tf_guest_va = vmcs_read(GUEST_LINEAR_ADDRESS);
902         tf->tf_guest_pa = vmcs_read(GUEST_PHYSICAL_ADDRESS);
903
904         set_current_ctx_vm(pcpui, tf);
905         tf = &pcpui->cur_ctx->tf.vm_tf;
906         vmexit_dispatch(tf);
907         /* We're either restarting a partial VM ctx (vmcs was launched, loaded on
908          * the core, etc) or a SW vc ctx for the reflected trap.  Or the proc is
909          * dying and we'll handle a __death KMSG shortly. */
910         proc_restartcore();
911 }
912
913 void x86_finalize_vmtf(struct vm_trapframe *tf)
914 {
915         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
916
917         x86_vmtf_clear_partial(tf);
918         unload_guest_pcore(pcpui->cur_proc, pcpui->guest_pcoreid);
919 }