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