3b44f95dbb1f4ffdebdcdffdeeeece01246f920d
[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 enum {
25         NMI_NORMAL_OPN = 0,
26         NMI_IN_PROGRESS,
27         NMI_HANDLE_ANOTHER,
28 };
29
30 taskstate_t ts;
31
32 /* Interrupt descriptor table.  64 bit needs 16 byte alignment (i think). */
33 gatedesc_t __attribute__((aligned (16))) idt[256] = { { 0 } };
34 pseudodesc_t idt_pd;
35
36 /* interrupt handler table, each element is a linked list of handlers for a
37  * given IRQ.  Modification requires holding the lock (TODO: RCU) */
38 struct irq_handler *irq_handlers[NUM_IRQS];
39 spinlock_t irq_handler_wlock = SPINLOCK_INITIALIZER_IRQSAVE;
40
41 static bool try_handle_exception_fixup(struct hw_trapframe *hw_tf)
42 {
43         if (in_kernel(hw_tf)) {
44                 uintptr_t fixup_ip = get_fixup_ip(hw_tf->tf_rip);
45
46                 if (fixup_ip != 0) {
47                         hw_tf->tf_rip = fixup_ip;
48                         return true;
49                 }
50         }
51
52         return false;
53 }
54
55 const char *x86_trapname(int trapno)
56 {
57         static const char *const excnames[] = {
58                 "Divide error",
59                 "Debug",
60                 "Non-Maskable Interrupt",
61                 "Breakpoint",
62                 "Overflow",
63                 "BOUND Range Exceeded",
64                 "Invalid Opcode",
65                 "Device Not Available",
66                 "Double Fault",
67                 "Coprocessor Segment Overrun",
68                 "Invalid TSS",
69                 "Segment Not Present",
70                 "Stack Fault",
71                 "General Protection",
72                 "Page Fault",
73                 "(unknown trap)",
74                 "x87 FPU Floating-Point Error",
75                 "Alignment Check",
76                 "Machine-Check",
77                 "SIMD Floating-Point Exception"
78         };
79
80         if (trapno < sizeof(excnames)/sizeof(excnames[0]))
81                 return excnames[trapno];
82         if (trapno == T_SYSCALL)
83                 return "System call";
84         return "(unknown trap)";
85 }
86
87 /* Set stacktop for the current core to be the stack the kernel will start on
88  * when trapping/interrupting from userspace.  Don't use this til after
89  * smp_percpu_init().  We can probably get the TSS by reading the task register
90  * and then the GDT.  Still, it's a pain. */
91 void set_stack_top(uintptr_t stacktop)
92 {
93         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
94         /* No need to reload the task register, this takes effect immediately */
95         x86_set_stacktop_tss(pcpui->tss, stacktop);
96         /* Also need to make sure sysenters come in correctly */
97         x86_set_sysenter_stacktop(stacktop);
98 }
99
100 /* Note the check implies we only are on a one page stack (or the first page) */
101 uintptr_t get_stack_top(void)
102 {
103         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
104         uintptr_t stacktop;
105         /* so we can check this in interrupt handlers (before smp_boot()) */
106         /* TODO: These are dangerous - it assumes we're on a one-page stack.  If we
107          * change it to KSTKSIZE, then we assume stacks are KSTKSIZE-aligned */
108         if (!pcpui->tss)
109                 return ROUNDUP(read_sp(), PGSIZE);
110         stacktop = x86_get_stacktop_tss(pcpui->tss);
111         if (stacktop != ROUNDUP(read_sp(), PGSIZE))
112                 panic("Bad stacktop: %p esp one is %p\n", stacktop,
113                       ROUNDUP(read_sp(), PGSIZE));
114         return stacktop;
115 }
116
117 /* Sends a non-maskable interrupt; the handler will print a trapframe. */
118 void send_nmi(uint32_t os_coreid)
119 {
120         /* NMI / IPI for x86 are limited to 8 bits */
121         uint8_t hw_core = (uint8_t)get_hw_coreid(os_coreid);
122         __send_nmi(hw_core);
123 }
124
125 void idt_init(void)
126 {
127         /* This table is made in trapentry$BITS.S by each macro in that file.
128          * It is layed out such that the ith entry is the ith's traphandler's
129          * (uintptr_t) trap addr, then (uint32_t) trap number. */
130         struct trapinfo { uintptr_t trapaddr; uint32_t trapnumber; }
131                __attribute__((packed));
132         extern struct trapinfo trap_tbl[];
133         extern struct trapinfo trap_tbl_end[];
134         int i, trap_tbl_size = trap_tbl_end - trap_tbl;
135         extern void ISR_default(void);
136         extern void ISR_syscall(void);
137
138         /* set all to default, to catch everything */
139         for (i = 0; i < 256; i++)
140                 SETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
141
142         /* set all entries that have real trap handlers
143          * we need to stop short of the last one, since the last is the default
144          * handler with a fake interrupt number (500) that is out of bounds of
145          * the idt[] */
146         for (i = 0; i < trap_tbl_size - 1; i++)
147                 SETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
148         /* Sanity check */
149         assert((uintptr_t)ISR_syscall ==
150                ((uintptr_t)idt[T_SYSCALL].gd_off_63_32 << 32 |
151                 (uintptr_t)idt[T_SYSCALL].gd_off_31_16 << 16 |
152                 (uintptr_t)idt[T_SYSCALL].gd_off_15_0));
153         /* turn on trap-based syscall handling and other user-accessible ints
154          * DPL 3 means this can be triggered by the int instruction */
155         idt[T_SYSCALL].gd_dpl = 3;
156         idt[T_BRKPT].gd_dpl = 3;
157         /* Send NMIs to their own stack (IST1 in every core's TSS) */
158         idt[T_NMI].gd_ist = 1;
159
160         /* Set up our kernel stack when changing rings */
161         /* Note: we want 16 byte aligned kernel stack frames (AMD 2:8.9.3) */
162         x86_set_stacktop_tss(&ts, (uintptr_t)bootstacktop);
163         x86_sysenter_init((uintptr_t)bootstacktop);
164
165 #ifdef CONFIG_KTHREAD_POISON
166         *kstack_bottom_addr((uintptr_t)bootstacktop) = 0xdeadbeef;
167 #endif /* CONFIG_KTHREAD_POISON */
168
169         /* Initialize the TSS field of the gdt.  The size of the TSS desc differs
170          * between 64 and 32 bit, hence the pointer acrobatics */
171         syssegdesc_t *ts_slot = (syssegdesc_t*)&gdt[GD_TSS >> 3];
172         *ts_slot = (syssegdesc_t)SEG_SYS_SMALL(STS_T32A, (uintptr_t)&ts,
173                                                sizeof(taskstate_t), 0);
174
175         /* Init the IDT PD.  Need to do this before ltr for some reason.  (Doing
176          * this between ltr and lidt causes the machine to reboot... */
177         idt_pd.pd_lim = sizeof(idt) - 1;
178         idt_pd.pd_base = (uintptr_t)idt;
179
180         ltr(GD_TSS);
181
182         asm volatile("lidt %0" : : "m"(idt_pd));
183
184         pic_remap();
185         pic_mask_all();
186
187         int ncleft = MAX_NUM_CORES;
188         int num_cores_mpacpi;
189
190         ncleft = mpsinit(ncleft);
191         ncleft = mpacpi(ncleft);
192         num_cores_mpacpi = MAX_NUM_CORES - ncleft;
193         printk("MP and ACPI found %d cores\n", num_cores_mpacpi);
194         if (num_cores != num_cores_mpacpi)
195                 warn("Topology (%d) and MP/ACPI (%d) differ on num_cores!", num_cores,
196                      num_cores_mpacpi);
197
198         apiconline();
199         ioapiconline();
200
201         /* the lapic IRQs need to be unmasked on a per-core basis */
202         register_irq(IdtLAPIC_TIMER, timer_interrupt, NULL,
203                      MKBUS(BusLAPIC, 0, 0, 0));
204         register_irq(IdtLAPIC_ERROR, handle_lapic_error, NULL,
205                      MKBUS(BusLAPIC, 0, 0, 0));
206         register_irq(IdtLAPIC_PCINT, perfmon_interrupt, NULL,
207                      MKBUS(BusLAPIC, 0, 0, 0));
208         register_irq(I_KERNEL_MSG, handle_kmsg_ipi, NULL, MKBUS(BusIPI, 0, 0, 0));
209 }
210
211 static void handle_fperr(struct hw_trapframe *hw_tf)
212 {
213         uint16_t fpcw, fpsw;
214         uint32_t mxcsr;
215         asm volatile ("fnstcw %0" : "=m"(fpcw));
216         asm volatile ("fnstsw %0" : "=m"(fpsw));
217         asm volatile ("stmxcsr %0" : "=m"(mxcsr));
218         print_trapframe(hw_tf);
219         printk("Core %d: FP ERR, CW: 0x%04x, SW: 0x%04x, MXCSR 0x%08x\n", core_id(),
220                fpcw, fpsw, mxcsr);
221         printk("Core %d: The following faults are unmasked:\n", core_id());
222         if (fpsw & ~fpcw & FP_EXCP_IE) {
223                 printk("\tInvalid Operation: ");
224                 if (fpsw & FP_SW_SF) {
225                         if (fpsw & FP_SW_C1)
226                                 printk("Stack overflow\n");
227                         else
228                                 printk("Stack underflow\n");
229                 } else {
230                         printk("invalid arithmetic operand\n");
231                 }
232         }
233         if (fpsw & ~fpcw & FP_EXCP_DE)
234                 printk("\tDenormalized operand\n");
235         if (fpsw & ~fpcw & FP_EXCP_ZE)
236                 printk("\tDivide by zero\n");
237         if (fpsw & ~fpcw & FP_EXCP_OE)
238                 printk("\tNumeric Overflow\n");
239         if (fpsw & ~fpcw & FP_EXCP_UE)
240                 printk("\tNumeric Underflow\n");
241         if (fpsw & ~fpcw & FP_EXCP_PE)
242                 printk("\tInexact result (precision)\n");
243         printk("Killing the process.\n");
244         proc_destroy(current);
245 }
246
247 static bool __handler_user_page_fault(struct hw_trapframe *hw_tf,
248                                       uintptr_t fault_va, int prot)
249 {
250         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
251         int err;
252
253         assert(pcpui->owning_proc == pcpui->cur_proc);
254         enable_irq();
255         err = handle_page_fault(pcpui->owning_proc, fault_va, prot);
256         disable_irq();
257         if (err) {
258                 if (err == -EAGAIN)
259                         hw_tf->tf_err |= PF_VMR_BACKED;
260                 return FALSE;
261         }
262         return TRUE;
263 }
264
265 static bool __handler_kernel_page_fault(struct hw_trapframe *hw_tf,
266                                         uintptr_t fault_va, int prot)
267 {
268         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
269         int err;
270
271         /* In general, if there's no cur_proc, a KPF is a bug. */
272         if (!pcpui->cur_proc) {
273                 /* This only runs from test_uaccess(), where it is expected to fail. */
274                 if (try_handle_exception_fixup(hw_tf))
275                         return TRUE;
276                 print_trapframe(hw_tf);
277                 backtrace_hwtf(hw_tf);
278                 panic("Proc-less Page Fault in the Kernel at %p!", fault_va);
279         }
280         /* TODO - handle kernel page faults.  This is dangerous, since we might be
281          * holding locks in the kernel and could deadlock when we HPF.  For now, I'm
282          * just disabling the lock checker, since it'll flip out when it sees there
283          * is a kernel trap.  Will need to think about this a bit, esp when we
284          * properly handle bad addrs and whatnot. */
285         pcpui->__lock_checking_enabled--;
286         /* It is a bug for the kernel to access user memory while holding locks that
287          * are used by handle_page_fault.  At a minimum, this includes p->vmr_lock
288          * and memory allocation locks.
289          *
290          * In an effort to reduce the number of locks (both now and in the future),
291          * the kernel will not attempt to handle faults on file-back VMRs.  We
292          * probably can turn that on in the future, but I'd rather keep things safe
293          * for now.  (We'll probably need to change this when we stop
294          * MAP_POPULATE | MAP_LOCKED entire binaries).
295          *
296          * Note that we do not enable IRQs here, unlike in the user case.  Again,
297          * this is to limit the locks we could be grabbing. */
298         err = handle_page_fault_nofile(pcpui->cur_proc, fault_va, prot);
299         pcpui->__lock_checking_enabled++;
300         if (err) {
301                 if (try_handle_exception_fixup(hw_tf))
302                         return TRUE;
303                 print_trapframe(hw_tf);
304                 backtrace_hwtf(hw_tf);
305                 /* Turn this on to help debug bad function pointers */
306                 printd("rsp %p\n\t 0(rsp): %p\n\t 8(rsp): %p\n\t 16(rsp): %p\n"
307                        "\t24(rsp): %p\n", hw_tf->tf_rsp,
308                        *(uintptr_t*)(hw_tf->tf_rsp +  0),
309                        *(uintptr_t*)(hw_tf->tf_rsp +  8),
310                        *(uintptr_t*)(hw_tf->tf_rsp + 16),
311                        *(uintptr_t*)(hw_tf->tf_rsp + 24));
312                 panic("Proc-ful Page Fault in the Kernel at %p!", fault_va);
313                 /* if we want to do something like kill a process or other code, be
314                  * aware we are in a sort of irq-like context, meaning the main
315                  * kernel code we 'interrupted' could be holding locks - even
316                  * irqsave locks. */
317         }
318         return TRUE;
319 }
320
321 static bool __handle_page_fault(struct hw_trapframe *hw_tf, unsigned long *aux)
322 {
323         uintptr_t fault_va = rcr2();
324         int prot = hw_tf->tf_err & PF_ERROR_WRITE ? PROT_WRITE : PROT_READ;
325
326         *aux = fault_va;
327         if (in_kernel(hw_tf))
328                 return __handler_kernel_page_fault(hw_tf, fault_va, prot);
329         else
330                 return __handler_user_page_fault(hw_tf, fault_va, prot);
331 }
332
333 /* Actual body of work done when an NMI arrives */
334 static void do_nmi_work(struct hw_trapframe *hw_tf)
335 {
336         /* TODO: this is all racy and needs to go */
337         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
338         char *fn_name;
339         /* This is a bit hacky, but we don't have a decent API yet */
340         extern bool mon_verbose_trace;
341
342         /* Temporarily disable deadlock detection when we print.  We could
343          * deadlock if we were printing when we NMIed. */
344         pcpui->__lock_checking_enabled--;
345         if (mon_verbose_trace) {
346                 print_trapframe(hw_tf);
347                 backtrace_hwtf(hw_tf);
348         }
349         fn_name = get_fn_name(get_hwtf_pc(hw_tf));
350         printk("Core %d is at %p (%s)\n", core_id(), get_hwtf_pc(hw_tf),
351                fn_name);
352         kfree(fn_name);
353         print_kmsgs(core_id());
354         pcpui->__lock_checking_enabled++;
355 }
356
357 /* NMI HW_TF hacking involves four symbols:
358  *
359  * [__nmi_pop_ok_start, __nmi_pop_ok_end) mark the beginning and end of the
360  * code for an nmi popping routine that will actually pop at the end.
361  *
362  * [__nmi_pop_fail_start, __nmi_pop_fail_end) mark the beginning and end of the
363  * shadow code for an nmi popping routine that will fail at the end.
364  *
365  * If we see a TF in the OK section, we'll move it to the FAIL section.  If it's
366  * already in the FAIL section, we'll report that as a success. */
367 extern char __nmi_pop_ok_start[], __nmi_pop_ok_end[];
368 extern char __nmi_pop_fail_start[], __nmi_pop_fail_end[];
369
370 static bool nmi_hw_tf_needs_hacked(struct hw_trapframe *hw_tf)
371 {
372         return ((uintptr_t)__nmi_pop_ok_start <= hw_tf->tf_rip) &&
373                (hw_tf->tf_rip < (uintptr_t)__nmi_pop_ok_end);
374 }
375
376 static bool nmi_hw_tf_was_hacked(struct hw_trapframe *hw_tf)
377 {
378         return ((uintptr_t)__nmi_pop_fail_start <= hw_tf->tf_rip) &&
379                (hw_tf->tf_rip < (uintptr_t)__nmi_pop_fail_end);
380 }
381
382 /* Helper.  Hacks the TF if it was in the OK section so that it is at the same
383  * spot in the FAIL section.  Returns TRUE if the TF is hacked, meaning the NMI
384  * handler can just return. */
385 static bool nmi_check_and_hack_tf(struct hw_trapframe *hw_tf)
386 {
387         uintptr_t offset;
388
389         if (!nmi_hw_tf_needs_hacked(hw_tf))
390                 return FALSE;
391         if (nmi_hw_tf_was_hacked(hw_tf))
392                 return TRUE;
393         offset = hw_tf->tf_rip - (uintptr_t)__nmi_pop_ok_start;
394         hw_tf->tf_rip = (uintptr_t)__nmi_pop_fail_start + offset;
395         return TRUE;
396 }
397
398 /* Bottom half of the NMI handler.  This can be interrupted under some
399  * circumstances by NMIs.  It exits by popping the hw_tf in assembly. */
400 void __attribute__((noinline, noreturn))
401 __nmi_bottom_half(struct hw_trapframe *hw_tf)
402 {
403         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
404
405         while (1) {
406                 /* Signal that we're doing work.  A concurrent NMI will set this to
407                  * NMI_HANDLE_ANOTHER if we should continue, which we'll catch later. */
408                 pcpui->nmi_status = NMI_IN_PROGRESS;
409                 do_nmi_work(hw_tf);
410                 /* We need to check nmi_status to see if it is NMI_HANDLE_ANOTHER (if
411                  * so, run again), write NMI_NORMAL_OPN, leave this stack, and return to
412                  * the original context.  We need to do that in such a manner that an
413                  * NMI can come in at any time.  There are two concerns.
414                  *
415                  * First, we need to not "miss the signal" telling us to re-run the NMI
416                  * handler.  To do that, we'll do the actual checking in asm.  Being in
417                  * the asm code block is a signal to the real NMI handler that we need
418                  * to abort and do_nmi_work() again.
419                  *
420                  * Second, we need to atomically leave the stack and return.  By being
421                  * in asm, the NMI handler knows to just hack our PC to make us return,
422                  * instead of starting up a fresh __nmi_bottom_half().
423                  *
424                  * The NMI handler works together with the following function such that
425                  * if that race occurs while we're in the function, it'll fail and
426                  * return.  Then we'll just do_nmi_work() and try again. */
427                 extern void nmi_try_to_pop(struct hw_trapframe *tf, int *status,
428                                            int old_val, int new_val);
429
430                 nmi_try_to_pop(hw_tf, &pcpui->nmi_status, NMI_IN_PROGRESS,
431                                NMI_NORMAL_OPN);
432                 /* Either we returned on our own, since we lost a race with nmi_status
433                  * and didn't write (status = ANOTHER), or we won the race, but an NMI
434                  * handler set the status to ANOTHER and restarted us. */
435                 assert(pcpui->nmi_status != NMI_NORMAL_OPN);
436         }
437 }
438
439 /* Separate handler from traps, since there's too many rules for NMI ctx.
440  *
441  * The general rule is that any writes from NMI context must be very careful.
442  * When talking about reads and writes to per-core data:
443  * - If NMIs write things written by normal kernel contexts, including IRQs and
444  *   traps with IRQs disabled, then you must use atomics on both sides.
445  * - If NMIs write things read by normal contexts, then readers must be careful,
446  *   since the data can change at will.
447  * - If NMIs read things written by normal contexts, don't worry: you're running
448  *   uninterrupted (given x86 NMI caveats).
449  * - We cannot block.  The current kthread thinks its stacktop is different than
450  *   the one we're on.  Just get in and get out.
451  * - If we interrupted a user TF, then we don't need to worry any more than for
452  *   normal traps/IRQs.
453  * - However, we cannot call proc_restartcore.  That could trigger all sorts of
454  *   things, like kthreads blocking.
455  * - Parallel accesses (from other cores) are the same as always.  You just
456  *   can't lock easily.
457  *
458  * Normally, once you're in NMI, other NMIs are blocked until we return.
459  * However, if our NMI handler faults (PF, GPF, breakpoint) due to something
460  * like tracing, the iret from that fault will cancel our NMI protections.  Thus
461  * we need another layer of code to make sure we don't run the NMI handler
462  * concurrently on the same core.  See https://lwn.net/Articles/484932/ for more
463  * info.
464  *
465  * We'll get around the problem by running on yet another NMI stack.  All NMIs
466  * come in on the nmi entry stack (tss->ist1).  While we're on that stack, we
467  * will not be interrupted.  We jump to another stack to do_nmi_work.  That code
468  * can be interrupted, but we are careful to only have one 'thread' running on
469  * that stack at a time.  We do this by carefully hopping off the stack in
470  * assembly, similar to popping user TFs. */
471 void handle_nmi(struct hw_trapframe *hw_tf)
472 {
473         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
474         struct hw_trapframe *hw_tf_copy;
475         uintptr_t worker_stacktop;
476
477         /* At this point, we're an NMI and other NMIs are blocked.  Only once we
478          * hop to the bottom half could that be no longer true.  NMI with NMIs fully
479          * blocked will run without interruption.  For that reason, we don't have to
480          * be careful about any memory accesses or compiler tricks. */
481         if (pcpui->nmi_status == NMI_HANDLE_ANOTHER)
482                 return;
483         if (pcpui->nmi_status == NMI_IN_PROGRESS) {
484                 /* Force the handler to run again.  We don't need to worry about
485                  * concurrent access here.  We're running, they are not.  We cannot
486                  * 'PAUSE' since NMIs are fully blocked.
487                  *
488                  * The asm routine, for its part, does a compare-and-swap, so if we
489                  * happened to interrupt it before it wrote NMI_NORMAL_OPN, it'll
490                  * notice, abort, and not write the status. */
491                 pcpui->nmi_status = NMI_HANDLE_ANOTHER;
492                 return;
493         }
494         assert(pcpui->nmi_status == NMI_NORMAL_OPN);
495         pcpui->nmi_status = NMI_HANDLE_ANOTHER;
496         /* We could be interrupting an NMI that is trying to pop back to a normal
497          * context.  We can tell by looking at its PC.  If it is within the popping
498          * routine, then we interrupted it at this bad time.  We'll hack the TF such
499          * that it will return instead of succeeding. */
500         if (nmi_check_and_hack_tf(hw_tf))
501                 return;
502         /* OK, so we didn't interrupt an NMI that was trying to return.  So we need
503          * to run the bottom half.  We're going to jump stacks, but we also need to
504          * copy the hw_tf.  The existing one will be clobbered by any interrupting
505          * NMIs.
506          *
507          * We also need to save some space on the top of that stack for a pointer to
508          * pcpui and a scratch register, which nmi_try_to_pop() will use.  The
509          * target stack will look like this:
510          *
511          *               +--------------------------+ Page boundary (e.g. 0x6000)
512          *               |   scratch space (rsp)    |
513          *               |       pcpui pointer      |
514          *               |      tf_ss + padding     | HW_TF end
515          *               |          tf_rsp          |
516          *               |            .             |
517          *               |            .             |
518          * RSP ->        |         tf_gsbase        | HW_TF start, hw_tf_copy
519          *               +--------------------------+
520          *               |            .             |
521          *               |            .             |
522          *               |            .             |
523          *               +--------------------------+ Page boundary (e.g. 0x5000)
524          *
525          * __nmi_bottom_half() just picks up using the stack below tf_gsbase.  It'll
526          * push as needed, growing down.  Basically we're just using the space
527          * 'above' the stack as storage. */
528         worker_stacktop = pcpui->nmi_worker_stacktop - 2 * sizeof(uintptr_t);
529         *(uintptr_t*)worker_stacktop = (uintptr_t)pcpui;
530         worker_stacktop = worker_stacktop - sizeof(struct hw_trapframe);
531         hw_tf_copy = (struct hw_trapframe*)worker_stacktop;
532         *hw_tf_copy = *hw_tf;
533         /* Once we head to the bottom half, consider ourselves interruptible (though
534          * it's not until the first time we do_nmi_work()).  We'll never come back
535          * to this stack.  Doing this in asm so we can easily pass an argument.  We
536          * don't need to call (vs jmp), but it helps keep the stack aligned. */
537         asm volatile("mov $0x0, %%rbp;"
538                      "mov %0, %%rsp;"
539                      "call __nmi_bottom_half;"
540                      : : "r"(worker_stacktop), "D"(hw_tf_copy));
541         assert(0);
542 }
543
544 /* Certain traps want IRQs enabled, such as the syscall.  Others can't handle
545  * it, like the page fault handler.  Turn them on on a case-by-case basis. */
546 static void trap_dispatch(struct hw_trapframe *hw_tf)
547 {
548         struct per_cpu_info *pcpui;
549         bool handled = TRUE;
550         unsigned long aux = 0;
551         uintptr_t fixup_ip;
552
553         // Handle processor exceptions.
554         switch(hw_tf->tf_trapno) {
555                 case T_BRKPT:
556                         enable_irq();
557                         monitor(hw_tf);
558                         disable_irq();
559                         break;
560                 case T_ILLOP:
561                 {
562                         /* TODO: this can PF if there is a concurrent unmap/PM removal. */
563                         uintptr_t ip = get_hwtf_pc(hw_tf);
564                         pcpui = &per_cpu_info[core_id()];
565                         pcpui->__lock_checking_enabled--;               /* for print debugging */
566                         /* We will muck with the actual TF.  If we're dealing with
567                          * userspace, we need to make sure we edit the actual TF that will
568                          * get restarted (pcpui), and not the TF on the kstack (which aren't
569                          * the same).  See set_current_ctx() for more info. */
570                         if (!in_kernel(hw_tf))
571                                 hw_tf = &pcpui->cur_ctx->tf.hw_tf;
572                         printd("bad opcode, eip: %p, next 3 bytes: %x %x %x\n", ip,
573                                *(uint8_t*)(ip + 0),
574                                *(uint8_t*)(ip + 1),
575                                *(uint8_t*)(ip + 2));
576                         /* rdtscp: 0f 01 f9 */
577                         if (*(uint8_t*)(ip + 0) == 0x0f,
578                             *(uint8_t*)(ip + 1) == 0x01,
579                             *(uint8_t*)(ip + 2) == 0xf9) {
580                                 x86_fake_rdtscp(hw_tf);
581                                 pcpui->__lock_checking_enabled++;       /* for print debugging */
582                                 return;
583                         }
584                         enable_irq();
585                         monitor(hw_tf);
586                         disable_irq();
587                         pcpui->__lock_checking_enabled++;               /* for print debugging */
588                         break;
589                 }
590                 case T_PGFLT:
591                         handled = __handle_page_fault(hw_tf, &aux);
592                         break;
593                 case T_FPERR:
594                         handled = try_handle_exception_fixup(hw_tf);
595                         if (!handled)
596                                 handle_fperr(hw_tf);
597                         break;
598                 case T_SYSCALL:
599                         enable_irq();
600                         // check for userspace, for now
601                         assert(hw_tf->tf_cs != GD_KT);
602                         /* Set up and run the async calls */
603                         /* TODO: this is using the wrong reg1 for traps for 32 bit */
604                         prep_syscalls(current,
605                                       (struct syscall*)x86_get_systrap_arg0(hw_tf),
606                                                   (unsigned int)x86_get_systrap_arg1(hw_tf));
607                         disable_irq();
608                         break;
609                 default:
610                         if (hw_tf->tf_cs == GD_KT) {
611                                 handled = try_handle_exception_fixup(hw_tf);
612                                 if (!handled) {
613                                         print_trapframe(hw_tf);
614                                         panic("Damn Damn!  Unhandled trap in the kernel!");
615                                 }
616                         } else {
617                                 handled = FALSE;
618                         }
619         }
620
621         if (!handled)
622                 reflect_unhandled_trap(hw_tf->tf_trapno, hw_tf->tf_err, aux);
623 }
624
625 /* Helper.  For now, this copies out the TF to pcpui.  Eventually, we should
626  * consider doing this in trapentry.S
627  *
628  * TODO: consider having this return the tf used, so we can set tf in trap and
629  * irq handlers to edit the TF that will get restarted.  Right now, the kernel
630  * uses and restarts tf, but userspace restarts the old pcpui tf.  It is
631  * tempting to do this, but note that tf stays on the stack of the kthread,
632  * while pcpui->cur_ctx is for the core we trapped in on.  Meaning if we ever
633  * block, suddenly cur_ctx is pointing to some old clobbered state that was
634  * already returned to and can't be trusted.  Meanwhile tf can always be trusted
635  * (like with an in_kernel() check).  The only types of traps from the user that
636  * can be expected to have editable trapframes are ones that don't block. */
637 static void set_current_ctx_hw(struct per_cpu_info *pcpui,
638                                struct hw_trapframe *hw_tf)
639 {
640         assert(!irq_is_enabled());
641         pcpui->actual_ctx.type = ROS_HW_CTX;
642         pcpui->actual_ctx.tf.hw_tf = *hw_tf;
643         pcpui->cur_ctx = &pcpui->actual_ctx;
644 }
645
646 static void set_current_ctx_sw(struct per_cpu_info *pcpui,
647                                struct sw_trapframe *sw_tf)
648 {
649         assert(!irq_is_enabled());
650         pcpui->actual_ctx.type = ROS_SW_CTX;
651         pcpui->actual_ctx.tf.sw_tf = *sw_tf;
652         pcpui->cur_ctx = &pcpui->actual_ctx;
653 }
654
655 static void set_current_ctx_vm(struct per_cpu_info *pcpui,
656                                struct vm_trapframe *vm_tf)
657 {
658         assert(!irq_is_enabled());
659         pcpui->actual_ctx.type = ROS_VM_CTX;
660         pcpui->actual_ctx.tf.vm_tf = *vm_tf;
661         pcpui->cur_ctx = &pcpui->actual_ctx;
662 }
663
664 void trap(struct hw_trapframe *hw_tf)
665 {
666         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
667         /* Copy out the TF for now */
668         if (!in_kernel(hw_tf)) {
669                 set_current_ctx_hw(pcpui, hw_tf);
670                 /* ignoring state for nested kernel traps.  should be rare. */
671                 __set_cpu_state(pcpui, CPU_STATE_KERNEL);
672         } else {
673                 inc_ktrap_depth(pcpui);
674         }
675         printd("Incoming TRAP %d on core %d, TF at %p\n", hw_tf->tf_trapno,
676                core_id(), hw_tf);
677         if ((hw_tf->tf_cs & ~3) != GD_UT && (hw_tf->tf_cs & ~3) != GD_KT) {
678                 print_trapframe(hw_tf);
679                 panic("Trapframe with invalid CS!");
680         }
681         trap_dispatch(hw_tf);
682         /* Return to the current process, which should be runnable.  If we're the
683          * kernel, we should just return naturally.  Note that current and tf need
684          * to still be okay (might not be after blocking) */
685         if (in_kernel(hw_tf)) {
686                 dec_ktrap_depth(pcpui);
687                 return;
688         }
689         proc_restartcore();
690         assert(0);
691 }
692
693 static bool vector_is_irq(int apic_vec)
694 {
695         /* arguably, we could limit them to MaxIdtIOAPIC */
696         return (IdtPIC <= apic_vec) && (apic_vec <= IdtMAX);
697 }
698
699 static void irq_dispatch(struct hw_trapframe *hw_tf)
700 {
701         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
702         struct irq_handler *irq_h;
703
704         if (!in_irq_ctx(pcpui))
705                 __set_cpu_state(pcpui, CPU_STATE_IRQ);
706         inc_irq_depth(pcpui);
707         //if (core_id())
708         if (hw_tf->tf_trapno != IdtLAPIC_TIMER) /* timer irq */
709         if (hw_tf->tf_trapno != I_KERNEL_MSG)
710         if (hw_tf->tf_trapno != 65)     /* qemu serial tends to get this one */
711                 printd("Incoming IRQ, ISR: %d on core %d\n", hw_tf->tf_trapno,
712                        core_id());
713         /* TODO: RCU read lock */
714         irq_h = irq_handlers[hw_tf->tf_trapno];
715         if (!irq_h) {
716                 warn_once("Received IRQ %d, had no handler registered!",
717                           hw_tf->tf_trapno);
718                 /* If we don't have an IRQ handler, we don't know how to EOI.  Odds are,
719                  * it's a LAPIC IRQ, such as I_TESTING */
720                 if (!lapic_check_spurious(hw_tf->tf_trapno))
721                         lapic_send_eoi(hw_tf->tf_trapno);
722                 goto out_no_eoi;
723         }
724         if (irq_h->check_spurious(hw_tf->tf_trapno))
725                 goto out_no_eoi;
726         /* Can now be interrupted/nested by higher priority IRQs, but not by our
727          * current IRQ vector, til we EOI. */
728         enable_irq();
729         while (irq_h) {
730                 irq_h->isr(hw_tf, irq_h->data);
731                 irq_h = irq_h->next;
732         }
733         // if we're a general purpose IPI function call, down the cpu_list
734         extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
735         if ((I_SMP_CALL0 <= hw_tf->tf_trapno) &&
736             (hw_tf->tf_trapno <= I_SMP_CALL_LAST))
737                 down_checklist(handler_wrappers[hw_tf->tf_trapno & 0x0f].cpu_list);
738         disable_irq();
739         /* Keep in sync with ipi_is_pending */
740         irq_handlers[hw_tf->tf_trapno]->eoi(hw_tf->tf_trapno);
741         /* Fall-through */
742 out_no_eoi:
743         dec_irq_depth(pcpui);
744         if (!in_irq_ctx(pcpui))
745                 __set_cpu_state(pcpui, CPU_STATE_KERNEL);
746 }
747
748 /* Note IRQs are disabled unless explicitly turned on.
749  *
750  * In general, we should only get trapno's >= PIC1_OFFSET (32).  Anything else
751  * should be a trap.  Even if we don't use the PIC, that should be the standard.
752  * It is possible to get a spurious LAPIC IRQ with vector 15 (or similar), but
753  * the spurious check should catch that.
754  *
755  * Note that from hardware's perspective (PIC, etc), IRQs start from 0, but they
756  * are all mapped up at PIC1_OFFSET for the cpu / irq_handler. */
757 void handle_irq(struct hw_trapframe *hw_tf)
758 {
759         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
760
761         /* Copy out the TF for now */
762         if (!in_kernel(hw_tf))
763                 set_current_ctx_hw(pcpui, hw_tf);
764         irq_dispatch(hw_tf);
765         /* Return to the current process, which should be runnable.  If we're the
766          * kernel, we should just return naturally.  Note that current and tf need
767          * to still be okay (might not be after blocking) */
768         if (in_kernel(hw_tf))
769                 return;
770         proc_restartcore();
771         assert(0);
772 }
773
774 /* The irq field may be ignored based on the type of Bus. */
775 int register_irq(int irq, isr_t handler, void *irq_arg, uint32_t tbdf)
776 {
777         struct irq_handler *irq_h;
778         int vector;
779         irq_h = kzmalloc(sizeof(struct irq_handler), 0);
780         assert(irq_h);
781         irq_h->dev_irq = irq;
782         irq_h->tbdf = tbdf;
783         vector = bus_irq_setup(irq_h);
784         if (vector == -1) {
785                 kfree(irq_h);
786                 return -1;
787         }
788         printk("IRQ %d, vector %d (0x%x), type %s\n", irq, vector, vector,
789                irq_h->type);
790         assert(irq_h->check_spurious && irq_h->eoi);
791         irq_h->isr = handler;
792         irq_h->data = irq_arg;
793         irq_h->apic_vector = vector;
794         /* RCU write lock */
795         spin_lock_irqsave(&irq_handler_wlock);
796         irq_h->next = irq_handlers[vector];
797         wmb();  /* make sure irq_h is done before publishing to readers */
798         irq_handlers[vector] = irq_h;
799         spin_unlock_irqsave(&irq_handler_wlock);
800         /* Most IRQs other than the BusIPI should need their irq unmasked.
801          * Might need to pass the irq_h, in case unmask needs more info.
802          * The lapic IRQs need to be unmasked on a per-core basis */
803         if (irq_h->unmask && strcmp(irq_h->type, "lapic"))
804                 irq_h->unmask(irq_h, vector);
805         return 0;
806 }
807
808 /* These routing functions only allow the routing of an irq to a single core.
809  * If we want to route to multiple cores, we'll probably need to set up logical
810  * groups or something and take some additional parameters. */
811 static int route_irq_h(struct irq_handler *irq_h, int os_coreid)
812 {
813         int hw_coreid;
814         if (!irq_h->route_irq) {
815                 printk("[kernel] apic_vec %d, type %s cannot be routed\n",
816                        irq_h->apic_vector, irq_h->type);
817                 return -1;
818         }
819         if (os_coreid >= MAX_NUM_CORES) {
820                 printk("[kernel] os_coreid %d out of range!\n", os_coreid);
821                 return -1;
822         }
823         hw_coreid = get_hw_coreid(os_coreid);
824         if (hw_coreid == -1) {
825                 printk("[kernel] os_coreid %d not a valid hw core!\n", os_coreid);
826                 return -1;
827         }
828         irq_h->route_irq(irq_h, irq_h->apic_vector, hw_coreid);
829         return 0;
830 }
831
832 /* Routes all irqs for a given apic_vector to os_coreid.  Returns 0 if all of
833  * them succeeded.  -1 if there were none or if any of them failed.  We don't
834  * share IRQs often (if ever anymore), so this shouldn't be an issue. */
835 int route_irqs(int apic_vec, int os_coreid)
836 {
837         struct irq_handler *irq_h;
838         int ret = -1;
839         if (!vector_is_irq(apic_vec)) {
840                 printk("[kernel] vector %d is not an IRQ vector!\n", apic_vec);
841                 return -1;
842         }
843         irq_h = irq_handlers[apic_vec];
844         while (irq_h) {
845                 assert(irq_h->apic_vector == apic_vec);
846                 ret = route_irq_h(irq_h, os_coreid);
847                 irq_h = irq_h->next;
848         }
849         return ret;
850 }
851
852 /* It's a moderate pain in the ass to put these in bit-specific files (header
853  * hell with the set_current_ helpers) */
854 void sysenter_callwrapper(struct syscall *sysc, unsigned long count,
855                           struct sw_trapframe *sw_tf)
856 {
857         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
858         set_current_ctx_sw(pcpui, sw_tf);
859         __set_cpu_state(pcpui, CPU_STATE_KERNEL);
860         /* Once we've set_current_ctx, we can enable interrupts.  This used to be
861          * mandatory (we had immediate KMSGs that would muck with cur_ctx).  Now it
862          * should only help for sanity/debugging. */
863         enable_irq();
864         /* Set up and run the async calls.  This may block, and we could migrate to
865          * another core.  If you use pcpui again, you need to reread it. */
866         prep_syscalls(current, sysc, count);
867         disable_irq();
868         proc_restartcore();
869 }
870
871 /* Declared in x86/arch.h */
872 void send_ipi(uint32_t os_coreid, uint8_t vector)
873 {
874         int hw_coreid = get_hw_coreid(os_coreid);
875         if (hw_coreid == -1) {
876                 panic("Unmapped OS coreid (OS %d)!\n", os_coreid);
877                 return;
878         }
879         assert(vector != T_NMI);
880         __send_ipi(hw_coreid, vector);
881 }
882
883 /****************** VM exit handling ******************/
884
885 static bool handle_vmexit_cpuid(struct vm_trapframe *tf)
886 {
887         uint32_t eax, ebx, ecx, edx;
888
889         /* 0x4000000 is taken from Linux; it is not documented but it signals the
890          * use of KVM. */
891         if (tf->tf_rax == 0x40000000) {
892                 /* Pretend to be KVM: Return the KVM signature by placing the following
893                  * constants in RAX, RBX, RCX and RDX. RAX is set to 0, while RBX to
894                  * RDX forms the string "KVMKVMKVMKVM\0\0\0". This can be placed in
895                  * 0x100 offsets from 0x40000000 to 0x40010000. */
896                 eax = 0;
897                 ebx = 0x4b4d564b;
898                 ecx = 0x564b4d56;
899                 edx = 0x0000004d;
900         } else {
901                 cpuid(tf->tf_rax, tf->tf_rcx, &eax, &ebx, &ecx, &edx);
902                 if (tf->tf_rax == 1) {
903                         /* Set the hypervisor bit to let the guest know it is virtualized */
904                         ecx |= 1 << 31;
905                 }
906         }
907         tf->tf_rax = eax;
908         tf->tf_rbx = ebx;
909         tf->tf_rcx = ecx;
910         tf->tf_rdx = edx;
911         tf->tf_rip += 2;
912         return TRUE;
913 }
914
915 static bool handle_vmexit_ept_fault(struct vm_trapframe *tf)
916 {
917         int prot = 0;
918         int ret;
919
920         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_READ ? PROT_READ : 0;
921         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_WRITE ? PROT_WRITE : 0;
922         prot |= tf->tf_exit_qual & VMX_EPT_FAULT_INS ? PROT_EXEC : 0;
923         ret = handle_page_fault(current, tf->tf_guest_pa, prot);
924         if (ret) {
925                 /* TODO: maybe put ret in the TF somewhere */
926                 return FALSE;
927         }
928         return TRUE;
929 }
930
931 static bool handle_vmexit_nmi(struct vm_trapframe *tf)
932 {
933         /* Sanity checks, make sure we really got an NMI.  Feel free to remove. */
934         assert((tf->tf_intrinfo2 & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR);
935         assert((tf->tf_intrinfo2 & INTR_INFO_VECTOR_MASK) == T_NMI);
936         /* our NMI handler from trap.c won't run.  but we don't need the lock
937          * disabling stuff. */
938         extern bool mon_verbose_trace;
939
940         if (mon_verbose_trace) {
941                 print_vmtrapframe(tf);
942                 /* TODO: a backtrace of the guest would be nice here. */
943         }
944         printk("Core %d is at %p\n", core_id(), get_vmtf_pc(tf));
945         return TRUE;
946 }
947
948 bool handle_vmexit_msr(struct vm_trapframe *tf)
949 {
950         bool ret;
951
952         ret = vmm_emulate_msr(&tf->tf_rcx, &tf->tf_rdx, &tf->tf_rax,
953                               (tf->tf_exit_reason == EXIT_REASON_MSR_READ
954                                                    ? VMM_MSR_EMU_READ : VMM_MSR_EMU_WRITE));
955         if (ret)
956                 tf->tf_rip += 2;
957         return ret;
958 }
959
960 bool handle_vmexit_extirq(struct vm_trapframe *tf)
961 {
962         struct hw_trapframe hw_tf;
963
964         /* For now, we just handle external IRQs.  I think guest traps should go to
965          * the guest, based on our vmctls */
966         assert((tf->tf_intrinfo2 & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_EXT_INTR);
967         /* TODO: Our IRQ handlers all expect TFs.  Let's fake one.  A bunch of
968          * handlers (e.g. backtrace/perf) will probably be unhappy about a user TF
969          * that is really a VM, so this all needs work. */
970         hw_tf.tf_gsbase = 0;
971         hw_tf.tf_fsbase = 0;
972         hw_tf.tf_rax = tf->tf_rax;
973         hw_tf.tf_rbx = tf->tf_rbx;
974         hw_tf.tf_rcx = tf->tf_rcx;
975         hw_tf.tf_rdx = tf->tf_rdx;
976         hw_tf.tf_rbp = tf->tf_rbp;
977         hw_tf.tf_rsi = tf->tf_rsi;
978         hw_tf.tf_rdi = tf->tf_rdi;
979         hw_tf.tf_r8 = tf->tf_r8;
980         hw_tf.tf_r9 = tf->tf_r9;
981         hw_tf.tf_r10 = tf->tf_r10;
982         hw_tf.tf_r11 = tf->tf_r11;
983         hw_tf.tf_r12 = tf->tf_r12;
984         hw_tf.tf_r13 = tf->tf_r13;
985         hw_tf.tf_r14 = tf->tf_r14;
986         hw_tf.tf_r15 = tf->tf_r15;
987         hw_tf.tf_trapno = tf->tf_intrinfo2 & INTR_INFO_VECTOR_MASK;
988         hw_tf.tf_err = 0;
989         hw_tf.tf_rip = tf->tf_rip;
990         hw_tf.tf_cs = GD_UT;    /* faking a user TF, even though it's a VM */
991         hw_tf.tf_rflags = tf->tf_rflags;
992         hw_tf.tf_rsp = tf->tf_rsp;
993         hw_tf.tf_ss = GD_UD;
994
995         irq_dispatch(&hw_tf);
996         /* Consider returning whether or not there was a handler registered */
997         return TRUE;
998 }
999
1000 static bool handle_vmexit_xsetbv(struct vm_trapframe *tf)
1001 {
1002         // The VM's requested-feature bitmap is represented by edx:eax
1003         uint64_t vm_rfbm = (tf->tf_rdx << 32) | tf->tf_rax;
1004
1005         // If the VM tries to set xcr0 to a superset
1006         // of Akaros's default value, kill the VM.
1007
1008         // Bit in vm_rfbm and x86_default_xcr0:        Ok. Requested and allowed.
1009         // Bit in vm_rfbm but not x86_default_xcr0:    Bad! Requested, not allowed.
1010         // Bit not in vm_rfbm but in x86_default_xcr0: Ok. Not requested.
1011
1012         // vm_rfbm & (~x86_default_xcr0) is nonzero if any bits
1013         // are set in vm_rfbm but not x86_default_xcr0
1014
1015         if (vm_rfbm & (~__proc_global_info.x86_default_xcr0))
1016                 return FALSE;
1017
1018
1019         // If attempting to use vm_rfbm for xsetbv
1020         // causes a fault, we reflect to the VMM.
1021         if (safe_lxcr0(vm_rfbm))
1022                 return FALSE;
1023
1024
1025         // If no fault, advance the instruction pointer
1026         // and return TRUE to make the VM resume.
1027         tf->tf_rip += 3; // XSETBV is a 3-byte instruction
1028         return TRUE;
1029 }
1030
1031 static void vmexit_dispatch(struct vm_trapframe *tf)
1032 {
1033         bool handled = FALSE;
1034
1035         /* Do not block in any of these functions.
1036          *
1037          * If we block, we'll probably need to finalize the context.  If we do, then
1038          * there's a chance the guest pcore can start somewhere else, and then we
1039          * can't get the GPC loaded again.  Plus, they could be running a GPC with
1040          * an unresolved vmexit.  It's just mess.
1041          *
1042          * If we want to enable IRQs, we can do so on a case-by-case basis.  Don't
1043          * do it for external IRQs - the irq_dispatch code will handle it. */
1044         switch (tf->tf_exit_reason) {
1045         case EXIT_REASON_VMCALL:
1046                 if (current->vmm.flags & VMM_VMCALL_PRINTF) {
1047                         printk("%c", tf->tf_rdi);
1048                         tf->tf_rip += 3;
1049                         handled = TRUE;
1050                 }
1051                 break;
1052         case EXIT_REASON_CPUID:
1053                 handled = handle_vmexit_cpuid(tf);
1054                 break;
1055         case EXIT_REASON_EPT_VIOLATION:
1056                 handled = handle_vmexit_ept_fault(tf);
1057                 break;
1058         case EXIT_REASON_EXCEPTION_NMI:
1059                 handled = handle_vmexit_nmi(tf);
1060                 break;
1061         case EXIT_REASON_MSR_READ:
1062         case EXIT_REASON_MSR_WRITE:
1063                 handled = handle_vmexit_msr(tf);
1064                 break;
1065         case EXIT_REASON_EXTERNAL_INTERRUPT:
1066                 handled = handle_vmexit_extirq(tf);
1067                 break;
1068         case EXIT_REASON_XSETBV:
1069                 handled = handle_vmexit_xsetbv(tf);
1070                 break;
1071         default:
1072                 printd("Unhandled vmexit: reason 0x%x, exit qualification 0x%x\n",
1073                        tf->tf_exit_reason, tf->tf_exit_qual);
1074         }
1075         if (!handled) {
1076                 tf->tf_flags |= VMCTX_FL_HAS_FAULT;
1077                 if (reflect_current_context()) {
1078                         /* VM contexts shouldn't be in vcore context, so this should be
1079                          * pretty rare (unlike SCPs or VC ctx page faults). */
1080                         printk("[kernel] Unable to reflect VM Exit\n");
1081                         print_vmtrapframe(tf);
1082                         proc_destroy(current);
1083                 }
1084         }
1085 }
1086
1087 void handle_vmexit(struct vm_trapframe *tf)
1088 {
1089         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
1090
1091         tf->tf_rip = vmcs_read(GUEST_RIP);
1092         tf->tf_rflags = vmcs_read(GUEST_RFLAGS);
1093         tf->tf_rsp = vmcs_read(GUEST_RSP);
1094         tf->tf_cr2 = rcr2();
1095         tf->tf_cr3 = vmcs_read(GUEST_CR3);
1096         tf->tf_guest_pcoreid = pcpui->guest_pcoreid;
1097         tf->tf_flags |= VMCTX_FL_PARTIAL;
1098         tf->tf_guest_intr_status = vmcs_read(GUEST_INTR_STATUS);
1099         tf->tf_exit_reason = vmcs_read(VM_EXIT_REASON);
1100         tf->tf_exit_qual = vmcs_read(EXIT_QUALIFICATION);
1101         tf->tf_intrinfo1 = vmcs_read(GUEST_INTERRUPTIBILITY_INFO);
1102         tf->tf_intrinfo2 = vmcs_read(VM_EXIT_INTR_INFO);
1103         tf->tf_guest_va = vmcs_read(GUEST_LINEAR_ADDRESS);
1104         tf->tf_guest_pa = vmcs_read(GUEST_PHYSICAL_ADDRESS);
1105
1106         set_current_ctx_vm(pcpui, tf);
1107         tf = &pcpui->cur_ctx->tf.vm_tf;
1108         vmexit_dispatch(tf);
1109         /* We're either restarting a partial VM ctx (vmcs was launched, loaded on
1110          * the core, etc) or a SW vc ctx for the reflected trap.  Or the proc is
1111          * dying and we'll handle a __death KMSG shortly. */
1112         proc_restartcore();
1113 }
1114
1115 void x86_finalize_vmtf(struct vm_trapframe *tf)
1116 {
1117         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
1118
1119         x86_vmtf_clear_partial(tf);
1120         unload_guest_pcore(pcpui->cur_proc, pcpui->guest_pcoreid);
1121 }