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