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