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