2cfb56a14b79527ca538c2dba809f6551c70701a
[barrelfish] / kernel / arch / x86_64 / syscall.c
1 /**
2  * \file
3  * \brief System calls implementation.
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <kernel.h>
16 #include <kcb.h>
17 #include <syscall.h>
18 #include <barrelfish_kpi/syscalls.h>
19 #include <mdb/mdb.h>
20 #include <dispatch.h>
21 #include <paging_kernel_arch.h>
22 #include <paging_generic.h>
23 #include <exec.h>
24 #include <arch/x86/x86.h>
25 #include <arch/x86/apic.h>
26 #include <arch/x86/global.h>
27 #include <arch/x86/perfmon.h>
28 #include <vmkit.h>
29 #include <barrelfish_kpi/sys_debug.h>
30 #include <barrelfish_kpi/lmp.h>
31 #include <barrelfish_kpi/dispatcher_shared_target.h>
32 #include <arch/x86/debugregs.h>
33 #include <trace/trace.h>
34 #include <arch/x86/syscall.h>
35 #include <arch/x86/timing.h>
36 #include <fpu.h>
37 #include <arch/x86/ipi_notify.h>
38
39 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
40
41 extern uint64_t user_stack_save;
42
43 /* FIXME: lots of missing argument checks in this function */
44 static struct sysret handle_dispatcher_setup(struct capability *to,
45                                              int cmd, uintptr_t *args)
46 {
47     capaddr_t cptr = args[0];
48     int depth    = args[1];
49     capaddr_t vptr = args[2];
50     capaddr_t dptr = args[3];
51     bool run = args[4];
52     capaddr_t odptr = args[5];
53
54     return sys_dispatcher_setup(to, cptr, depth, vptr, dptr, run, odptr);
55 }
56
57 static struct sysret handle_dispatcher_properties(struct capability *to,
58                                                   int cmd, uintptr_t *args)
59 {
60     enum task_type type = args[0];
61     unsigned long deadline = args[1];
62     unsigned long wcet = args[2];
63     unsigned long period = args[3];
64     unsigned long release = args[4];
65     unsigned short weight = args[5];
66
67     return sys_dispatcher_properties(to, type, deadline, wcet, period,
68                                      release, weight);
69 }
70
71 static struct sysret handle_retype_common(struct capability *root,
72                                           uintptr_t *args,
73                                           bool from_monitor)
74 {
75     uint64_t source_cptr     = args[0];
76     uint64_t type            = args[1];
77     uint64_t objbits         = args[2];
78     uint64_t  dest_cnode_cptr = args[3];
79     uint64_t dest_slot       = args[4];
80     uint64_t dest_vbits      = args[5];
81
82     return sys_retype(root, source_cptr, type, objbits, dest_cnode_cptr,
83                       dest_slot, dest_vbits, from_monitor);
84 }
85
86 static struct sysret handle_retype(struct capability *root,
87                                    int cmd, uintptr_t *args)
88 {
89     return handle_retype_common(root, args, false);
90 }
91
92 static struct sysret handle_create(struct capability *root,
93                                    int cmd, uintptr_t *args)
94 {
95     /* Retrieve arguments */
96     enum objtype type         = args[0];
97     uint8_t objbits           = args[1];
98     capaddr_t dest_cnode_cptr = args[2];
99     cslot_t dest_slot         = args[3];
100     uint8_t dest_vbits        = args[4];
101
102     return sys_create(root, type, objbits, dest_cnode_cptr, dest_slot,
103                       dest_vbits);
104 }
105
106
107 /**
108  * Common code for copying and minting except the mint flag and param passing
109  */
110 static struct sysret copy_or_mint(struct capability *root,
111                                   uintptr_t *args, bool mint)
112 {
113     /* Retrive arguments */
114     capaddr_t  destcn_cptr   = args[0];
115     uint64_t dest_slot     = args[1];
116     capaddr_t  source_cptr   = args[2];
117     int      destcn_vbits  = args[3];
118     int      source_vbits  = args[4];
119     uint64_t param1, param2;
120     // params only sent if mint operation
121     if (mint) {
122         param1 = args[5];
123         param2 = args[6];
124     } else {
125         param1 = param2 = 0;
126     }
127
128     return sys_copy_or_mint(root, destcn_cptr, dest_slot, source_cptr,
129                             destcn_vbits, source_vbits, param1, param2, mint);
130 }
131
132 static struct sysret handle_map(struct capability *ptable,
133                                 int cmd, uintptr_t *args)
134 {
135     /* Retrieve arguments */
136     uint64_t  slot          = args[0];
137     capaddr_t source_cptr   = args[1];
138     int       source_vbits  = args[2];
139     uint64_t  flags         = args[3];
140     uint64_t  offset        = args[4];
141     uint64_t  pte_count     = args[5];
142
143     return sys_map(ptable, slot, source_cptr, source_vbits, flags, offset,
144                    pte_count);
145 }
146
147 static struct sysret handle_mint(struct capability *root,
148                                  int cmd, uintptr_t *args)
149 {
150     return copy_or_mint(root, args, true);
151 }
152
153 static struct sysret handle_copy(struct capability *root,
154                                  int cmd, uintptr_t *args)
155 {
156     return copy_or_mint(root, args, false);
157 }
158
159 static struct sysret handle_delete_common(struct capability *root,
160                                    uintptr_t *args,
161                                    bool from_monitor)
162 {
163     capaddr_t cptr = args[0];
164     int bits     = args[1];
165     return sys_delete(root, cptr, bits, from_monitor);
166 }
167
168 static struct sysret handle_delete(struct capability *root,
169                                    int cmd, uintptr_t *args)
170 {
171     return handle_delete_common(root, args, false);
172 }
173
174
175 static struct sysret handle_revoke_common(struct capability *root,
176                                           uintptr_t *args,
177                                           bool from_monitor)
178 {
179     capaddr_t cptr = args[0];
180     int bits     = args[1];
181     return sys_revoke(root, cptr, bits, from_monitor);
182 }
183
184 static struct sysret handle_revoke(struct capability *root,
185                                    int cmd, uintptr_t *args)
186 {
187     return handle_revoke_common(root, args, false);
188 }
189
190
191 static struct sysret handle_unmap(struct capability *pgtable,
192                                   int cmd, uintptr_t *args)
193 {
194     capaddr_t cptr = args[0];
195     int bits       = args[1];
196     size_t entry   = args[2];
197     size_t pages   = args[3];
198
199     errval_t err;
200     struct cte *mapping;
201     err = caps_lookup_slot(&dcb_current->cspace.cap, cptr, bits,
202                                     &mapping, CAPRIGHTS_READ_WRITE);
203     if (err_is_fail(err)) {
204         return SYSRET(err_push(err, SYS_ERR_CAP_NOT_FOUND));
205     }
206
207     err = page_mappings_unmap(pgtable, mapping, entry, pages);
208     return SYSRET(err);
209 }
210
211 /// Different handler for cap operations performed by the monitor
212 static struct sysret monitor_handle_retype(struct capability *kernel_cap,
213                                            int cmd, uintptr_t *args)
214 {
215     errval_t err;
216
217     capaddr_t root_caddr = args[0];
218     capaddr_t root_vbits = args[1];
219
220     struct capability *root;
221     err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
222                           &root, CAPRIGHTS_READ);
223     if (err_is_fail(err)) {
224         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
225     }
226
227     /* XXX: this hides the first two arguments */
228     return handle_retype_common(root, &args[2], true);
229 }
230
231 /// Different handler for cap operations performed by the monitor
232 static struct sysret monitor_handle_delete(struct capability *kernel_cap,
233                                            int cmd, uintptr_t *args)
234 {
235     errval_t err;
236
237     capaddr_t root_caddr = args[0];
238     capaddr_t root_vbits = args[1];
239
240     struct capability *root;
241     err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
242                           &root, CAPRIGHTS_READ);
243     if (err_is_fail(err)) {
244         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
245     }
246
247     /* XXX: this hides the first two arguments */
248     return handle_delete_common(root, &args[2], true);
249 }
250
251 /// Different handler for cap operations performed by the monitor
252 static struct sysret monitor_handle_revoke(struct capability *kernel_cap,
253                                            int cmd, uintptr_t *args)
254 {
255     errval_t err;
256
257     capaddr_t root_caddr = args[0];
258     capaddr_t root_vbits = args[1];
259
260     struct capability *root;
261     err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
262                           &root, CAPRIGHTS_READ);
263     if (err_is_fail(err)) {
264         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
265     }
266
267     /* XXX: this hides the first two arguments */
268     return handle_revoke_common(root, &args[2], true);
269 }
270
271 static struct sysret monitor_handle_register(struct capability *kernel_cap,
272                                              int cmd, uintptr_t *args)
273 {
274     capaddr_t ep_caddr = args[0];
275     return sys_monitor_register(ep_caddr);
276 }
277
278 /**
279  * \brief Spawn a new core and create a kernel cap for it.
280  */
281 static struct sysret monitor_spawn_core(struct capability *kernel_cap,
282                                         int cmd, uintptr_t *args)
283 {
284     coreid_t core_id       = args[0];
285     enum cpu_type cpu_type = args[1];
286     genvaddr_t entry       = args[2];
287
288     return sys_monitor_spawn_core(core_id, cpu_type, entry);
289 }
290
291 static inline void __monitor(const void *eax, unsigned long ecx,
292                  unsigned long edx)
293 {
294     /* "monitor %eax, %ecx, %edx;" */
295     __asm__ __volatile__ (".byte 0x0f, 0x01, 0xc8;"
296                           :: "a" (eax), "c" (ecx), "d"(edx));
297 }
298
299 static inline void __mwait(unsigned long eax, unsigned long ecx)
300 {
301     /* "mwait %eax, %ecx;" */
302     __asm__ __volatile__ (".byte 0x0f, 0x01, 0xc9;"
303                           :: "a" (eax), "c" (ecx));
304 }
305
306 /**
307  * \brief Request to stop the current core
308  */
309 #include "startup.h"
310 #include <barrelfish_kpi/init.h>
311 #define CNODE(cte)     (cte)->cap.u.cnode.cnode
312 static struct sysret monitor_stop_core(struct capability *kernel_cap,
313                                        int cmd, uintptr_t *args)
314 {
315     printk(LOG_ERR, "monitor_stop_core id=%d\n", my_core_id);
316
317     /*extern struct spawn_state spawn_state;
318     struct cte *urpc_frame_cte = caps_locate_slot(CNODE(spawn_state.taskcn),
319                                                   TASKCN_SLOT_MON_URPC);
320     int  err = paging_x86_64_map_memory(urpc_frame_cte->cap.u.frame.base, 4096);
321     assert (err == 0);
322     lpaddr_t urpc_ptr = local_phys_to_mem(urpc_frame_cte->cap.u.frame.base);
323     printf("%s:%s:%d: waiting on urpc 0x%"PRIxGENPADDR" 0x%"PRIxLPADDR"\n",
324            __FILE__, __FUNCTION__, __LINE__, urpc_frame_cte->cap.u.frame.base, urpc_ptr);*/
325
326     printf("%s:%s:%d: before monitor...\n", __FILE__, __FUNCTION__, __LINE__);
327     //apic_mask_timer();
328     //apic_disable();
329
330     //dcb_current->disabled = false;
331
332     global->wait[0] = 0x1;
333     if (has_monitor_mwait()) {
334         printf("%s:%s:%d: before monitor/mwait\n", __FILE__, __FUNCTION__, __LINE__);
335         monitor_mwait((lvaddr_t)&(global->wait[0]), 0x1, 0, 0);
336     }
337     else {
338         printf("%s:%s:%d: before halt \n", __FILE__, __FUNCTION__, __LINE__);
339
340         halt();
341     }
342
343     printf("%s:%s:%d: woken up again...\n", __FILE__, __FUNCTION__, __LINE__);
344     /**
345      * This means we reenable on an IRQ an jump in irq handler
346      * in irq.c, after that we segfault in the kernel
347      */
348     //__asm__ __volatile__ ("sti");
349     //halt();
350
351     return (struct sysret){.error = SYS_ERR_OK, .value = my_core_id};
352 }
353
354 static struct sysret kernel_start_core(struct capability *kernel_cap,
355                                        int cmd, uintptr_t *args)
356 {
357     printf("%s:%s:%d %"PRIu64"\n", __FILE__, __FUNCTION__, __LINE__, global->wait[0]);
358     global->wait[0] = 0x0;
359     return (struct sysret){.error = SYS_ERR_OK, .value = 0x0};
360 }
361
362 static struct sysret kernel_add_kcb(struct capability *kern_cap,
363                                     int cmd, uintptr_t *args)
364 {
365     uint64_t kcb_addr = args[0];
366
367     struct kcb *new_kcb = (struct kcb *)kcb_addr;
368     if (kcb_current->next) {
369         assert(kcb_current->prev);
370         new_kcb->next = kcb_current->next;
371         new_kcb->prev = kcb_current;
372         new_kcb->next->prev = new_kcb;
373         new_kcb->prev->next = new_kcb;
374     } else {
375         kcb_current->next = kcb_current->prev = new_kcb;
376         new_kcb->next = new_kcb->prev = kcb_current;
377     }
378     // update kernel_now offset
379     new_kcb->kernel_off -= kernel_now;
380     // reset scheduler statistics
381     scheduler_reset_time();
382     // update current core id of all domains
383     kcb_update_core_id(new_kcb);
384     // upcall domains with registered interrupts to tell them to reregister
385     irq_table_notify_domains(new_kcb);
386
387     printk(LOG_NOTE, "kcb_current = %p\n", kcb_current);
388
389     return SYSRET(SYS_ERR_OK);
390 }
391
392 static struct sysret kernel_remove_kcb(struct capability *kern_cap,
393                                        int cmd, uintptr_t *args)
394 {
395     printk(LOG_NOTE, "in kernel_remove_kcb invocation!\n");
396     uint64_t kcb_addr = args[0];
397
398     struct kcb *to_remove = (struct kcb *)kcb_addr;
399
400     return SYSRET(kcb_remove(to_remove));
401 }
402
403 static struct sysret kernel_suspend_kcb_sched(struct capability *kern_cap,
404                                               int cmd, uintptr_t *args)
405 {
406     printk(LOG_NOTE, "in kernel_suspend_kcb_sched invocation!\n");
407     kcb_sched_suspended = (bool)args[0];
408     return SYSRET(SYS_ERR_OK);
409 }
410
411
412 static struct sysret monitor_get_core_id(struct capability *kernel_cap,
413                                          int cmd, uintptr_t *args)
414 {
415     return (struct sysret){.error = SYS_ERR_OK, .value = my_core_id};
416 }
417
418 static struct sysret monitor_get_arch_id(struct capability *kernel_cap,
419                                          int cmd, uintptr_t *args)
420 {
421     return (struct sysret){.error = SYS_ERR_OK, .value = apic_id};
422 }
423
424 static struct sysret monitor_identify_cap_common(struct capability *kernel_cap,
425                                                  struct capability *root,
426                                                  uintptr_t *args)
427 {
428     capaddr_t cptr = args[0];
429     uint8_t bits = args[1];
430     struct capability *retbuf = (void *)args[2];
431
432     return sys_monitor_identify_cap(root, cptr, bits, retbuf);
433 }
434
435 static struct sysret monitor_identify_cap(struct capability *kernel_cap,
436                                           int cmd, uintptr_t *args)
437 {
438     return monitor_identify_cap_common(kernel_cap, &dcb_current->cspace.cap, args);
439 }
440
441 static struct sysret monitor_identify_domains_cap(struct capability *kernel_cap,
442                                                   int cmd, uintptr_t *args)
443 {
444     errval_t err;
445
446     capaddr_t root_caddr = args[0];
447     capaddr_t root_vbits = args[1];
448
449     struct capability *root;
450     err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
451                           &root, CAPRIGHTS_READ);
452
453     if (err_is_fail(err)) {
454         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
455     }
456
457     /* XXX: this hides the first two arguments */
458     return monitor_identify_cap_common(kernel_cap, root, &args[2]);
459 }
460
461 static struct sysret monitor_remote_cap(struct capability *kernel_cap,
462                                         int cmd, uintptr_t *args)
463 {
464     struct capability *root = &dcb_current->cspace.cap;
465     capaddr_t cptr = args[0];
466     int bits = args[1];
467     bool remote = args[2];
468
469     struct cte *cte;
470     errval_t err = caps_lookup_slot(root, cptr, bits, &cte, CAPRIGHTS_WRITE);
471     if (err_is_fail(err)) {
472         return SYSRET(err_push(err, SYS_ERR_IDENTIFY_LOOKUP));
473     }
474
475     set_cap_remote(cte, remote);
476     bool has_desc = has_descendants(cte);
477
478     return (struct sysret){ .error = SYS_ERR_OK, .value = has_desc };
479 }
480
481
482 static struct sysret monitor_create_cap(struct capability *kernel_cap,
483                                         int cmd, uintptr_t *args)
484 {
485     /* XXX: Get the raw metadata of the capability to create */
486     struct capability *src = (struct capability *)args;
487     int pos = sizeof(struct capability) / sizeof(uint64_t);
488
489     /* Certain types cannot be created here */
490     if ((src->type == ObjType_Null) || (src->type == ObjType_EndPoint)
491         || (src->type == ObjType_Dispatcher) || (src->type == ObjType_Kernel)
492         || (src->type == ObjType_IRQTable)) {
493         return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
494     }
495
496     /* Create the cap in the destination */
497     capaddr_t cnode_cptr = args[pos];
498     int cnode_vbits    = args[pos + 1];
499     size_t slot        = args[pos + 2];
500
501     return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
502                                             cnode_cptr, cnode_vbits,
503                                             slot, src));
504 }
505
506 static struct sysret monitor_nullify_cap(struct capability *kernel_cap,
507                                          int cmd, uintptr_t *args)
508 {
509     capaddr_t cptr = args[0];
510     uint8_t bits = args[1];
511
512     return sys_monitor_nullify_cap(cptr, bits);
513 }
514
515 static struct sysret monitor_iden_cnode_get_cap(struct capability *kern_cap,
516                                                 int cmd, uintptr_t *args)
517 {
518     errval_t err;
519
520     /* XXX: Get the raw metadata of the cnode */
521     int pos = sizeof(struct capability) / sizeof(uint64_t);
522     struct capability *cnode = (struct capability *)args;
523     assert(cnode->type == ObjType_CNode);
524
525     struct capability *cnode_copy;
526     err = mdb_get_copy(cnode, &cnode_copy);
527     if (err_is_fail(err)) {
528         return SYSRET(err);
529     }
530
531     capaddr_t slot = args[pos];
532     struct cte* cte = caps_locate_slot(cnode_copy->u.cnode.cnode, slot);
533
534     // XXX: Write cap data directly back to user-space
535     // FIXME: this should involve a pointer/range check for reliability,
536     // but because the monitor is inherently trusted it's not a security hole
537     struct capability *retbuf = (void *)args[pos + 1];
538     *retbuf = cte->cap;
539
540     return SYSRET(SYS_ERR_OK);
541 }
542
543 static struct sysret monitor_handle_sync_timer(struct capability *kern_cap,
544                                                int cmd, uintptr_t *args)
545 {
546     uint64_t synctime = args[0];
547     return sys_monitor_handle_sync_timer(synctime);
548 }
549
550
551 static struct sysret handle_frame_identify(struct capability *to,
552                                            int cmd, uintptr_t *args)
553 {
554     // Return with physical base address of frame
555     // XXX: pack size into bottom bits of base address
556     assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame);
557     assert((to->u.frame.base & BASE_PAGE_MASK) == 0);
558     return (struct sysret) {
559         .error = SYS_ERR_OK,
560         .value = to->u.frame.base | to->u.frame.bits,
561     };
562 }
563
564 static struct sysret handle_frame_modify_flags(struct capability *to,
565                                                int cmd, uintptr_t *args)
566 {
567     // Modify flags of (part of) mapped region of frame
568     assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame);
569
570     // unpack arguments
571     size_t offset = args[0]; // in pages; of first page to modify from first
572                              // page in mapped region
573     size_t pages  = args[1]; // #pages to modify
574     size_t flags  = args[2]; // new flags
575
576     page_mappings_modify_flags(to, offset, pages, flags);
577
578     return (struct sysret) {
579         .error = SYS_ERR_OK,
580         .value = 0,
581     };
582 }
583
584 static struct sysret handle_kcb_identify(struct capability *to,
585                                          int cmd, uintptr_t *args)
586 {
587     // Return with physical base address of frame
588     // XXX: pack size into bottom bits of base address
589     assert(to->type == ObjType_KernelControlBlock);
590     lvaddr_t vkcb = (lvaddr_t) to->u.kernelcontrolblock.kcb;
591     assert((vkcb & BASE_PAGE_MASK) == 0);
592     return (struct sysret) {
593         .error = SYS_ERR_OK,
594         .value = mem_to_local_phys(vkcb) | OBJBITS_KCB,
595     };
596 }
597
598
599
600 static struct sysret handle_io(struct capability *to, int cmd, uintptr_t *args)
601 {
602     uint64_t    port = args[0];
603     uint64_t    data = args[1]; // ignored for input
604
605     return sys_io(to, cmd, port, data);
606 }
607
608 static struct sysret
609 handle_dispatcher_setup_guest (struct capability *to, int cmd, uintptr_t *args)
610 {
611     errval_t err;
612     struct dcb *dcb = to->u.dispatcher.dcb;
613
614     capaddr_t epp = args[0];
615     capaddr_t vnodep = args[1];
616     capaddr_t vmcbp = args[2];
617     capaddr_t ctrlp = args[3];
618
619     // 0. Enable VM extensions
620     err = vmkit_enable_virtualization();
621     if(err != SYS_ERR_OK) {
622         return SYSRET(err);
623     }
624
625     // 1. Check arguments
626     // Monitor endpoint for exits of this geust
627     struct cte *ep_cte;
628
629     err = caps_lookup_slot(&dcb_current->cspace.cap, epp, CPTR_BITS,
630                            &ep_cte, CAPRIGHTS_READ_WRITE);
631     if (err_is_fail(err)) {
632         return SYSRET(err);
633     }
634     if (ep_cte->cap.type != ObjType_EndPoint) {
635         return SYSRET(SYS_ERR_VMKIT_ENDPOINT_INVALID);
636     }
637     err = caps_copy_to_cte(&dcb->guest_desc.monitor_ep, ep_cte, false, 0, 0);
638     if (err_is_fail(err)) {
639         return SYSRET(err_push(err, SYS_ERR_VMKIT_ENDPOINT));
640     }
641
642     // Domain vspace
643     struct capability *vnode_cap;
644     err = caps_lookup_cap(&dcb_current->cspace.cap, vnodep, CPTR_BITS,
645                           &vnode_cap, CAPRIGHTS_WRITE);
646     if (err_is_fail(err)) {
647         return SYSRET(err);
648     }
649     if (vnode_cap->type != ObjType_VNode_x86_64_pml4) {
650         return SYSRET(SYS_ERR_DISP_VSPACE_INVALID);
651     }
652
653     assert(vnode_cap->type == ObjType_VNode_x86_64_pml4);
654
655     // VMCB
656     struct cte *vmcb_cte;
657     err = caps_lookup_slot(&dcb_current->cspace.cap, vmcbp, CPTR_BITS,
658                            &vmcb_cte, CAPRIGHTS_READ_WRITE);
659     if (err_is_fail(err)) {
660         return SYSRET(err);
661     }
662     if (vmcb_cte->cap.type != ObjType_Frame ||
663         vmcb_cte->cap.u.frame.bits < BASE_PAGE_BITS) {
664         return SYSRET(SYS_ERR_VMKIT_VMCB_INVALID);
665     }
666     err = caps_copy_to_cte(&dcb->guest_desc.vmcb, vmcb_cte, false, 0, 0);
667     if (err_is_fail(err)) {
668         return SYSRET(err_push(err, SYS_ERR_VMKIT_VMCB));
669     }
670
671     // guest control
672     struct cte *ctrl_cte;
673     err = caps_lookup_slot(&dcb_current->cspace.cap, ctrlp, CPTR_BITS,
674                            &ctrl_cte, CAPRIGHTS_READ_WRITE);
675     if (err_is_fail(err)) {
676         return SYSRET(err);
677     }
678     if (ctrl_cte->cap.type != ObjType_Frame ||
679         ctrl_cte->cap.u.frame.bits < BASE_PAGE_BITS) {
680         return SYSRET(SYS_ERR_VMKIT_CTRL_INVALID);
681     }
682     err = caps_copy_to_cte(&dcb->guest_desc.ctrl, ctrl_cte, false, 0, 0);
683     if (err_is_fail(err)) {
684         return SYSRET(err_push(err, SYS_ERR_VMKIT_CTRL));
685     }
686
687     // 2. Set up the target DCB
688 /*     dcb->guest_desc.monitor_ep = ep_cap; */
689     dcb->vspace = vnode_cap->u.vnode_x86_64_pml4.base;
690     dcb->is_vm_guest = true;
691 /*     dcb->guest_desc.vmcb = vmcb_cap->u.frame.base; */
692 /*     dcb->guest_desc.ctrl = (void *)x86_64_phys_to_mem(ctrl_cap->u.frame.base); */
693
694     return SYSRET(SYS_ERR_OK);
695 }
696
697 static struct sysret monitor_handle_domain_id(struct capability *monitor_cap,
698                                               int cmd, uintptr_t *args)
699 {
700     capaddr_t cptr = args[0];
701     domainid_t domain_id = args[1];
702
703     return sys_monitor_domain_id(cptr, domain_id);
704 }
705
706 /**
707  * \brief Set up tracing in the kernel
708  */
709 static struct sysret handle_trace_setup(struct capability *cap,
710                                         int cmd, uintptr_t *args)
711 {
712     struct capability *frame;
713     errval_t err;
714
715     /* lookup passed cap */
716     capaddr_t cptr = args[0];
717     err = caps_lookup_cap(&dcb_current->cspace.cap, cptr, CPTR_BITS, &frame,
718                           CAPRIGHTS_READ_WRITE);
719     if (err_is_fail(err)) {
720         return SYSRET(err);
721     }
722
723     lpaddr_t lpaddr = gen_phys_to_local_phys(frame->u.frame.base);
724     kernel_trace_buf = local_phys_to_mem(lpaddr);
725     //printf("kernel.%u: handle_trace_setup at %lx\n", apic_id, kernel_trace_buf);
726
727     // Copy boot applications.
728     trace_copy_boot_applications();
729
730     return SYSRET(SYS_ERR_OK);
731 }
732
733 static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
734                                             uintptr_t *args)
735 {
736     struct sysret ret;
737     int outvec;
738     ret.error = irq_table_alloc(&outvec);
739     ret.value = outvec;
740     return ret;
741 }
742
743
744 static struct sysret handle_irq_table_set(struct capability *to, int cmd,
745                                           uintptr_t *args)
746 {
747     return SYSRET(irq_table_set(args[0], args[1]));
748 }
749
750 static struct sysret handle_irq_table_delete(struct capability *to, int cmd,
751                                              uintptr_t *args)
752 {
753     return SYSRET(irq_table_delete(args[0]));
754 }
755
756 static struct sysret handle_ipi_notify_send(struct capability *cap,
757                                             int cmd, uintptr_t *args)
758 {
759     assert(cap->type == ObjType_Notify_IPI);
760     return ipi_raise_notify(cap->u.notify_ipi.coreid, cap->u.notify_ipi.chanid);
761 }
762
763 static struct sysret kernel_ipi_register(struct capability *cap,
764                                          int cmd, uintptr_t *args)
765 {
766     assert(cap->type == ObjType_Kernel);
767     capaddr_t ep = args[0];
768     int chanid = args[1];
769     return SYSRET(ipi_register_notification(ep, chanid));
770 }
771
772 static struct sysret kernel_ipi_delete(struct capability *cap,
773                                        int cmd, uintptr_t *args)
774 {
775     assert(cap->type == ObjType_Kernel);
776     assert(!"NYI");
777     return SYSRET(SYS_ERR_OK);
778 }
779
780 static struct sysret dispatcher_dump_ptables(struct capability *cap,
781                                              int cmd, uintptr_t *args)
782 {
783     assert(cap->type == ObjType_Dispatcher);
784
785     printf("kernel_dump_ptables\n");
786
787     struct dcb *dispatcher = cap->u.dispatcher.dcb;
788
789     paging_dump_tables(dispatcher);
790
791     return SYSRET(SYS_ERR_OK);
792 }
793
794 /*
795  * \brief Activate performance monitoring
796  *
797  * Activates performance monitoring.
798  * \param xargs Expected parameters in args:
799  * - performance monitoring type
800  * - mask for given type
801  * - Counter id
802  * - Also count in privileged mode
803  * - Number of counts before overflow. This parameter may be used to
804  *   set tradeoff between accuracy and overhead. Set the counter to 0
805  *   to deactivate the usage of APIC.
806  * - Endpoint capability to be invoked when the counter overflows.
807  *   The buffer associated with the endpoint needs to be large enough
808  *   to hold several overflow notifications depending on the overflow
809  *   frequency.
810  */
811 static struct sysret performance_counter_activate(struct capability *cap,
812                                                   int cmd, uintptr_t *args)
813 {
814     uint8_t event = args[0];
815     uint8_t umask = args[1];
816     uint8_t counter_id = args[2];
817     bool kernel = args[3];
818     uint64_t counter_value = args[4];
819     capaddr_t ep_addr = args[5];
820
821     errval_t err;
822     struct capability *ep;
823     extern struct capability perfmon_callback_ep;
824
825     // Make sure that
826     assert(ep_addr!=0 || counter_value==0);
827
828     perfmon_init();
829     perfmon_measure_start(event, umask, counter_id, kernel, counter_value);
830
831     if(ep_addr!=0) {
832
833         err = caps_lookup_cap(&dcb_current->cspace.cap, ep_addr, CPTR_BITS, &ep,
834                                CAPRIGHTS_READ);
835         if(err_is_fail(err)) {
836             return SYSRET(err);
837         }
838
839         perfmon_callback_ep = *ep;
840     }
841
842     return SYSRET(SYS_ERR_OK);
843 }
844
845 /*
846  * \brief Write counter values.
847  */
848 static struct sysret performance_counter_write(struct capability *cap,
849                                                int cmd, uintptr_t *args)
850 {
851     uint8_t counter_id = args[0];
852     uint64_t counter_value = args[1];
853
854     perfmon_measure_write(counter_id, counter_value);
855     return SYSRET(SYS_ERR_OK);
856 }
857
858 /*
859  * \brief Deactivate performance counters again.
860  */
861 static struct sysret performance_counter_deactivate(struct capability *cap,
862                                                   int cmd, uintptr_t *args)
863 {
864     perfmon_measure_stop();
865     return SYSRET(SYS_ERR_OK);
866 }
867
868 /*
869  * \brief Return system-wide unique ID of this ID cap.
870  */
871 static struct sysret handle_idcap_identify(struct capability *cap, int cmd,
872                                            uintptr_t *args)
873 {
874     idcap_id_t id;
875     struct sysret sysret = sys_idcap_identify(cap, &id);
876     sysret.value = id;
877
878     return sysret;
879 }
880
881 static struct sysret kernel_send_init_ipi(struct capability *cap, int cmd,
882                                           uintptr_t *args)
883 {
884     coreid_t destination = args[0];
885     printk(LOG_DEBUG, "%s:%s:%d: destination=%"PRIuCOREID"\n",
886            __FILE__, __FUNCTION__, __LINE__, destination);
887
888     apic_send_init_assert(destination, xapic_none);
889     apic_send_init_deassert();
890
891     return SYSRET(SYS_ERR_OK);
892 }
893
894 static struct sysret kernel_send_start_ipi(struct capability *cap,
895                                            int cmd,
896                                            uintptr_t *args)
897 {
898     coreid_t destination = args[0];
899     genvaddr_t start_vector = X86_64_REAL_MODE_SEGMENT_TO_REAL_MODE_PAGE(X86_64_REAL_MODE_SEGMENT);
900     printk(LOG_DEBUG, "%s:%d: destination=%"PRIuCOREID" start_vector=%"PRIxGENVADDR"\n",
901            __FILE__, __LINE__, destination, start_vector);
902
903     apic_send_start_up(destination, xapic_none, start_vector);
904
905     return SYSRET(SYS_ERR_OK);
906 }
907
908 static struct sysret kernel_get_global_phys(struct capability *cap,
909                                            int cmd,
910                                            uintptr_t *args)
911 {
912
913     struct sysret sysret;
914     sysret.value = mem_to_local_phys((lvaddr_t)global);
915     sysret.error = SYS_ERR_OK;
916
917     return sysret;
918 }
919
920 typedef struct sysret (*invocation_handler_t)(struct capability *to,
921                                               int cmd, uintptr_t *args);
922
923 static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
924     [ObjType_Dispatcher] = {
925         [DispatcherCmd_Setup] = handle_dispatcher_setup,
926         [DispatcherCmd_Properties] = handle_dispatcher_properties,
927         [DispatcherCmd_SetupGuest] = handle_dispatcher_setup_guest,
928         [DispatcherCmd_DumpPTables]  = dispatcher_dump_ptables,
929     },
930     [ObjType_KernelControlBlock] = {
931         [FrameCmd_Identify] = handle_kcb_identify,
932     },
933     [ObjType_Frame] = {
934         [FrameCmd_Identify] = handle_frame_identify,
935         [FrameCmd_ModifyFlags] = handle_frame_modify_flags,
936     },
937     [ObjType_DevFrame] = {
938         [FrameCmd_Identify] = handle_frame_identify,
939         [FrameCmd_ModifyFlags] = handle_frame_modify_flags,
940     },
941     [ObjType_CNode] = {
942         [CNodeCmd_Copy]   = handle_copy,
943         [CNodeCmd_Mint]   = handle_mint,
944         [CNodeCmd_Retype] = handle_retype,
945         [CNodeCmd_Create] = handle_create,
946         [CNodeCmd_Delete] = handle_delete,
947         [CNodeCmd_Revoke] = handle_revoke,
948     },
949     [ObjType_VNode_x86_64_pml4] = {
950         [VNodeCmd_Map]   = handle_map,
951         [VNodeCmd_Unmap] = handle_unmap,
952     },
953     [ObjType_VNode_x86_64_pdpt] = {
954         [VNodeCmd_Map]   = handle_map,
955         [VNodeCmd_Unmap] = handle_unmap,
956     },
957     [ObjType_VNode_x86_64_pdir] = {
958         [VNodeCmd_Map]   = handle_map,
959         [VNodeCmd_Unmap] = handle_unmap,
960     },
961     [ObjType_VNode_x86_64_ptable] = {
962         [VNodeCmd_Map]   = handle_map,
963         [VNodeCmd_Unmap] = handle_unmap,
964     },
965     [ObjType_Kernel] = {
966         [KernelCmd_Stop_core]    = monitor_stop_core,
967         [KernelCmd_Spawn_core]   = monitor_spawn_core,
968         [KernelCmd_Get_core_id]  = monitor_get_core_id,
969         [KernelCmd_Get_arch_id]  = monitor_get_arch_id,
970         [KernelCmd_Identify_cap] = monitor_identify_cap,
971         [KernelCmd_Identify_domains_cap] = monitor_identify_domains_cap,
972         [KernelCmd_Remote_cap]   = monitor_remote_cap,
973         [KernelCmd_Iden_cnode_get_cap] = monitor_iden_cnode_get_cap,
974         [KernelCmd_Create_cap]   = monitor_create_cap,
975         [KernelCmd_Nullify_cap]  = monitor_nullify_cap,
976         [KernelCmd_Setup_trace]  = handle_trace_setup,
977         [KernelCmd_Register]     = monitor_handle_register,
978         [KernelCmd_Domain_Id]    = monitor_handle_domain_id,
979         [MonitorCmd_Retype]      = monitor_handle_retype,
980         [MonitorCmd_Delete]      = monitor_handle_delete,
981         [MonitorCmd_Revoke]      = monitor_handle_revoke,
982         [KernelCmd_Sync_timer]   = monitor_handle_sync_timer,
983         [KernelCmd_IPI_Register] = kernel_ipi_register,
984         [KernelCmd_IPI_Delete]   = kernel_ipi_delete,
985         [KernelCmd_Start_IPI_Send] = kernel_send_start_ipi,
986         [KernelCmd_Init_IPI_Send] = kernel_send_init_ipi,
987         [KernelCmd_GetGlobalPhys] = kernel_get_global_phys,
988         [KernelCmd_StartCore] = kernel_start_core,
989         [KernelCmd_Add_kcb]      = kernel_add_kcb,
990         [KernelCmd_Remove_kcb]   = kernel_remove_kcb,
991         [KernelCmd_Suspend_kcb_sched]   = kernel_suspend_kcb_sched,
992     },
993     [ObjType_IRQTable] = {
994         [IRQTableCmd_Alloc] = handle_irq_table_alloc,
995         [IRQTableCmd_Set] = handle_irq_table_set,
996         [IRQTableCmd_Delete] = handle_irq_table_delete
997     },
998     [ObjType_IO] = {
999         [IOCmd_Outb] = handle_io,
1000         [IOCmd_Outw] = handle_io,
1001         [IOCmd_Outd] = handle_io,
1002         [IOCmd_Inb] = handle_io,
1003         [IOCmd_Inw] = handle_io,
1004         [IOCmd_Ind] = handle_io
1005     },
1006     [ObjType_Notify_IPI] = {
1007         [NotifyCmd_Send] = handle_ipi_notify_send
1008     },
1009     [ObjType_PerfMon] = {
1010         [PerfmonCmd_Activate] = performance_counter_activate,
1011         [PerfmonCmd_Deactivate] = performance_counter_deactivate,
1012         [PerfmonCmd_Write] = performance_counter_write,
1013     },
1014     [ObjType_ID] = {
1015         [IDCmd_Identify] = handle_idcap_identify,
1016     }
1017 };
1018
1019 /* syscall C entry point; called only from entry.S so no prototype in header */
1020 struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
1021                           uint64_t *args, uint64_t rflags, uint64_t rip);
1022 struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
1023                           uint64_t *args, uint64_t rflags, uint64_t rip)
1024 {
1025     struct sysret retval = { .error = SYS_ERR_OK, .value = 0 };
1026
1027     switch(syscall) {
1028     case SYSCALL_INVOKE: /* Handle capability invocation */
1029     {
1030         // unpack "header" word
1031         capaddr_t invoke_cptr = arg0 >> 32;
1032         uint8_t send_bits = arg0 >> 24;
1033         uint8_t invoke_bits = arg0 >> 16;
1034         uint8_t length_words = arg0 >> 8;
1035         uint8_t flags = arg0;
1036
1037         debug(SUBSYS_SYSCALL, "sys_invoke(0x%x(%d), 0x%lx)\n",
1038               invoke_cptr, invoke_bits, arg1);
1039
1040         // Capability to invoke
1041         struct capability *to = NULL;
1042         retval.error = caps_lookup_cap(&dcb_current->cspace.cap, invoke_cptr,
1043                                        invoke_bits, &to, CAPRIGHTS_READ);
1044         if (err_is_fail(retval.error)) {
1045             break;
1046         }
1047
1048         assert(to != NULL);
1049         assert(to->type < ObjType_Num);
1050
1051         // Endpoint cap, do LMP
1052         if (to->type == ObjType_EndPoint) {
1053             struct dcb *listener = to->u.endpoint.listener;
1054             assert(listener != NULL);
1055
1056             if (listener->disp == 0) {
1057                 retval.error = SYS_ERR_LMP_NO_TARGET;
1058                 break;
1059             }
1060
1061             /* limit length of message from buggy/malicious sender */
1062             length_words = MIN(length_words, LMP_MSG_LENGTH);
1063
1064             // does the sender want to yield their timeslice on success?
1065             bool sync = flags & LMP_FLAG_SYNC;
1066             // does the sender want to yield to the target if undeliverable?
1067             bool yield = flags & LMP_FLAG_YIELD;
1068
1069             // try to deliver message
1070             retval.error = lmp_deliver(to, dcb_current, args, length_words,
1071                                        arg1, send_bits);
1072
1073             /* Switch to reciever upon successful delivery with sync flag,
1074              * or (some cases of) unsuccessful delivery with yield flag */
1075             enum err_code err_code = err_no(retval.error);
1076             if ((sync && err_is_ok(retval.error)) ||
1077                 (yield && (err_code == SYS_ERR_LMP_BUF_OVERFLOW
1078                            || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
1079                            || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
1080                            || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED))
1081                     ) {
1082                 if (err_is_fail(retval.error)) {
1083                     struct dispatcher_shared_generic *current_disp =
1084                         get_dispatcher_shared_generic(dcb_current->disp);
1085                     struct dispatcher_shared_generic *listener_disp =
1086                         get_dispatcher_shared_generic(listener->disp);
1087                     debug(SUBSYS_DISPATCH, "LMP failed; %.*s yields to %.*s: %u\n",
1088                           DISP_NAME_LEN, current_disp->name,
1089                           DISP_NAME_LEN, listener_disp->name, err_code);
1090                 }
1091
1092                 // special-case context switch: ensure correct state in current DCB
1093                 dispatcher_handle_t handle = dcb_current->disp;
1094                 struct dispatcher_shared_x86_64 *disp =
1095                     get_dispatcher_shared_x86_64(handle);
1096                 dcb_current->disabled = dispatcher_is_disabled_ip(handle, rip);
1097                 struct registers_x86_64 *save_area;
1098                 if (dcb_current->disabled) {
1099                     save_area = &disp->disabled_save_area;
1100                 } else {
1101                     save_area = &disp->enabled_save_area;
1102                 }
1103
1104                 // save calling dispatcher's registers, so that when the dispatcher
1105                 // next runs, it has a valid state in the relevant save area.
1106                 // Save RIP, RFLAGS, RSP and set RAX (return value) for later resume
1107                 save_area->rax = retval.error; // XXX: x86 1st return register
1108                 save_area->rip = rip;
1109                 save_area->eflags = rflags;
1110                 save_area->rsp = user_stack_save;
1111
1112                 /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
1113                 __asm ("mov     %%fs, %[fs]     \n\t"
1114                        "mov     %%gs, %[gs]     \n\t"
1115                        "mov     %[zero], %%fs   \n\t"
1116                        "mov     %[zero], %%gs   \n\t"
1117                        : /* No output */
1118                        :
1119                        [fs] "m" (save_area->fs),
1120                        [gs] "m" (save_area->gs),
1121                        [zero] "r" (0)
1122                        );
1123
1124                 dispatch(to->u.endpoint.listener);
1125                 panic("dispatch returned");
1126             }
1127         } else { // not endpoint cap, call kernel handler through dispatch table
1128             uint64_t cmd = args[0];
1129             if (cmd >= CAP_MAX_CMD) {
1130                 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1131                 break;
1132             }
1133
1134             // Call the invocation
1135             invocation_handler_t invocation = invocations[to->type][cmd];
1136             if(invocation == NULL) {
1137                 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1138             } else {
1139                 retval = invocation(to, cmd, &args[1]);
1140             }
1141         }
1142         break;
1143     }
1144
1145         // Yield the CPU to the next dispatcher
1146     case SYSCALL_YIELD:
1147         retval = sys_yield((capaddr_t)arg0);
1148         break;
1149
1150         // NOP system call for benchmarking purposes
1151     case SYSCALL_NOP:
1152         break;
1153
1154         // Debug print system call
1155     case SYSCALL_PRINT:
1156         retval.error = sys_print((char *)arg0, arg1);
1157         break;
1158
1159         // Reboot!
1160         // FIXME: this should be a kernel cap invocation or similarly restricted
1161     case SYSCALL_REBOOT:
1162         reboot();
1163         break;
1164
1165     case SYSCALL_X86_FPU_TRAP_ON:
1166         fpu_trap_on();
1167         break;
1168
1169     case SYSCALL_X86_RELOAD_LDT:
1170         maybe_reload_ldt(dcb_current, true);
1171         break;
1172
1173         // Temporarily suspend the CPU
1174     case SYSCALL_SUSPEND:
1175         retval = sys_suspend((bool)arg0);
1176         break;
1177
1178     case SYSCALL_DEBUG:
1179         switch(arg0) {
1180         case DEBUG_CONTEXT_COUNTER_RESET:
1181             dispatch_csc_reset();
1182             break;
1183
1184         case DEBUG_CONTEXT_COUNTER_READ:
1185             retval.value = dispatch_get_csc();
1186             break;
1187
1188         case DEBUG_TIMESLICE_COUNTER_READ:
1189             retval.value = kernel_now;
1190             break;
1191
1192         case DEBUG_FLUSH_CACHE:
1193             wbinvd();
1194             break;
1195
1196         case DEBUG_SEND_IPI:
1197             apic_send_std_ipi(arg1, args[0], args[1]);
1198             break;
1199
1200         case DEBUG_SET_BREAKPOINT:
1201             debugregs_set_breakpoint(arg1, args[0], args[1]);
1202             break;
1203
1204         case DEBUG_GET_TSC_PER_MS:
1205             retval.value = timing_get_tsc_per_ms();
1206             break;
1207
1208         case DEBUG_GET_APIC_TIMER:
1209             retval.value = apic_timer_get_count();
1210             break;
1211
1212         case DEBUG_GET_APIC_TICKS_PER_SEC:
1213             retval.value = timing_get_apic_ticks_per_sec();
1214             break;
1215
1216         default:
1217             printk(LOG_ERR, "invalid sys_debug msg type\n");
1218         }
1219         break;
1220
1221     default:
1222         printk(LOG_ERR, "sys_syscall: Illegal system call! "
1223                "(0x%lx, 0x%lx, 0x%lx)\n", syscall, arg0, arg1);
1224         retval.error = SYS_ERR_ILLEGAL_SYSCALL;
1225         break;
1226     }
1227
1228     // If dcb_current got removed, dispatch someone else
1229     if (dcb_current == NULL) {
1230         assert(err_is_ok(retval.error));
1231         dispatch(schedule());
1232     }
1233
1234     if (syscall == SYSCALL_INVOKE) {
1235         debug(SUBSYS_SYSCALL, "invoke returning 0x%lx 0x%lx\n",
1236               retval.error, retval.value);
1237     }
1238
1239     return retval;
1240 }