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