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