3 * \brief System calls implementation.
7 * Copyright (c) 2007, 2008, 2009, 2010, 2012, ETH Zurich.
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.
17 #include <sys_debug.h>
19 #include <barrelfish_kpi/syscalls.h>
21 #include <mdb/mdb_tree.h>
23 #include <paging_kernel_arch.h>
24 #include <paging_generic.h>
27 #include <arch/x86/x86.h>
28 #include <arch/x86/apic.h>
29 #include <arch/x86/global.h>
30 #include <arch/x86/perfmon.h>
31 #include <arch/x86/debugregs.h>
32 #include <arch/x86/syscall.h>
33 #include <arch/x86/timing.h>
34 #include <arch/x86/ipi_notify.h>
35 #include <barrelfish_kpi/sys_debug.h>
36 #include <barrelfish_kpi/lmp.h>
37 #include <barrelfish_kpi/dispatcher_shared_target.h>
38 #include <barrelfish_kpi/platform.h>
39 #include <trace/trace.h>
40 #include <useraccess.h>
43 #include <dev/amd_vmcb_dev.h>
46 #define MIN(a,b) ((a) < (b) ? (a) : (b))
48 extern uint64_t user_stack_save;
50 /* FIXME: lots of missing argument checks in this function */
51 static struct sysret handle_dispatcher_setup(struct capability *to,
52 int cmd, uintptr_t *args)
54 capaddr_t cptr = args[0];
55 uint8_t level = args[1];
56 capaddr_t vptr = args[2] & 0xffffffff;
57 capaddr_t dptr = args[3] & 0xffffffff;
59 capaddr_t odptr = args[5] & 0xffffffff;
61 TRACE(KERNEL, SC_DISP_SETUP, 0);
62 struct sysret sr = sys_dispatcher_setup(to, cptr, level, vptr, dptr, run, odptr);
63 TRACE(KERNEL, SC_DISP_SETUP, 1);
67 static struct sysret handle_dispatcher_properties(struct capability *to,
68 int cmd, uintptr_t *args)
70 enum task_type type = args[0];
71 unsigned long deadline = args[1];
72 unsigned long wcet = args[2];
73 unsigned long period = args[3];
74 unsigned long release = args[4];
75 unsigned short weight = args[5];
77 TRACE(KERNEL, SC_DISP_PROPS, 0);
78 struct sysret sr = sys_dispatcher_properties(to, type, deadline, wcet, period,
80 TRACE(KERNEL, SC_DISP_PROPS, 1);
84 static struct sysret handle_retype_common(struct capability *root,
88 capaddr_t source_croot = args[0] >> 32;
89 capaddr_t source_cptr = args[0] & 0xffffffff;
90 uint64_t offset = args[1];
91 uint64_t type = args[2];
92 uint64_t objsize = args[3];
93 uint64_t objcount = args[4];
94 capaddr_t dest_cspace_cptr= args[5] >> 32;
95 capaddr_t dest_cnode_cptr = args[5] & 0xffffffff;
96 uint64_t dest_slot = args[6];
97 uint64_t dest_cnode_level = args[7];
99 TRACE(KERNEL, SC_RETYPE, 0);
100 struct sysret sr = sys_retype(root, source_croot, source_cptr, offset, type,
101 objsize, objcount, dest_cspace_cptr,
102 dest_cnode_cptr, dest_cnode_level,
103 dest_slot, from_monitor);
104 TRACE(KERNEL, SC_RETYPE, 1);
108 static struct sysret handle_retype(struct capability *root,
109 int cmd, uintptr_t *args)
111 return handle_retype_common(root, args, false);
114 static struct sysret handle_create(struct capability *root,
115 int cmd, uintptr_t *args)
117 /* Retrieve arguments */
118 enum objtype type = args[0];
119 size_t objsize = args[1];
120 capaddr_t dest_cnode_cptr = args[2];
121 uint8_t dest_level = args[3];
122 cslot_t dest_slot = args[4];
124 TRACE(KERNEL, SC_CREATE, 0);
125 struct sysret sr = sys_create(root, type, objsize, dest_cnode_cptr,
126 dest_level, dest_slot);
127 TRACE(KERNEL, SC_CREATE, 1);
132 static struct sysret handle_map(struct capability *ptable,
133 int cmd, uintptr_t *args)
135 /* Retrieve arguments */
136 uint64_t slot = args[0];
137 capaddr_t source_root_cptr= args[1] >> 32;
138 capaddr_t source_cptr = args[1] & 0xffffffff;
139 uint8_t source_level = args[2];
140 uint64_t flags = args[3];
141 uint64_t offset = args[4];
142 uint64_t pte_count = args[5];
143 capaddr_t mapping_croot = args[6] >> 32;
144 capaddr_t mapping_cnptr = args[6] & 0xffffffff;
145 uint8_t mapping_cn_level= args[7];
146 cslot_t mapping_slot = args[8];
148 TRACE(KERNEL, SC_MAP, 0);
149 struct sysret sr = sys_map(ptable, slot, source_root_cptr, source_cptr,
150 source_level, flags, offset, pte_count,
151 mapping_croot, mapping_cnptr,
152 mapping_cn_level, mapping_slot);
153 TRACE(KERNEL, SC_MAP, 1);
158 * Common code for copying and minting except the mint flag and param passing
160 static struct sysret copy_or_mint(struct capability *root,
161 uintptr_t *args, bool mint)
163 /* Retrieve arguments */
164 capaddr_t dest_cspace_cptr = args[0];
165 capaddr_t destcn_cptr = args[1];
166 uint64_t dest_slot = args[2];
167 capaddr_t source_croot_ptr = args[3];
168 capaddr_t source_cptr = args[4];
169 uint8_t destcn_level = args[5];
170 uint8_t source_level = args[6];
171 uint64_t param1, param2;
172 // params only sent if mint operation
180 TRACE(KERNEL, SC_COPY_OR_MINT, 0);
181 struct sysret sr = sys_copy_or_mint(root, dest_cspace_cptr, destcn_cptr, dest_slot,
182 source_croot_ptr, source_cptr,
183 destcn_level, source_level,
184 param1, param2, mint);
185 TRACE(KERNEL, SC_COPY_OR_MINT, 1);
189 static struct sysret handle_mint(struct capability *root,
190 int cmd, uintptr_t *args)
192 return copy_or_mint(root, args, true);
195 static struct sysret handle_copy(struct capability *root,
196 int cmd, uintptr_t *args)
198 return copy_or_mint(root, args, false);
201 static struct sysret handle_delete(struct capability *root,
202 int cmd, uintptr_t *args)
204 capaddr_t cptr = args[0];
205 uint8_t level = args[1];
206 return sys_delete(root, cptr, level);
209 static struct sysret handle_revoke(struct capability *root,
210 int cmd, uintptr_t *args)
212 capaddr_t cptr = args[0];
213 uint8_t level = args[1];
214 return sys_revoke(root, cptr, level);
217 static struct sysret handle_get_state(struct capability *root,
218 int cmd, uintptr_t *args)
220 capaddr_t cptr = args[0];
221 uint8_t level = args[1];
222 return sys_get_state(root, cptr, level);
227 static struct sysret handle_cnode_cmd_obsolete(struct capability *root,
228 int cmd, uintptr_t *args)
230 panic("Trying to invoke GPT CNode: command %d", cmd);
231 return SYSRET(LIB_ERR_NOT_IMPLEMENTED);
235 static struct sysret handle_unmap(struct capability *pgtable,
236 int cmd, uintptr_t *args)
238 capaddr_t cptr = args[0];
239 uint8_t level = args[1];
243 err = caps_lookup_slot_2(&dcb_current->cspace.cap, cptr, level,
244 &mapping, CAPRIGHTS_READ_WRITE);
245 if (err_is_fail(err)) {
246 return SYSRET(err_push(err, SYS_ERR_CAP_NOT_FOUND));
249 TRACE(KERNEL, SC_UNMAP, 0);
250 err = page_mappings_unmap(pgtable, mapping);
251 TRACE(KERNEL, SC_UNMAP, 1);
255 static struct sysret handle_mapping_destroy(struct capability *mapping,
256 int cmd, uintptr_t *args)
259 return SYSRET(SYS_ERR_OK);
262 static struct sysret handle_mapping_modify(struct capability *mapping,
263 int cmd, uintptr_t *args)
265 // Modify flags of (part of) mapped region of frame
266 assert(type_is_mapping(mapping->type));
269 size_t offset = args[0]; // in pages; of first page to modify from first
270 // page in mapped region
271 size_t pages = args[1]; // #pages to modify
272 size_t flags = args[2]; // new flags
273 genvaddr_t va = args[3]; // virtual addr hint
275 errval_t err = page_mappings_modify_flags(mapping, offset, pages, flags, va);
277 return (struct sysret) {
283 /// Different handler for cap operations performed by the monitor
284 static struct sysret monitor_handle_retype(struct capability *kernel_cap,
285 int cmd, uintptr_t *args)
289 capaddr_t root_caddr = args[0] & 0xFFFFFFFF;
290 capaddr_t root_level = (args[0] >> 32);
292 struct capability *root;
293 err = caps_lookup_cap_2(&dcb_current->cspace.cap, root_caddr, root_level,
294 &root, CAPRIGHTS_READ);
295 if (err_is_fail(err)) {
296 return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
299 /* This hides the first argument, which is resolved here and passed as 'root' */
300 return handle_retype_common(root, &args[1], true);
303 static struct sysret monitor_handle_has_descendants(struct capability *kernel_cap,
304 int cmd, uintptr_t *args)
306 struct capability *src = (struct capability *)args;
308 struct cte *next = mdb_find_greater(src, false);
310 return (struct sysret) {
312 .value = (next && is_ancestor(&next->cap, src)),
316 static struct sysret monitor_handle_delete_last(struct capability *kernel_cap,
317 int cmd, uintptr_t *args)
319 capaddr_t root_caddr = args[0];
320 uint8_t root_level = args[1];
321 capaddr_t target_caddr = args[2];
322 uint8_t target_level = args[3];
323 capaddr_t retcn_caddr = args[4];
324 uint8_t retcn_level = args[5];
325 cslot_t ret_slot = args[6];
327 return sys_monitor_delete_last(root_caddr, root_level, target_caddr,
328 target_level, retcn_caddr, retcn_level,
332 static struct sysret monitor_handle_delete_foreigns(struct capability *kernel_cap,
333 int cmd, uintptr_t *args)
335 capaddr_t caddr = args[0];
336 uint8_t level = args[1];
337 return sys_monitor_delete_foreigns(caddr, level);
340 static struct sysret monitor_handle_revoke_mark_tgt(struct capability *kernel_cap,
341 int cmd, uintptr_t *args)
343 capaddr_t root_caddr = args[0];
344 uint8_t root_level = args[1];
345 capaddr_t target_caddr = args[2];
346 uint8_t target_level = args[3];
348 return sys_monitor_revoke_mark_tgt(root_caddr, root_level,
349 target_caddr, target_level);
352 static struct sysret monitor_handle_revoke_mark_rels(struct capability *kernel_cap,
353 int cmd, uintptr_t *args)
355 struct capability *base = (struct capability*)args;
357 return sys_monitor_revoke_mark_rels(base);
360 static struct sysret monitor_handle_delete_step(struct capability *kernel_cap,
361 int cmd, uintptr_t *args)
363 capaddr_t ret_cn_addr = args[0];
364 capaddr_t ret_cn_level = args[1];
365 capaddr_t ret_slot = args[2];
367 return sys_monitor_delete_step(ret_cn_addr, ret_cn_level, ret_slot);
370 static struct sysret monitor_handle_clear_step(struct capability *kernel_cap,
371 int cmd, uintptr_t *args)
373 capaddr_t ret_cn_addr = args[0];
374 capaddr_t ret_cn_level = args[1];
375 capaddr_t ret_slot = args[2];
377 return sys_monitor_clear_step(ret_cn_addr, ret_cn_level, ret_slot);
380 static struct sysret monitor_handle_register(struct capability *kernel_cap,
381 int cmd, uintptr_t *args)
383 capaddr_t ep_caddr = args[0];
385 TRACE(KERNEL, SC_MONITOR_REGISTER, 0);
386 struct sysret sr = sys_monitor_register(ep_caddr);
387 TRACE(KERNEL, SC_MONITOR_REGISTER, 1);
391 static struct sysret monitor_get_core_id(struct capability *kernel_cap,
392 int cmd, uintptr_t *args)
394 return (struct sysret){.error = SYS_ERR_OK, .value = my_core_id};
397 static struct sysret monitor_get_arch_id(struct capability *kernel_cap,
398 int cmd, uintptr_t *args)
400 return (struct sysret){.error = SYS_ERR_OK, .value = apic_id};
403 static struct sysret monitor_identify_cap_common(struct capability *kernel_cap,
404 struct capability *root,
407 capaddr_t cptr = args[0];
408 uint8_t level = args[1];
410 struct capability *retbuf = (void *)args[2];
412 return sys_monitor_identify_cap(root, cptr, level, retbuf);
415 static struct sysret monitor_identify_cap(struct capability *kernel_cap,
416 int cmd, uintptr_t *args)
418 return monitor_identify_cap_common(kernel_cap, &dcb_current->cspace.cap, args);
421 static struct sysret monitor_identify_domains_cap(struct capability *kernel_cap,
422 int cmd, uintptr_t *args)
426 capaddr_t root_caddr = args[0];
427 capaddr_t root_level = args[1];
429 struct capability *root;
430 err = caps_lookup_cap_2(&dcb_current->cspace.cap, root_caddr, root_level,
431 &root, CAPRIGHTS_READ);
433 if (err_is_fail(err)) {
434 return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
437 /* XXX: this hides the first two arguments */
438 return monitor_identify_cap_common(kernel_cap, root, &args[2]);
441 static struct sysret monitor_cap_has_relations(struct capability *kernel_cap,
442 int cmd, uintptr_t *args)
444 capaddr_t caddr = args[0];
445 uint8_t level = args[1];
446 uint8_t mask = args[2];
448 return sys_cap_has_relations(caddr, level, mask);
451 static struct sysret monitor_remote_relations(struct capability *kernel_cap,
452 int cmd, uintptr_t *args)
454 capaddr_t root_addr = args[0];
455 int root_level = args[1];
456 capaddr_t cptr = args[2];
458 uint8_t relations = args[4] & 0xFF;
459 uint8_t mask = (args[4] >> 8) & 0xFF;
461 return sys_monitor_remote_relations(root_addr, root_level, cptr, level,
466 static struct sysret monitor_create_cap(struct capability *kernel_cap,
467 int cmd, uintptr_t *args)
469 /* XXX: Get the raw metadata of the capability to create */
470 struct capability *src = (struct capability *)args;
471 int pos = ROUND_UP(sizeof(struct capability), sizeof(uint64_t)) / sizeof(uint64_t);
473 /* Cannot create null caps */
474 if (src->type == ObjType_Null) {
475 return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
478 coreid_t owner = args[pos + 3];
480 /* For certain types, only foreign copies can be created here */
481 if ((src->type == ObjType_EndPoint || src->type == ObjType_Dispatcher
482 || src->type == ObjType_Kernel || src->type == ObjType_IRQTable)
483 && owner == my_core_id)
485 return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
488 /* Create the cap in the destination */
489 capaddr_t cnode_cptr = args[pos];
490 int cnode_level = args[pos + 1];
491 size_t slot = args[pos + 2];
492 assert(cnode_level <= 2);
494 return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
495 cnode_cptr, cnode_level,
499 static struct sysret monitor_copy_existing(struct capability *kernel_cap,
500 int cmd, uintptr_t *args)
502 /* XXX: Get the raw metadata of the capability to create */
503 struct capability *src = (struct capability *)args;
504 int pos = ROUND_UP(sizeof(struct capability), sizeof(uint64_t)) / sizeof(uint64_t);
506 capaddr_t cnode_cptr = args[pos];
507 int cnode_level = args[pos + 1];
508 size_t slot = args[pos + 2];
510 return sys_monitor_copy_existing(src, cnode_cptr, cnode_level, slot);
513 static struct sysret monitor_nullify_cap(struct capability *kernel_cap,
514 int cmd, uintptr_t *args)
516 capaddr_t cptr = args[0];
517 uint8_t level = args[1];
519 return sys_monitor_nullify_cap(cptr, level);
522 static struct sysret monitor_handle_sync_timer(struct capability *kern_cap,
523 int cmd, uintptr_t *args)
525 uint64_t synctime = args[0];
526 return sys_monitor_handle_sync_timer(synctime);
529 static struct sysret monitor_get_platform(struct capability *kern_cap,
530 int cmd, uintptr_t *args)
532 if (!access_ok(ACCESS_WRITE, args[0], sizeof(struct platform_info))) {
533 return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
535 struct platform_info *pi = (struct platform_info *)args[0];
536 // x86: only have PC as platform
537 pi->arch = PI_ARCH_X86;
538 pi->platform = PI_PLATFORM_PC;
539 return SYSRET(SYS_ERR_OK);
542 static struct sysret handle_frame_identify(struct capability *to,
543 int cmd, uintptr_t *args)
545 // Return with physical base address of frame
546 assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame ||
547 to->type == ObjType_RAM);
548 assert((get_address(to) & BASE_PAGE_MASK) == 0);
550 struct frame_identity *fi = (struct frame_identity *)args[0];
552 if (!access_ok(ACCESS_WRITE, (lvaddr_t)fi, sizeof(struct frame_identity))) {
553 return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
556 fi->base = get_address(to);
557 fi->bytes = get_size(to);
559 return SYSRET(SYS_ERR_OK);
562 static struct sysret handle_vnode_identify(struct capability *to,
563 int cmd, uintptr_t *args)
565 // Return with physical base address of the VNode
566 assert(to->type == ObjType_VNode_x86_64_pml4 ||
567 to->type == ObjType_VNode_x86_64_pdpt ||
568 to->type == ObjType_VNode_x86_64_pdir ||
569 to->type == ObjType_VNode_x86_64_ptable);
571 uint64_t base_addr = 0;
573 case ObjType_VNode_x86_64_pml4:
574 base_addr = (uint64_t)(to->u.vnode_x86_64_pml4.base);
576 case ObjType_VNode_x86_64_pdpt:
577 base_addr = (uint64_t)(to->u.vnode_x86_64_pdpt.base);
579 case ObjType_VNode_x86_64_pdir:
580 base_addr = (uint64_t)(to->u.vnode_x86_64_pdir.base);
582 case ObjType_VNode_x86_64_ptable:
583 base_addr = (uint64_t)(to->u.vnode_x86_64_ptable.base);
588 assert((base_addr & BASE_PAGE_MASK) == 0);
590 return (struct sysret) {
592 .value = (genpaddr_t)base_addr | ((uint8_t)to->type),
597 static struct sysret handle_io(struct capability *to, int cmd, uintptr_t *args)
599 uint64_t port = args[0];
600 uint64_t data = args[1]; // ignored for input
602 return sys_io(to, cmd, port, data);
605 static struct sysret handle_vmread(struct capability *to,
606 int cmd, uintptr_t *args)
608 #if defined(__k1om__) || defined(CONFIG_SVM)
609 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
612 struct dcb *dcb = to->u.dispatcher.dcb;
613 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
614 if (vmcs_base != vmptrst()) {
615 err = SYS_ERR_VMKIT_VMX_VMFAIL_INVALID;
617 err = vmread(args[0], (lvaddr_t *)args[1]);
623 static struct sysret handle_vmwrite(struct capability *to,
624 int cmd, uintptr_t *args)
626 #if defined(__k1om__) || defined(CONFIG_SVM)
627 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
630 struct dcb *dcb = to->u.dispatcher.dcb;
631 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
632 if (vmcs_base != vmptrst()) {
633 err = SYS_ERR_VMKIT_VMX_VMFAIL_INVALID;
635 err = vmwrite(args[0], args[1]);
641 static struct sysret handle_vmptrld(struct capability *to,
642 int cmd, uintptr_t *args)
644 #if defined(__k1om__) || defined(CONFIG_SVM)
645 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
648 struct dcb *dcb = to->u.dispatcher.dcb;
649 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
650 err = vmptrld(vmcs_base);
655 static struct sysret handle_vmclear(struct capability *to,
656 int cmd, uintptr_t *args)
658 #if defined(__k1om__) || defined(CONFIG_SVM)
659 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
662 struct dcb *dcb = to->u.dispatcher.dcb;
663 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
664 err = vmclear(vmcs_base);
671 handle_dispatcher_setup_guest (struct capability *to, int cmd, uintptr_t *args)
674 struct dcb *dcb = to->u.dispatcher.dcb;
676 capaddr_t epp = args[0];
677 capaddr_t vnodep = args[1];
678 capaddr_t vmcbp = args[2];
679 capaddr_t ctrlp = args[3];
681 // 0. Enable VM extensions
682 err = vmkit_enable_virtualization();
683 if (err != SYS_ERR_OK) {
687 // 1. Check arguments
688 // Monitor endpoint for exits of this geust
691 err = caps_lookup_slot_2(&dcb_current->cspace.cap, epp, 2,
692 &ep_cte, CAPRIGHTS_READ_WRITE);
693 if (err_is_fail(err)) {
696 if (ep_cte->cap.type != ObjType_EndPoint) {
697 return SYSRET(SYS_ERR_VMKIT_ENDPOINT_INVALID);
699 err = caps_copy_to_cte(&dcb->guest_desc.monitor_ep, ep_cte, false, 0, 0);
700 if (err_is_fail(err)) {
701 return SYSRET(err_push(err, SYS_ERR_VMKIT_ENDPOINT));
705 struct capability *vnode_cap;
706 err = caps_lookup_cap_2(&dcb_current->cspace.cap, vnodep, 2,
707 &vnode_cap, CAPRIGHTS_WRITE);
708 if (err_is_fail(err)) {
711 if (vnode_cap->type != ObjType_VNode_x86_64_pml4) {
712 return SYSRET(SYS_ERR_DISP_VSPACE_INVALID);
715 assert(vnode_cap->type == ObjType_VNode_x86_64_pml4);
718 struct cte *vmcb_cte;
719 err = caps_lookup_slot_2(&dcb_current->cspace.cap, vmcbp, 2,
720 &vmcb_cte, CAPRIGHTS_READ_WRITE);
721 if (err_is_fail(err)) {
724 if (vmcb_cte->cap.type != ObjType_Frame ||
725 vmcb_cte->cap.u.frame.bytes < BASE_PAGE_SIZE) {
726 return SYSRET(SYS_ERR_VMKIT_VMCB_INVALID);
728 err = caps_copy_to_cte(&dcb->guest_desc.vmcb, vmcb_cte, false, 0, 0);
729 if (err_is_fail(err)) {
730 return SYSRET(err_push(err, SYS_ERR_VMKIT_VMCB));
734 struct cte *ctrl_cte;
735 err = caps_lookup_slot_2(&dcb_current->cspace.cap, ctrlp, 2,
736 &ctrl_cte, CAPRIGHTS_READ_WRITE);
737 if (err_is_fail(err)) {
740 if (ctrl_cte->cap.type != ObjType_Frame ||
741 ctrl_cte->cap.u.frame.bytes < BASE_PAGE_SIZE) {
742 return SYSRET(SYS_ERR_VMKIT_CTRL_INVALID);
744 err = caps_copy_to_cte(&dcb->guest_desc.ctrl, ctrl_cte, false, 0, 0);
745 if (err_is_fail(err)) {
746 return SYSRET(err_push(err, SYS_ERR_VMKIT_CTRL));
750 // Initialize VMCS for the single virtual-CPU here instead of in
751 // userspace, where the privilege level is not 0.
752 err = initialize_vmcs(vmcb_cte->cap.u.frame.base);
753 assert(err_is_ok(err));
756 // 2. Set up the target DCB
757 /* dcb->guest_desc.monitor_ep = ep_cap; */
758 dcb->vspace = vnode_cap->u.vnode_x86_64_pml4.base;
759 dcb->is_vm_guest = true;
760 /* dcb->guest_desc.vmcb = vmcb_cap->u.frame.base; */
761 /* dcb->guest_desc.ctrl = (void *)x86_64_phys_to_mem(ctrl_cap->u.frame.base); */
763 return SYSRET(SYS_ERR_OK);
767 static struct sysret monitor_handle_domain_id(struct capability *monitor_cap,
768 int cmd, uintptr_t *args)
770 capaddr_t cptr = args[0];
771 domainid_t domain_id = args[1];
773 return sys_monitor_domain_id(cptr, domain_id);
776 static struct sysret monitor_get_cap_owner(struct capability *monitor_cap,
777 int cmd, uintptr_t *args)
779 capaddr_t root_addr = args[0];
780 uint8_t root_level = args[1];
781 capaddr_t cptr = args[2];
782 uint8_t level = args[3];
784 return sys_get_cap_owner(root_addr, root_level, cptr, level);
787 static struct sysret monitor_set_cap_owner(struct capability *monitor_cap,
788 int cmd, uintptr_t *args)
790 capaddr_t root_addr = args[0];
791 uint8_t root_level = args[1];
792 capaddr_t cptr = args[2];
793 uint8_t level = args[3];
794 coreid_t owner = args[4];
796 return sys_set_cap_owner(root_addr, root_level, cptr, level, owner);
799 static struct sysret monitor_lock_cap(struct capability *monitor_cap,
800 int cmd, uintptr_t *args)
802 capaddr_t root_addr = args[0];
803 uint8_t root_level = args[1];
804 capaddr_t cptr = args[2];
805 uint8_t level = args[3];
807 return sys_lock_cap(root_addr, root_level, cptr, level);
810 static struct sysret monitor_unlock_cap(struct capability *monitor_cap,
811 int cmd, uintptr_t *args)
813 capaddr_t root_addr = args[0];
814 uint8_t root_level = args[1];
815 capaddr_t cptr = args[2];
816 uint8_t level = args[3];
818 return sys_unlock_cap(root_addr, root_level, cptr, level);
822 * \brief Set up tracing in the kernel
824 static struct sysret handle_trace_setup(struct capability *cap,
825 int cmd, uintptr_t *args)
827 struct capability *frame;
830 /* lookup passed cap */
831 capaddr_t cptr = args[0];
832 err = caps_lookup_cap_2(&dcb_current->cspace.cap, cptr, 2, &frame,
833 CAPRIGHTS_READ_WRITE);
834 if (err_is_fail(err)) {
838 lpaddr_t lpaddr = gen_phys_to_local_phys(frame->u.frame.base);
839 kernel_trace_buf = local_phys_to_mem(lpaddr);
840 //printf("kernel.%u: handle_trace_setup at %lx\n", apic_id, kernel_trace_buf);
842 // Copy boot applications.
843 trace_copy_boot_applications();
845 return SYSRET(SYS_ERR_OK);
848 static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
852 ret.error = SYS_ERR_OK;
853 ret.value = to->u.irqsrc.vector;
859 static struct sysret handle_irqdest_get_vector(struct capability *to, int cmd,
863 ret.error = SYS_ERR_OK;
864 ret.value = to->u.irqdest.vector;
868 static struct sysret handle_irqdest_connect(struct capability *to, int cmd,
871 return SYSRET(irq_connect(to, args[0]));
874 static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
879 ret.error = irq_table_alloc(&outvec);
884 static struct sysret handle_irq_table_alloc_dest_cap(struct capability *to, int cmd,
887 return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2]));
891 static struct sysret handle_irq_table_set(struct capability *to, int cmd,
894 return SYSRET(irq_table_set(args[0], args[1]));
897 static struct sysret handle_irq_table_delete(struct capability *to, int cmd,
900 return SYSRET(irq_table_delete(args[0]));
903 static struct sysret handle_ipi_notify_send(struct capability *cap,
904 int cmd, uintptr_t *args)
906 assert(cap->type == ObjType_Notify_IPI);
907 return ipi_raise_notify(cap->u.notify_ipi.coreid, cap->u.notify_ipi.chanid);
910 static struct sysret kernel_ipi_register(struct capability *cap,
911 int cmd, uintptr_t *args)
913 assert(cap->type == ObjType_Kernel);
914 capaddr_t ep = args[0];
915 int chanid = args[1];
916 return SYSRET(ipi_register_notification(ep, chanid));
919 static struct sysret kernel_ipi_delete(struct capability *cap,
920 int cmd, uintptr_t *args)
922 assert(cap->type == ObjType_Kernel);
924 return SYSRET(SYS_ERR_OK);
927 static struct sysret dispatcher_dump_ptables(struct capability *cap,
928 int cmd, uintptr_t *args)
930 assert(cap->type == ObjType_Dispatcher);
932 printf("kernel_dump_ptables\n");
934 struct dcb *dispatcher = cap->u.dispatcher.dcb;
936 paging_dump_tables(dispatcher);
938 return SYSRET(SYS_ERR_OK);
941 static struct sysret dispatcher_dump_capabilities(struct capability *cap,
942 int cmd, uintptr_t *args)
944 assert(cap->type == ObjType_Dispatcher);
946 printf("dispatcher_dump_capabilities\n");
948 struct dcb *dispatcher = cap->u.dispatcher.dcb;
950 errval_t err = debug_print_cababilities(dispatcher);
956 * \brief Activate performance monitoring
958 * Activates performance monitoring.
959 * \param xargs Expected parameters in args:
960 * - performance monitoring type
961 * - mask for given type
963 * - Also count in privileged mode
964 * - Number of counts before overflow. This parameter may be used to
965 * set tradeoff between accuracy and overhead. Set the counter to 0
966 * to deactivate the usage of APIC.
967 * - Endpoint capability to be invoked when the counter overflows.
968 * The buffer associated with the endpoint needs to be large enough
969 * to hold several overflow notifications depending on the overflow
972 static struct sysret performance_counter_activate(struct capability *cap,
973 int cmd, uintptr_t *args)
975 uint8_t event = args[0];
976 uint8_t umask = args[1];
977 uint8_t counter_id = args[2];
978 bool kernel = args[3];
979 uint64_t counter_value = args[4];
980 capaddr_t ep_addr = args[5];
983 struct capability *ep;
984 extern struct capability perfmon_callback_ep;
987 assert(ep_addr!=0 || counter_value==0);
990 perfmon_measure_start(event, umask, counter_id, kernel, counter_value);
994 err = caps_lookup_cap_2(&dcb_current->cspace.cap, ep_addr, 2, &ep,
996 if(err_is_fail(err)) {
1000 perfmon_callback_ep = *ep;
1003 return SYSRET(SYS_ERR_OK);
1007 * \brief Write counter values.
1009 static struct sysret performance_counter_write(struct capability *cap,
1010 int cmd, uintptr_t *args)
1012 uint8_t counter_id = args[0];
1013 uint64_t counter_value = args[1];
1015 perfmon_measure_write(counter_id, counter_value);
1016 return SYSRET(SYS_ERR_OK);
1020 * \brief Deactivate performance counters again.
1022 static struct sysret performance_counter_deactivate(struct capability *cap,
1023 int cmd, uintptr_t *args)
1025 perfmon_measure_stop();
1026 return SYSRET(SYS_ERR_OK);
1030 * \brief Return system-wide unique ID of this ID cap.
1032 static struct sysret handle_idcap_identify(struct capability *cap, int cmd,
1036 struct sysret sysret = sys_idcap_identify(cap, &id);
1042 static struct sysret kernel_send_init_ipi(struct capability *cap, int cmd,
1045 coreid_t destination = args[0];
1046 // printk(LOG_DEBUG, "%s:%s:%d: destination=%"PRIuCOREID"\n",
1047 // __FILE__, __FUNCTION__, __LINE__, destination);
1049 apic_send_init_assert(destination, xapic_none);
1050 apic_send_init_deassert();
1052 return SYSRET(SYS_ERR_OK);
1055 static struct sysret kernel_send_start_ipi(struct capability *cap,
1059 coreid_t destination = args[0];
1060 genvaddr_t start_vector = X86_64_REAL_MODE_SEGMENT_TO_REAL_MODE_PAGE(X86_64_REAL_MODE_SEGMENT);
1061 // printk(LOG_DEBUG, "%s:%d: destination=%"PRIuCOREID" start_vector=%"PRIxGENVADDR"\n",
1062 // __FILE__, __LINE__, destination, start_vector);
1064 apic_send_start_up(destination, xapic_none, start_vector);
1066 return SYSRET(SYS_ERR_OK);
1069 static struct sysret kernel_get_global_phys(struct capability *cap,
1074 struct sysret sysret;
1075 sysret.value = mem_to_local_phys((lvaddr_t)global);
1076 sysret.error = SYS_ERR_OK;
1081 static struct sysret kernel_add_kcb(struct capability *kern_cap,
1082 int cmd, uintptr_t *args)
1084 uintptr_t kcb_addr = args[0];
1085 struct kcb *new_kcb = (struct kcb *)kcb_addr;
1087 return sys_kernel_add_kcb(new_kcb);
1090 static struct sysret kernel_remove_kcb(struct capability *kern_cap,
1091 int cmd, uintptr_t *args)
1093 printk(LOG_NOTE, "in kernel_remove_kcb invocation!\n");
1094 uintptr_t kcb_addr = args[0];
1095 struct kcb *to_remove = (struct kcb *)kcb_addr;
1097 return sys_kernel_remove_kcb(to_remove);
1100 static struct sysret kernel_suspend_kcb_sched(struct capability *kern_cap,
1101 int cmd, uintptr_t *args)
1103 printk(LOG_NOTE, "in kernel_suspend_kcb_sched invocation!\n");
1104 return sys_kernel_suspend_kcb_sched((bool)args[0]);
1107 static struct sysret handle_kcb_identify(struct capability *to,
1108 int cmd, uintptr_t *args)
1110 return sys_handle_kcb_identify(to, (struct frame_identity *)args[0]);
1114 typedef struct sysret (*invocation_handler_t)(struct capability *to,
1115 int cmd, uintptr_t *args);
1117 static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
1118 [ObjType_Dispatcher] = {
1119 [DispatcherCmd_Setup] = handle_dispatcher_setup,
1120 [DispatcherCmd_Properties] = handle_dispatcher_properties,
1122 [DispatcherCmd_SetupGuest] = handle_dispatcher_setup_guest,
1124 [DispatcherCmd_DumpPTables] = dispatcher_dump_ptables,
1125 [DispatcherCmd_DumpCapabilities] = dispatcher_dump_capabilities,
1126 [DispatcherCmd_Vmread] = handle_vmread,
1127 [DispatcherCmd_Vmwrite] = handle_vmwrite,
1128 [DispatcherCmd_Vmptrld] = handle_vmptrld,
1129 [DispatcherCmd_Vmclear] = handle_vmclear,
1131 [ObjType_KernelControlBlock] = {
1132 [FrameCmd_Identify] = handle_kcb_identify,
1135 [RAMCmd_Identify] = handle_frame_identify,
1138 [FrameCmd_Identify] = handle_frame_identify,
1140 [ObjType_DevFrame] = {
1141 [FrameCmd_Identify] = handle_frame_identify,
1144 [CNodeCmd_Copy] = handle_cnode_cmd_obsolete,
1145 [CNodeCmd_Mint] = handle_cnode_cmd_obsolete,
1146 [CNodeCmd_Retype] = handle_cnode_cmd_obsolete,
1147 [CNodeCmd_Create] = handle_cnode_cmd_obsolete,
1148 [CNodeCmd_Delete] = handle_cnode_cmd_obsolete,
1149 [CNodeCmd_Revoke] = handle_cnode_cmd_obsolete,
1150 [CNodeCmd_GetState] = handle_cnode_cmd_obsolete,
1152 [ObjType_L1CNode] = {
1153 [CNodeCmd_Copy] = handle_copy,
1154 [CNodeCmd_Mint] = handle_mint,
1155 [CNodeCmd_Retype] = handle_retype,
1156 [CNodeCmd_Create] = handle_create,
1157 [CNodeCmd_Delete] = handle_delete,
1158 [CNodeCmd_Revoke] = handle_revoke,
1159 [CNodeCmd_GetState] = handle_get_state,
1161 [ObjType_L2CNode] = {
1162 [CNodeCmd_Copy] = handle_copy,
1163 [CNodeCmd_Mint] = handle_mint,
1164 [CNodeCmd_Retype] = handle_retype,
1165 [CNodeCmd_Create] = handle_create,
1166 [CNodeCmd_Delete] = handle_delete,
1167 [CNodeCmd_Revoke] = handle_revoke,
1168 [CNodeCmd_GetState] = handle_get_state,
1170 [ObjType_VNode_x86_64_pml4] = {
1171 [VNodeCmd_Identify] = handle_vnode_identify,
1172 [VNodeCmd_Map] = handle_map,
1173 [VNodeCmd_Unmap] = handle_unmap,
1175 [ObjType_VNode_x86_64_pdpt] = {
1176 [VNodeCmd_Identify] = handle_vnode_identify,
1177 [VNodeCmd_Map] = handle_map,
1178 [VNodeCmd_Unmap] = handle_unmap,
1180 [ObjType_VNode_x86_64_pdir] = {
1181 [VNodeCmd_Identify] = handle_vnode_identify,
1182 [VNodeCmd_Map] = handle_map,
1183 [VNodeCmd_Unmap] = handle_unmap,
1185 [ObjType_VNode_x86_64_ptable] = {
1186 [VNodeCmd_Identify] = handle_vnode_identify,
1187 [VNodeCmd_Map] = handle_map,
1188 [VNodeCmd_Unmap] = handle_unmap,
1190 [ObjType_Frame_Mapping] = {
1191 [MappingCmd_Destroy] = handle_mapping_destroy,
1192 [MappingCmd_Modify] = handle_mapping_modify,
1194 [ObjType_DevFrame_Mapping] = {
1195 [MappingCmd_Destroy] = handle_mapping_destroy,
1196 [MappingCmd_Modify] = handle_mapping_modify,
1198 [ObjType_VNode_x86_64_pml4_Mapping] = {
1199 [MappingCmd_Destroy] = handle_mapping_destroy,
1200 [MappingCmd_Modify] = handle_mapping_modify,
1202 [ObjType_VNode_x86_64_pdpt_Mapping] = {
1203 [MappingCmd_Destroy] = handle_mapping_destroy,
1204 [MappingCmd_Modify] = handle_mapping_modify,
1206 [ObjType_VNode_x86_64_pdir_Mapping] = {
1207 [MappingCmd_Destroy] = handle_mapping_destroy,
1208 [MappingCmd_Modify] = handle_mapping_modify,
1210 [ObjType_VNode_x86_64_ptable_Mapping] = {
1211 [MappingCmd_Destroy] = handle_mapping_destroy,
1212 [MappingCmd_Modify] = handle_mapping_modify,
1214 [ObjType_Kernel] = {
1215 [KernelCmd_Get_core_id] = monitor_get_core_id,
1216 [KernelCmd_Get_arch_id] = monitor_get_arch_id,
1217 [KernelCmd_Identify_cap] = monitor_identify_cap,
1218 [KernelCmd_Identify_domains_cap] = monitor_identify_domains_cap,
1219 [KernelCmd_Remote_relations] = monitor_remote_relations,
1220 [KernelCmd_Cap_has_relations] = monitor_cap_has_relations,
1221 [KernelCmd_Create_cap] = monitor_create_cap,
1222 [KernelCmd_Copy_existing] = monitor_copy_existing,
1223 [KernelCmd_Nullify_cap] = monitor_nullify_cap,
1224 [KernelCmd_Setup_trace] = handle_trace_setup,
1225 [KernelCmd_Register] = monitor_handle_register,
1226 [KernelCmd_Domain_Id] = monitor_handle_domain_id,
1227 [KernelCmd_Get_cap_owner] = monitor_get_cap_owner,
1228 [KernelCmd_Set_cap_owner] = monitor_set_cap_owner,
1229 [KernelCmd_Lock_cap] = monitor_lock_cap,
1230 [KernelCmd_Unlock_cap] = monitor_unlock_cap,
1231 [KernelCmd_Retype] = monitor_handle_retype,
1232 [KernelCmd_Has_descendants] = monitor_handle_has_descendants,
1233 [KernelCmd_Delete_last] = monitor_handle_delete_last,
1234 [KernelCmd_Delete_foreigns] = monitor_handle_delete_foreigns,
1235 [KernelCmd_Revoke_mark_target] = monitor_handle_revoke_mark_tgt,
1236 [KernelCmd_Revoke_mark_relations] = monitor_handle_revoke_mark_rels,
1237 [KernelCmd_Delete_step] = monitor_handle_delete_step,
1238 [KernelCmd_Clear_step] = monitor_handle_clear_step,
1239 [KernelCmd_Sync_timer] = monitor_handle_sync_timer,
1240 [KernelCmd_IPI_Register] = kernel_ipi_register,
1241 [KernelCmd_IPI_Delete] = kernel_ipi_delete,
1242 [KernelCmd_GetGlobalPhys] = kernel_get_global_phys,
1243 [KernelCmd_Add_kcb] = kernel_add_kcb,
1244 [KernelCmd_Remove_kcb] = kernel_remove_kcb,
1245 [KernelCmd_Suspend_kcb_sched] = kernel_suspend_kcb_sched,
1246 [KernelCmd_Get_platform] = monitor_get_platform,
1249 [IPICmd_Send_Start] = kernel_send_start_ipi,
1250 [IPICmd_Send_Init] = kernel_send_init_ipi,
1252 [ObjType_IRQDest] = {
1253 [IRQDestCmd_Connect] = handle_irqdest_connect,
1254 [IRQDestCmd_GetVector] = handle_irqdest_get_vector
1256 [ObjType_IRQSrc] = {
1257 [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
1259 [ObjType_IRQTable] = {
1260 [IRQTableCmd_Alloc] = handle_irq_table_alloc,
1261 [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
1262 [IRQTableCmd_Set] = handle_irq_table_set,
1263 [IRQTableCmd_Delete] = handle_irq_table_delete
1266 [IOCmd_Outb] = handle_io,
1267 [IOCmd_Outw] = handle_io,
1268 [IOCmd_Outd] = handle_io,
1269 [IOCmd_Inb] = handle_io,
1270 [IOCmd_Inw] = handle_io,
1271 [IOCmd_Ind] = handle_io
1273 [ObjType_Notify_IPI] = {
1274 [NotifyCmd_Send] = handle_ipi_notify_send
1276 [ObjType_PerfMon] = {
1277 [PerfmonCmd_Activate] = performance_counter_activate,
1278 [PerfmonCmd_Deactivate] = performance_counter_deactivate,
1279 [PerfmonCmd_Write] = performance_counter_write,
1282 [IDCmd_Identify] = handle_idcap_identify,
1286 /* syscall C entry point; called only from entry.S so no prototype in header */
1287 struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
1288 uint64_t *args, uint64_t rflags, uint64_t rip);
1289 struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
1290 uint64_t *args, uint64_t rflags, uint64_t rip)
1292 struct sysret retval = { .error = SYS_ERR_OK, .value = 0 };
1295 // Set dcb_current->disabled correctly. This should really be
1298 assert(dcb_current != NULL);
1299 if (dispatcher_is_disabled_ip(dcb_current->disp, rip)) {
1300 dcb_current->disabled = true;
1302 dcb_current->disabled = false;
1304 assert(get_dispatcher_shared_generic(dcb_current->disp)->disabled ==
1305 dcb_current->disabled);
1308 case SYSCALL_INVOKE: /* Handle capability invocation */
1310 // unpack "header" word
1311 capaddr_t invoke_cptr = arg0 >> 32;
1312 uint8_t send_level = arg0 >> 24;
1313 uint8_t invoke_level = arg0 >> 16;
1314 uint8_t length_words = arg0 >> 8;
1315 uint8_t flags = arg0;
1317 debug(SUBSYS_SYSCALL, "sys_invoke(0x%x(%d), 0x%lx)\n",
1318 invoke_cptr, invoke_level, arg1);
1319 //printk(LOG_NOTE, "sys_invoke(0x%x(%d), 0x%lx)\n",
1320 // invoke_cptr, invoke_level, arg1);
1322 // Capability to invoke
1323 struct capability *to = NULL;
1324 retval.error = caps_lookup_cap_2(&dcb_current->cspace.cap, invoke_cptr,
1325 invoke_level, &to, CAPRIGHTS_READ);
1326 if (err_is_fail(retval.error)) {
1331 assert(to->type < ObjType_Num);
1333 // Endpoint cap, do LMP
1334 if (to->type == ObjType_EndPoint) {
1335 struct dcb *listener = to->u.endpoint.listener;
1336 assert(listener != NULL);
1338 if (listener->disp == 0) {
1339 retval.error = SYS_ERR_LMP_NO_TARGET;
1343 /* limit length of message from buggy/malicious sender */
1344 length_words = MIN(length_words, LMP_MSG_LENGTH);
1346 // does the sender want to yield their timeslice on success?
1347 bool sync = flags & LMP_FLAG_SYNC;
1348 // does the sender want to yield to the target if undeliverable?
1349 bool yield = flags & LMP_FLAG_YIELD;
1350 // is the cap (if present) to be deleted on send?
1351 bool give_away = flags & LMP_FLAG_GIVEAWAY;
1353 // try to deliver message
1354 retval.error = lmp_deliver(to, dcb_current, args, length_words,
1355 arg1, send_level, give_away);
1357 /* Switch to reciever upon successful delivery with sync flag,
1358 * or (some cases of) unsuccessful delivery with yield flag */
1359 enum err_code err_code = err_no(retval.error);
1360 if ((sync && err_is_ok(retval.error)) ||
1361 (yield && (err_code == SYS_ERR_LMP_BUF_OVERFLOW
1362 || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
1363 || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
1364 || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED))
1366 if (err_is_fail(retval.error)) {
1367 struct dispatcher_shared_generic *current_disp =
1368 get_dispatcher_shared_generic(dcb_current->disp);
1369 struct dispatcher_shared_generic *listener_disp =
1370 get_dispatcher_shared_generic(listener->disp);
1371 debug(SUBSYS_DISPATCH, "LMP failed; %.*s yields to %.*s: %u\n",
1372 DISP_NAME_LEN, current_disp->name,
1373 DISP_NAME_LEN, listener_disp->name, err_code);
1376 // special-case context switch: ensure correct state in current DCB
1377 dispatcher_handle_t handle = dcb_current->disp;
1378 struct dispatcher_shared_x86_64 *disp =
1379 get_dispatcher_shared_x86_64(handle);
1380 dcb_current->disabled = dispatcher_is_disabled_ip(handle, rip);
1381 struct registers_x86_64 *save_area;
1382 if (dcb_current->disabled) {
1383 save_area = &disp->disabled_save_area;
1385 save_area = &disp->enabled_save_area;
1388 // Should be enabled. Else, how do we do an invocation??
1389 if(dcb_current->disabled) {
1390 panic("Dispatcher needs to be enabled for this invocation");
1393 // save calling dispatcher's registers, so that when the dispatcher
1394 // next runs, it has a valid state in the relevant save area.
1395 // Save RIP, RFLAGS, RSP and set RAX (return value) for later resume
1396 save_area->rax = retval.error; // XXX: x86 1st return register
1397 save_area->rip = rip;
1398 save_area->eflags = rflags;
1399 save_area->rsp = user_stack_save;
1401 if(!dcb_current->is_vm_guest) {
1402 /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
1403 __asm ("mov %%fs, %[fs] \n\t"
1404 "mov %%gs, %[gs] \n\t"
1405 "mov %[zero], %%fs \n\t"
1406 "mov %[zero], %%gs \n\t"
1409 [fs] "m" (save_area->fs),
1410 [gs] "m" (save_area->gs),
1416 lpaddr_t lpaddr = gen_phys_to_local_phys(dcb_current->guest_desc.vmcb.cap.u.frame.base);
1418 amd_vmcb_initialize(&vmcb, (void *)local_phys_to_mem(lpaddr));
1419 save_area->fs = amd_vmcb_fs_selector_rd(&vmcb);
1420 save_area->gs = amd_vmcb_gs_selector_rd(&vmcb);
1423 err = vmread(VMX_GUEST_FS_SEL, (uint64_t *)&save_area->fs);
1424 err += vmread(VMX_GUEST_GS_SEL, (uint64_t *)&save_area->gs);
1425 assert(err_is_ok(err));
1428 panic("VM Guests not supported on Xeon Phi");
1432 dispatch(to->u.endpoint.listener);
1433 panic("dispatch returned");
1435 } else { // not endpoint cap, call kernel handler through dispatch table
1436 // printk(LOG_NOTE, "sys_invoke: to->type = %d, cmd = %"PRIu64"\n",
1437 // to->type, args[0]);
1439 uint64_t cmd = args[0];
1440 if (cmd >= CAP_MAX_CMD) {
1441 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1445 // Call the invocation
1446 invocation_handler_t invocation = invocations[to->type][cmd];
1447 if(invocation == NULL) {
1448 printk(LOG_WARN, "invocation not found. type: %"PRIu32", cmd: %"PRIu64"\n",
1450 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1452 retval = invocation(to, cmd, &args[1]);
1458 // Yield the CPU to the next dispatcher
1460 TRACE(KERNEL, SC_YIELD, 0);
1461 retval = sys_yield((capaddr_t)arg0);
1462 TRACE(KERNEL, SC_YIELD, 1);
1465 // NOP system call for benchmarking purposes
1469 // Debug print system call
1471 TRACE(KERNEL, SC_PRINT, 0);
1472 retval.error = sys_print((char *)arg0, arg1);
1473 TRACE(KERNEL, SC_PRINT, 1);
1477 // FIXME: this should be a kernel cap invocation or similarly restricted
1478 case SYSCALL_REBOOT:
1482 case SYSCALL_X86_FPU_TRAP_ON:
1486 case SYSCALL_X86_RELOAD_LDT:
1487 maybe_reload_ldt(dcb_current, true);
1490 // Temporarily suspend the CPU
1491 case SYSCALL_SUSPEND:
1492 TRACE(KERNEL, SC_SUSPEND, 0);
1493 retval = sys_suspend((bool)arg0);
1494 TRACE(KERNEL, SC_SUSPEND, 1);
1497 case SYSCALL_GET_ABS_TIME:
1498 retval = sys_get_absolute_time();
1503 case DEBUG_CONTEXT_COUNTER_RESET:
1504 dispatch_csc_reset();
1507 case DEBUG_CONTEXT_COUNTER_READ:
1508 retval.value = dispatch_get_csc();
1511 case DEBUG_TIMESLICE_COUNTER_READ:
1512 retval.value = kernel_now;
1515 case DEBUG_FLUSH_CACHE:
1519 case DEBUG_SEND_IPI:
1520 apic_send_std_ipi(arg1, args[0], args[1]);
1523 case DEBUG_SET_BREAKPOINT:
1524 debugregs_set_breakpoint(arg1, args[0], args[1]);
1527 case DEBUG_GET_TSC_PER_MS:
1528 retval.value = timing_get_tsc_per_ms();
1531 case DEBUG_GET_APIC_TIMER:
1532 retval.value = apic_timer_get_count();
1535 case DEBUG_GET_APIC_TICKS_PER_SEC:
1536 retval.value = timing_get_apic_ticks_per_sec();
1539 case DEBUG_TRACE_PMEM_CTRL:
1540 #ifdef TRACE_PMEM_CAPS
1542 caps_trace_ctrl(arg1, args[0], args[1]);
1544 caps_trace_ctrl(arg1, 0, 0);
1548 retval.error = SYS_ERR_OK;
1552 case DEBUG_GET_APIC_ID:
1553 retval.value = apic_get_id();
1556 case DEBUG_CREATE_IRQ_SRC_CAP:
1557 retval.error = irq_debug_create_src_cap(arg1, args[0], args[1], args[2]);
1561 printk(LOG_ERR, "invalid sys_debug msg type\n");
1566 printk(LOG_ERR, "sys_syscall: Illegal system call! "
1567 "(0x%lx, 0x%lx, 0x%lx)\n", syscall, arg0, arg1);
1568 retval.error = SYS_ERR_ILLEGAL_SYSCALL;
1572 // If dcb_current got removed, dispatch someone else
1573 if (dcb_current == NULL) {
1574 assert(err_is_ok(retval.error));
1575 dispatch(schedule());
1578 if (syscall == SYSCALL_INVOKE) {
1579 debug(SUBSYS_SYSCALL, "invoke returning 0x%lx 0x%lx\n",
1580 retval.error, retval.value);