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 <trace/trace.h>
39 #include <useraccess.h>
42 #include <dev/amd_vmcb_dev.h>
45 #define MIN(a,b) ((a) < (b) ? (a) : (b))
47 extern uint64_t user_stack_save;
49 /* FIXME: lots of missing argument checks in this function */
50 static struct sysret handle_dispatcher_setup(struct capability *to,
51 int cmd, uintptr_t *args)
53 capaddr_t cptr = args[0];
55 capaddr_t vptr = args[2];
56 capaddr_t dptr = args[3];
58 capaddr_t odptr = args[5];
60 TRACE(KERNEL, SC_DISP_SETUP, 0);
61 struct sysret sr = sys_dispatcher_setup(to, cptr, depth, vptr, dptr, run, odptr);
62 TRACE(KERNEL, SC_DISP_SETUP, 1);
66 static struct sysret handle_dispatcher_properties(struct capability *to,
67 int cmd, uintptr_t *args)
69 enum task_type type = args[0];
70 unsigned long deadline = args[1];
71 unsigned long wcet = args[2];
72 unsigned long period = args[3];
73 unsigned long release = args[4];
74 unsigned short weight = args[5];
76 TRACE(KERNEL, SC_DISP_PROPS, 0);
77 struct sysret sr = sys_dispatcher_properties(to, type, deadline, wcet, period,
79 TRACE(KERNEL, SC_DISP_PROPS, 1);
83 static struct sysret handle_retype_common(struct capability *root,
87 uint64_t source_cptr = args[0];
88 uint64_t type = args[1];
89 uint64_t objbits = args[2];
90 uint64_t dest_cnode_cptr = args[3];
91 uint64_t dest_slot = args[4];
92 uint64_t dest_vbits = args[5];
94 TRACE(KERNEL, SC_RETYPE, 0);
95 struct sysret sr = sys_retype(root, source_cptr, type, objbits, dest_cnode_cptr,
96 dest_slot, dest_vbits, from_monitor);
97 TRACE(KERNEL, SC_RETYPE, 1);
101 static struct sysret handle_retype(struct capability *root,
102 int cmd, uintptr_t *args)
104 return handle_retype_common(root, args, false);
107 static struct sysret handle_create(struct capability *root,
108 int cmd, uintptr_t *args)
110 /* Retrieve arguments */
111 enum objtype type = args[0];
112 uint8_t objbits = args[1];
113 capaddr_t dest_cnode_cptr = args[2];
114 cslot_t dest_slot = args[3];
115 uint8_t dest_vbits = args[4];
117 TRACE(KERNEL, SC_CREATE, 0);
118 struct sysret sr = sys_create(root, type, objbits, dest_cnode_cptr, dest_slot,
120 TRACE(KERNEL, SC_CREATE, 1);
126 * Common code for copying and minting except the mint flag and param passing
128 static struct sysret copy_or_mint(struct capability *root,
129 uintptr_t *args, bool mint)
131 /* Retrive arguments */
132 capaddr_t destcn_cptr = args[0];
133 uint64_t dest_slot = args[1];
134 capaddr_t source_cptr = args[2];
135 int destcn_vbits = args[3];
136 int source_vbits = args[4];
137 uint64_t param1, param2;
138 // params only sent if mint operation
146 TRACE(KERNEL, SC_COPY_OR_MINT, 0);
147 struct sysret sr = sys_copy_or_mint(root, destcn_cptr, dest_slot, source_cptr,
148 destcn_vbits, source_vbits, param1, param2, mint);
149 TRACE(KERNEL, SC_COPY_OR_MINT, 1);
153 static struct sysret handle_map(struct capability *ptable,
154 int cmd, uintptr_t *args)
156 /* Retrieve arguments */
157 uint64_t slot = args[0];
158 capaddr_t source_cptr = args[1];
159 int source_vbits = args[2];
160 uint64_t flags = args[3];
161 uint64_t offset = args[4];
162 uint64_t pte_count = args[5];
163 capaddr_t mapping_cnptr = args[6];
164 int mapping_cnvbits = args[7];
165 cslot_t mapping_slot = args[8];
167 TRACE(KERNEL, SC_MAP, 0);
168 struct sysret sr = sys_map(ptable, slot, source_cptr, source_vbits, flags,
169 offset, pte_count, mapping_cnptr, mapping_cnvbits,
171 TRACE(KERNEL, SC_MAP, 1);
175 static struct sysret handle_mint(struct capability *root,
176 int cmd, uintptr_t *args)
178 return copy_or_mint(root, args, true);
181 static struct sysret handle_copy(struct capability *root,
182 int cmd, uintptr_t *args)
184 return copy_or_mint(root, args, false);
187 static struct sysret handle_delete(struct capability *root,
188 int cmd, uintptr_t *args)
190 capaddr_t cptr = args[0];
192 return sys_delete(root, cptr, bits);
195 static struct sysret handle_revoke(struct capability *root,
196 int cmd, uintptr_t *args)
198 capaddr_t cptr = args[0];
200 return sys_revoke(root, cptr, bits);
203 static struct sysret handle_get_state(struct capability *root,
204 int cmd, uintptr_t *args)
206 capaddr_t cptr = args[0];
208 return sys_get_state(root, cptr, bits);
211 static struct sysret handle_unmap(struct capability *pgtable,
212 int cmd, uintptr_t *args)
214 capaddr_t cptr = args[0];
219 err = caps_lookup_slot(&dcb_current->cspace.cap, cptr, bits,
220 &mapping, CAPRIGHTS_READ_WRITE);
221 if (err_is_fail(err)) {
222 return SYSRET(err_push(err, SYS_ERR_CAP_NOT_FOUND));
225 TRACE(KERNEL, SC_UNMAP, 0);
226 err = page_mappings_unmap(pgtable, mapping);
227 TRACE(KERNEL, SC_UNMAP, 1);
231 static struct sysret handle_mapping_destroy(struct capability *mapping,
232 int cmd, uintptr_t *args)
235 return SYSRET(SYS_ERR_OK);
238 static struct sysret handle_mapping_modify(struct capability *mapping,
239 int cmd, uintptr_t *args)
241 // Modify flags of (part of) mapped region of frame
242 assert(type_is_mapping(mapping->type));
245 size_t offset = args[0]; // in pages; of first page to modify from first
246 // page in mapped region
247 size_t pages = args[1]; // #pages to modify
248 size_t flags = args[2]; // new flags
249 genvaddr_t va = args[3]; // virtual addr hint
251 errval_t err = page_mappings_modify_flags(mapping, offset, pages, flags, va);
253 return (struct sysret) {
259 /// Different handler for cap operations performed by the monitor
260 static struct sysret monitor_handle_retype(struct capability *kernel_cap,
261 int cmd, uintptr_t *args)
265 capaddr_t root_caddr = args[0];
266 capaddr_t root_vbits = args[1];
268 struct capability *root;
269 err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
270 &root, CAPRIGHTS_READ);
271 if (err_is_fail(err)) {
272 return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
275 /* XXX: this hides the first two arguments */
276 return handle_retype_common(root, &args[2], true);
279 static struct sysret monitor_handle_has_descendants(struct capability *kernel_cap,
280 int cmd, uintptr_t *args)
282 struct capability *src = (struct capability *)args;
284 struct cte *next = mdb_find_greater(src, false);
286 return (struct sysret) {
288 .value = (next && is_ancestor(&next->cap, src)),
292 static struct sysret monitor_handle_delete_last(struct capability *kernel_cap,
293 int cmd, uintptr_t *args)
295 capaddr_t root_caddr = args[0];
296 uint8_t root_vbits = args[1];
297 capaddr_t target_caddr = args[2];
298 uint8_t target_vbits = args[3];
299 capaddr_t retcn_caddr = args[4];
300 uint8_t retcn_vbits = args[5];
301 cslot_t ret_slot = args[6];
303 return sys_monitor_delete_last(root_caddr, root_vbits, target_caddr,
304 target_vbits, retcn_caddr, retcn_vbits,
308 static struct sysret monitor_handle_delete_foreigns(struct capability *kernel_cap,
309 int cmd, uintptr_t *args)
311 capaddr_t caddr = args[0];
312 uint8_t bits = args[1];
313 return sys_monitor_delete_foreigns(caddr, bits);
316 static struct sysret monitor_handle_revoke_mark_tgt(struct capability *kernel_cap,
317 int cmd, uintptr_t *args)
319 capaddr_t root_caddr = args[0];
320 uint8_t root_vbits = args[1];
321 capaddr_t target_caddr = args[2];
322 uint8_t target_vbits = args[3];
324 return sys_monitor_revoke_mark_tgt(root_caddr, root_vbits,
325 target_caddr, target_vbits);
328 static struct sysret monitor_handle_revoke_mark_rels(struct capability *kernel_cap,
329 int cmd, uintptr_t *args)
331 struct capability *base = (struct capability*)args;
333 return sys_monitor_revoke_mark_rels(base);
336 static struct sysret monitor_handle_delete_step(struct capability *kernel_cap,
337 int cmd, uintptr_t *args)
339 capaddr_t ret_cn_addr = args[0];
340 capaddr_t ret_cn_bits = args[1];
341 capaddr_t ret_slot = args[2];
342 return sys_monitor_delete_step(ret_cn_addr, ret_cn_bits, ret_slot);
345 static struct sysret monitor_handle_clear_step(struct capability *kernel_cap,
346 int cmd, uintptr_t *args)
348 capaddr_t ret_cn_addr = args[0];
349 capaddr_t ret_cn_bits = args[1];
350 capaddr_t ret_slot = args[2];
351 return sys_monitor_clear_step(ret_cn_addr, ret_cn_bits, ret_slot);
354 static struct sysret monitor_handle_register(struct capability *kernel_cap,
355 int cmd, uintptr_t *args)
357 capaddr_t ep_caddr = args[0];
359 TRACE(KERNEL, SC_MONITOR_REGISTER, 0);
360 struct sysret sr = sys_monitor_register(ep_caddr);
361 TRACE(KERNEL, SC_MONITOR_REGISTER, 1);
365 static struct sysret monitor_get_core_id(struct capability *kernel_cap,
366 int cmd, uintptr_t *args)
368 return (struct sysret){.error = SYS_ERR_OK, .value = my_core_id};
371 static struct sysret monitor_get_arch_id(struct capability *kernel_cap,
372 int cmd, uintptr_t *args)
374 return (struct sysret){.error = SYS_ERR_OK, .value = apic_id};
377 static struct sysret monitor_identify_cap_common(struct capability *kernel_cap,
378 struct capability *root,
381 capaddr_t cptr = args[0];
382 uint8_t bits = args[1];
384 struct capability *retbuf = (void *)args[2];
386 return sys_monitor_identify_cap(root, cptr, bits, retbuf);
389 static struct sysret monitor_identify_cap(struct capability *kernel_cap,
390 int cmd, uintptr_t *args)
392 return monitor_identify_cap_common(kernel_cap, &dcb_current->cspace.cap, args);
395 static struct sysret monitor_identify_domains_cap(struct capability *kernel_cap,
396 int cmd, uintptr_t *args)
400 capaddr_t root_caddr = args[0];
401 capaddr_t root_vbits = args[1];
403 struct capability *root;
404 err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
405 &root, CAPRIGHTS_READ);
407 if (err_is_fail(err)) {
408 return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
411 /* XXX: this hides the first two arguments */
412 return monitor_identify_cap_common(kernel_cap, root, &args[2]);
415 static struct sysret monitor_cap_has_relations(struct capability *kernel_cap,
416 int cmd, uintptr_t *args)
418 capaddr_t caddr = args[0];
419 uint8_t vbits = args[1];
420 uint8_t mask = args[2];
422 return sys_cap_has_relations(caddr, vbits, mask);
425 static struct sysret monitor_remote_relations(struct capability *kernel_cap,
426 int cmd, uintptr_t *args)
428 capaddr_t root_addr = args[0];
429 int root_bits = args[1];
430 capaddr_t cptr = args[2];
432 uint8_t relations = args[4] & 0xFF;
433 uint8_t mask = (args[4] >> 8) & 0xFF;
435 return sys_monitor_remote_relations(root_addr, root_bits, cptr, bits,
440 static struct sysret monitor_create_cap(struct capability *kernel_cap,
441 int cmd, uintptr_t *args)
443 /* XXX: Get the raw metadata of the capability to create */
444 struct capability *src = (struct capability *)args;
445 int pos = ROUND_UP(sizeof(struct capability), sizeof(uint64_t)) / sizeof(uint64_t);
447 /* Cannot create null caps */
448 if (src->type == ObjType_Null) {
449 return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
452 coreid_t owner = args[pos + 3];
454 /* For certain types, only foreign copies can be created here */
455 if ((src->type == ObjType_EndPoint || src->type == ObjType_Dispatcher
456 || src->type == ObjType_Kernel || src->type == ObjType_IRQTable)
457 && owner == my_core_id)
459 return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
462 /* Create the cap in the destination */
463 capaddr_t cnode_cptr = args[pos];
464 int cnode_vbits = args[pos + 1];
465 size_t slot = args[pos + 2];
466 assert(cnode_vbits < CPTR_BITS);
468 return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
469 cnode_cptr, cnode_vbits,
473 static struct sysret monitor_copy_existing(struct capability *kernel_cap,
474 int cmd, uintptr_t *args)
476 /* XXX: Get the raw metadata of the capability to create */
477 struct capability *src = (struct capability *)args;
478 int pos = ROUND_UP(sizeof(struct capability), sizeof(uint64_t)) / sizeof(uint64_t);
480 capaddr_t cnode_cptr = args[pos];
481 int cnode_vbits = args[pos + 1];
482 size_t slot = args[pos + 2];
484 return sys_monitor_copy_existing(src, cnode_cptr, cnode_vbits, slot);
487 static struct sysret monitor_nullify_cap(struct capability *kernel_cap,
488 int cmd, uintptr_t *args)
490 capaddr_t cptr = args[0];
491 uint8_t bits = args[1];
493 return sys_monitor_nullify_cap(cptr, bits);
496 static struct sysret monitor_handle_sync_timer(struct capability *kern_cap,
497 int cmd, uintptr_t *args)
499 uint64_t synctime = args[0];
500 return sys_monitor_handle_sync_timer(synctime);
503 static struct sysret handle_frame_identify(struct capability *to,
504 int cmd, uintptr_t *args)
506 // Return with physical base address of frame
507 // XXX: pack size into bottom bits of base address
508 assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame);
509 assert((to->u.frame.base & BASE_PAGE_MASK) == 0);
511 struct frame_identity *fi = (struct frame_identity *)args[0];
513 if (!access_ok(ACCESS_WRITE, (lvaddr_t)fi, sizeof(struct frame_identity))) {
514 return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
517 fi->base = get_address(to);
518 fi->bytes = get_size(to);
520 return SYSRET(SYS_ERR_OK);
523 static struct sysret handle_vnode_identify(struct capability *to,
524 int cmd, uintptr_t *args)
526 // Return with physical base address of the VNode
527 // XXX: pack type into bottom bits of base address
528 assert(to->type == ObjType_VNode_x86_64_pml4 ||
529 to->type == ObjType_VNode_x86_64_pdpt ||
530 to->type == ObjType_VNode_x86_64_pdir ||
531 to->type == ObjType_VNode_x86_64_ptable);
533 uint64_t base_addr = 0;
535 case ObjType_VNode_x86_64_pml4:
536 base_addr = (uint64_t)(to->u.vnode_x86_64_pml4.base);
538 case ObjType_VNode_x86_64_pdpt:
539 base_addr = (uint64_t)(to->u.vnode_x86_64_pdpt.base);
541 case ObjType_VNode_x86_64_pdir:
542 base_addr = (uint64_t)(to->u.vnode_x86_64_pdir.base);
544 case ObjType_VNode_x86_64_ptable:
545 base_addr = (uint64_t)(to->u.vnode_x86_64_ptable.base);
550 assert((base_addr & BASE_PAGE_MASK) == 0);
552 return (struct sysret) {
554 .value = (genpaddr_t)base_addr | ((uint8_t)to->type),
559 static struct sysret handle_io(struct capability *to, int cmd, uintptr_t *args)
561 uint64_t port = args[0];
562 uint64_t data = args[1]; // ignored for input
564 return sys_io(to, cmd, port, data);
567 static struct sysret handle_vmread(struct capability *to,
568 int cmd, uintptr_t *args)
570 #if defined(__k1om__) || defined(CONFIG_SVM)
571 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
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;
579 err = vmread(args[0], (lvaddr_t *)args[1]);
585 static struct sysret handle_vmwrite(struct capability *to,
586 int cmd, uintptr_t *args)
588 #if defined(__k1om__) || defined(CONFIG_SVM)
589 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
592 struct dcb *dcb = to->u.dispatcher.dcb;
593 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
594 if (vmcs_base != vmptrst()) {
595 err = SYS_ERR_VMKIT_VMX_VMFAIL_INVALID;
597 err = vmwrite(args[0], args[1]);
603 static struct sysret handle_vmptrld(struct capability *to,
604 int cmd, uintptr_t *args)
606 #if defined(__k1om__) || defined(CONFIG_SVM)
607 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
610 struct dcb *dcb = to->u.dispatcher.dcb;
611 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
612 err = vmptrld(vmcs_base);
617 static struct sysret handle_vmclear(struct capability *to,
618 int cmd, uintptr_t *args)
620 #if defined(__k1om__) || defined(CONFIG_SVM)
621 return SYSRET(SYS_ERR_VMKIT_UNAVAIL);
624 struct dcb *dcb = to->u.dispatcher.dcb;
625 lpaddr_t vmcs_base = dcb->guest_desc.vmcb.cap.u.frame.base;
626 err = vmclear(vmcs_base);
633 handle_dispatcher_setup_guest (struct capability *to, int cmd, uintptr_t *args)
636 struct dcb *dcb = to->u.dispatcher.dcb;
638 capaddr_t epp = args[0];
639 capaddr_t vnodep = args[1];
640 capaddr_t vmcbp = args[2];
641 capaddr_t ctrlp = args[3];
643 // 0. Enable VM extensions
644 err = vmkit_enable_virtualization();
645 if (err != SYS_ERR_OK) {
649 // 1. Check arguments
650 // Monitor endpoint for exits of this geust
653 err = caps_lookup_slot(&dcb_current->cspace.cap, epp, CPTR_BITS,
654 &ep_cte, CAPRIGHTS_READ_WRITE);
655 if (err_is_fail(err)) {
658 if (ep_cte->cap.type != ObjType_EndPoint) {
659 return SYSRET(SYS_ERR_VMKIT_ENDPOINT_INVALID);
661 err = caps_copy_to_cte(&dcb->guest_desc.monitor_ep, ep_cte, false, 0, 0);
662 if (err_is_fail(err)) {
663 return SYSRET(err_push(err, SYS_ERR_VMKIT_ENDPOINT));
667 struct capability *vnode_cap;
668 err = caps_lookup_cap(&dcb_current->cspace.cap, vnodep, CPTR_BITS,
669 &vnode_cap, CAPRIGHTS_WRITE);
670 if (err_is_fail(err)) {
673 if (vnode_cap->type != ObjType_VNode_x86_64_pml4) {
674 return SYSRET(SYS_ERR_DISP_VSPACE_INVALID);
677 assert(vnode_cap->type == ObjType_VNode_x86_64_pml4);
680 struct cte *vmcb_cte;
681 err = caps_lookup_slot(&dcb_current->cspace.cap, vmcbp, CPTR_BITS,
682 &vmcb_cte, CAPRIGHTS_READ_WRITE);
683 if (err_is_fail(err)) {
686 if (vmcb_cte->cap.type != ObjType_Frame ||
687 vmcb_cte->cap.u.frame.bytes < BASE_PAGE_SIZE) {
688 return SYSRET(SYS_ERR_VMKIT_VMCB_INVALID);
690 err = caps_copy_to_cte(&dcb->guest_desc.vmcb, vmcb_cte, false, 0, 0);
691 if (err_is_fail(err)) {
692 return SYSRET(err_push(err, SYS_ERR_VMKIT_VMCB));
696 struct cte *ctrl_cte;
697 err = caps_lookup_slot(&dcb_current->cspace.cap, ctrlp, CPTR_BITS,
698 &ctrl_cte, CAPRIGHTS_READ_WRITE);
699 if (err_is_fail(err)) {
702 if (ctrl_cte->cap.type != ObjType_Frame ||
703 ctrl_cte->cap.u.frame.bytes < BASE_PAGE_SIZE) {
704 return SYSRET(SYS_ERR_VMKIT_CTRL_INVALID);
706 err = caps_copy_to_cte(&dcb->guest_desc.ctrl, ctrl_cte, false, 0, 0);
707 if (err_is_fail(err)) {
708 return SYSRET(err_push(err, SYS_ERR_VMKIT_CTRL));
712 // Initialize VMCS for the single virtual-CPU here instead of in
713 // userspace, where the privilege level is not 0.
714 err = initialize_vmcs(vmcb_cte->cap.u.frame.base);
715 assert(err_is_ok(err));
718 // 2. Set up the target DCB
719 /* dcb->guest_desc.monitor_ep = ep_cap; */
720 dcb->vspace = vnode_cap->u.vnode_x86_64_pml4.base;
721 dcb->is_vm_guest = true;
722 /* dcb->guest_desc.vmcb = vmcb_cap->u.frame.base; */
723 /* dcb->guest_desc.ctrl = (void *)x86_64_phys_to_mem(ctrl_cap->u.frame.base); */
725 return SYSRET(SYS_ERR_OK);
729 static struct sysret monitor_handle_domain_id(struct capability *monitor_cap,
730 int cmd, uintptr_t *args)
732 capaddr_t cptr = args[0];
733 domainid_t domain_id = args[1];
735 return sys_monitor_domain_id(cptr, domain_id);
738 static struct sysret monitor_get_cap_owner(struct capability *monitor_cap,
739 int cmd, uintptr_t *args)
741 capaddr_t root_addr = args[0];
742 uint8_t root_bits = args[1];
743 capaddr_t cptr = args[2];
744 uint8_t bits = args[3];
746 return sys_get_cap_owner(root_addr, root_bits, cptr, bits);
749 static struct sysret monitor_set_cap_owner(struct capability *monitor_cap,
750 int cmd, uintptr_t *args)
752 capaddr_t root_addr = args[0];
753 uint8_t root_bits = args[1];
754 capaddr_t cptr = args[2];
755 uint8_t bits = args[3];
756 coreid_t owner = args[4];
758 return sys_set_cap_owner(root_addr, root_bits, cptr, bits, owner);
761 static struct sysret monitor_lock_cap(struct capability *monitor_cap,
762 int cmd, uintptr_t *args)
764 capaddr_t root_addr = args[0];
765 uint8_t root_bits = args[1];
766 capaddr_t cptr = args[2];
767 uint8_t bits = args[3];
769 return sys_lock_cap(root_addr, root_bits, cptr, bits);
772 static struct sysret monitor_unlock_cap(struct capability *monitor_cap,
773 int cmd, uintptr_t *args)
775 capaddr_t root_addr = args[0];
776 uint8_t root_bits = args[1];
777 capaddr_t cptr = args[2];
778 uint8_t bits = args[3];
780 return sys_unlock_cap(root_addr, root_bits, cptr, bits);
784 * \brief Set up tracing in the kernel
786 static struct sysret handle_trace_setup(struct capability *cap,
787 int cmd, uintptr_t *args)
789 struct capability *frame;
792 /* lookup passed cap */
793 capaddr_t cptr = args[0];
794 err = caps_lookup_cap(&dcb_current->cspace.cap, cptr, CPTR_BITS, &frame,
795 CAPRIGHTS_READ_WRITE);
796 if (err_is_fail(err)) {
800 lpaddr_t lpaddr = gen_phys_to_local_phys(frame->u.frame.base);
801 kernel_trace_buf = local_phys_to_mem(lpaddr);
802 //printf("kernel.%u: handle_trace_setup at %lx\n", apic_id, kernel_trace_buf);
804 // Copy boot applications.
805 trace_copy_boot_applications();
807 return SYSRET(SYS_ERR_OK);
810 static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
814 ret.error = SYS_ERR_OK;
815 ret.value = to->u.irqsrc.vector;
821 static struct sysret handle_irqdest_get_vector(struct capability *to, int cmd,
825 ret.error = SYS_ERR_OK;
826 ret.value = to->u.irqdest.vector;
830 static struct sysret handle_irqdest_connect(struct capability *to, int cmd,
833 return SYSRET(irq_connect(to, args[0]));
836 static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
841 ret.error = irq_table_alloc(&outvec);
846 static struct sysret handle_irq_table_alloc_dest_cap(struct capability *to, int cmd,
849 return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2]));
853 static struct sysret handle_irq_table_set(struct capability *to, int cmd,
856 return SYSRET(irq_table_set(args[0], args[1]));
859 static struct sysret handle_irq_table_delete(struct capability *to, int cmd,
862 return SYSRET(irq_table_delete(args[0]));
865 static struct sysret handle_ipi_notify_send(struct capability *cap,
866 int cmd, uintptr_t *args)
868 assert(cap->type == ObjType_Notify_IPI);
869 return ipi_raise_notify(cap->u.notify_ipi.coreid, cap->u.notify_ipi.chanid);
872 static struct sysret kernel_ipi_register(struct capability *cap,
873 int cmd, uintptr_t *args)
875 assert(cap->type == ObjType_Kernel);
876 capaddr_t ep = args[0];
877 int chanid = args[1];
878 return SYSRET(ipi_register_notification(ep, chanid));
881 static struct sysret kernel_ipi_delete(struct capability *cap,
882 int cmd, uintptr_t *args)
884 assert(cap->type == ObjType_Kernel);
886 return SYSRET(SYS_ERR_OK);
889 static struct sysret dispatcher_dump_ptables(struct capability *cap,
890 int cmd, uintptr_t *args)
892 assert(cap->type == ObjType_Dispatcher);
894 printf("kernel_dump_ptables\n");
896 struct dcb *dispatcher = cap->u.dispatcher.dcb;
898 paging_dump_tables(dispatcher);
900 return SYSRET(SYS_ERR_OK);
903 static struct sysret dispatcher_dump_capabilities(struct capability *cap,
904 int cmd, uintptr_t *args)
906 assert(cap->type == ObjType_Dispatcher);
908 printf("dispatcher_dump_capabilities\n");
910 struct dcb *dispatcher = cap->u.dispatcher.dcb;
912 errval_t err = debug_print_cababilities(dispatcher);
918 * \brief Activate performance monitoring
920 * Activates performance monitoring.
921 * \param xargs Expected parameters in args:
922 * - performance monitoring type
923 * - mask for given type
925 * - Also count in privileged mode
926 * - Number of counts before overflow. This parameter may be used to
927 * set tradeoff between accuracy and overhead. Set the counter to 0
928 * to deactivate the usage of APIC.
929 * - Endpoint capability to be invoked when the counter overflows.
930 * The buffer associated with the endpoint needs to be large enough
931 * to hold several overflow notifications depending on the overflow
934 static struct sysret performance_counter_activate(struct capability *cap,
935 int cmd, uintptr_t *args)
937 uint8_t event = args[0];
938 uint8_t umask = args[1];
939 uint8_t counter_id = args[2];
940 bool kernel = args[3];
941 uint64_t counter_value = args[4];
942 capaddr_t ep_addr = args[5];
945 struct capability *ep;
946 extern struct capability perfmon_callback_ep;
949 assert(ep_addr!=0 || counter_value==0);
952 perfmon_measure_start(event, umask, counter_id, kernel, counter_value);
956 err = caps_lookup_cap(&dcb_current->cspace.cap, ep_addr, CPTR_BITS, &ep,
958 if(err_is_fail(err)) {
962 perfmon_callback_ep = *ep;
965 return SYSRET(SYS_ERR_OK);
969 * \brief Write counter values.
971 static struct sysret performance_counter_write(struct capability *cap,
972 int cmd, uintptr_t *args)
974 uint8_t counter_id = args[0];
975 uint64_t counter_value = args[1];
977 perfmon_measure_write(counter_id, counter_value);
978 return SYSRET(SYS_ERR_OK);
982 * \brief Deactivate performance counters again.
984 static struct sysret performance_counter_deactivate(struct capability *cap,
985 int cmd, uintptr_t *args)
987 perfmon_measure_stop();
988 return SYSRET(SYS_ERR_OK);
992 * \brief Return system-wide unique ID of this ID cap.
994 static struct sysret handle_idcap_identify(struct capability *cap, int cmd,
998 struct sysret sysret = sys_idcap_identify(cap, &id);
1004 static struct sysret kernel_send_init_ipi(struct capability *cap, int cmd,
1007 coreid_t destination = args[0];
1008 // printk(LOG_DEBUG, "%s:%s:%d: destination=%"PRIuCOREID"\n",
1009 // __FILE__, __FUNCTION__, __LINE__, destination);
1011 apic_send_init_assert(destination, xapic_none);
1012 apic_send_init_deassert();
1014 return SYSRET(SYS_ERR_OK);
1017 static struct sysret kernel_send_start_ipi(struct capability *cap,
1021 coreid_t destination = args[0];
1022 genvaddr_t start_vector = X86_64_REAL_MODE_SEGMENT_TO_REAL_MODE_PAGE(X86_64_REAL_MODE_SEGMENT);
1023 // printk(LOG_DEBUG, "%s:%d: destination=%"PRIuCOREID" start_vector=%"PRIxGENVADDR"\n",
1024 // __FILE__, __LINE__, destination, start_vector);
1026 apic_send_start_up(destination, xapic_none, start_vector);
1028 return SYSRET(SYS_ERR_OK);
1031 static struct sysret kernel_get_global_phys(struct capability *cap,
1036 struct sysret sysret;
1037 sysret.value = mem_to_local_phys((lvaddr_t)global);
1038 sysret.error = SYS_ERR_OK;
1043 static struct sysret kernel_add_kcb(struct capability *kern_cap,
1044 int cmd, uintptr_t *args)
1046 uintptr_t kcb_addr = args[0];
1047 struct kcb *new_kcb = (struct kcb *)kcb_addr;
1049 return sys_kernel_add_kcb(new_kcb);
1052 static struct sysret kernel_remove_kcb(struct capability *kern_cap,
1053 int cmd, uintptr_t *args)
1055 printk(LOG_NOTE, "in kernel_remove_kcb invocation!\n");
1056 uintptr_t kcb_addr = args[0];
1057 struct kcb *to_remove = (struct kcb *)kcb_addr;
1059 return sys_kernel_remove_kcb(to_remove);
1062 static struct sysret kernel_suspend_kcb_sched(struct capability *kern_cap,
1063 int cmd, uintptr_t *args)
1065 printk(LOG_NOTE, "in kernel_suspend_kcb_sched invocation!\n");
1066 return sys_kernel_suspend_kcb_sched((bool)args[0]);
1069 static struct sysret handle_kcb_identify(struct capability *to,
1070 int cmd, uintptr_t *args)
1072 return sys_handle_kcb_identify(to, (struct frame_identity *)args[0]);
1076 typedef struct sysret (*invocation_handler_t)(struct capability *to,
1077 int cmd, uintptr_t *args);
1079 static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
1080 [ObjType_Dispatcher] = {
1081 [DispatcherCmd_Setup] = handle_dispatcher_setup,
1082 [DispatcherCmd_Properties] = handle_dispatcher_properties,
1084 [DispatcherCmd_SetupGuest] = handle_dispatcher_setup_guest,
1086 [DispatcherCmd_DumpPTables] = dispatcher_dump_ptables,
1087 [DispatcherCmd_DumpCapabilities] = dispatcher_dump_capabilities,
1088 [DispatcherCmd_Vmread] = handle_vmread,
1089 [DispatcherCmd_Vmwrite] = handle_vmwrite,
1090 [DispatcherCmd_Vmptrld] = handle_vmptrld,
1091 [DispatcherCmd_Vmclear] = handle_vmclear,
1093 [ObjType_KernelControlBlock] = {
1094 [FrameCmd_Identify] = handle_kcb_identify,
1097 [FrameCmd_Identify] = handle_frame_identify,
1099 [ObjType_DevFrame] = {
1100 [FrameCmd_Identify] = handle_frame_identify,
1103 [CNodeCmd_Copy] = handle_copy,
1104 [CNodeCmd_Mint] = handle_mint,
1105 [CNodeCmd_Retype] = handle_retype,
1106 [CNodeCmd_Create] = handle_create,
1107 [CNodeCmd_Delete] = handle_delete,
1108 [CNodeCmd_Revoke] = handle_revoke,
1109 [CNodeCmd_GetState] = handle_get_state,
1111 [ObjType_VNode_x86_64_pml4] = {
1112 [VNodeCmd_Identify] = handle_vnode_identify,
1113 [VNodeCmd_Map] = handle_map,
1114 [VNodeCmd_Unmap] = handle_unmap,
1116 [ObjType_VNode_x86_64_pdpt] = {
1117 [VNodeCmd_Identify] = handle_vnode_identify,
1118 [VNodeCmd_Map] = handle_map,
1119 [VNodeCmd_Unmap] = handle_unmap,
1121 [ObjType_VNode_x86_64_pdir] = {
1122 [VNodeCmd_Identify] = handle_vnode_identify,
1123 [VNodeCmd_Map] = handle_map,
1124 [VNodeCmd_Unmap] = handle_unmap,
1126 [ObjType_VNode_x86_64_ptable] = {
1127 [VNodeCmd_Identify] = handle_vnode_identify,
1128 [VNodeCmd_Map] = handle_map,
1129 [VNodeCmd_Unmap] = handle_unmap,
1131 [ObjType_Frame_Mapping] = {
1132 [MappingCmd_Destroy] = handle_mapping_destroy,
1133 [MappingCmd_Modify] = handle_mapping_modify,
1135 [ObjType_DevFrame_Mapping] = {
1136 [MappingCmd_Destroy] = handle_mapping_destroy,
1137 [MappingCmd_Modify] = handle_mapping_modify,
1139 [ObjType_VNode_x86_64_pml4_Mapping] = {
1140 [MappingCmd_Destroy] = handle_mapping_destroy,
1141 [MappingCmd_Modify] = handle_mapping_modify,
1143 [ObjType_VNode_x86_64_pdpt_Mapping] = {
1144 [MappingCmd_Destroy] = handle_mapping_destroy,
1145 [MappingCmd_Modify] = handle_mapping_modify,
1147 [ObjType_VNode_x86_64_pdir_Mapping] = {
1148 [MappingCmd_Destroy] = handle_mapping_destroy,
1149 [MappingCmd_Modify] = handle_mapping_modify,
1151 [ObjType_VNode_x86_64_ptable_Mapping] = {
1152 [MappingCmd_Destroy] = handle_mapping_destroy,
1153 [MappingCmd_Modify] = handle_mapping_modify,
1155 [ObjType_Kernel] = {
1156 [KernelCmd_Get_core_id] = monitor_get_core_id,
1157 [KernelCmd_Get_arch_id] = monitor_get_arch_id,
1158 [KernelCmd_Identify_cap] = monitor_identify_cap,
1159 [KernelCmd_Identify_domains_cap] = monitor_identify_domains_cap,
1160 [KernelCmd_Remote_relations] = monitor_remote_relations,
1161 [KernelCmd_Cap_has_relations] = monitor_cap_has_relations,
1162 [KernelCmd_Create_cap] = monitor_create_cap,
1163 [KernelCmd_Copy_existing] = monitor_copy_existing,
1164 [KernelCmd_Nullify_cap] = monitor_nullify_cap,
1165 [KernelCmd_Setup_trace] = handle_trace_setup,
1166 [KernelCmd_Register] = monitor_handle_register,
1167 [KernelCmd_Domain_Id] = monitor_handle_domain_id,
1168 [KernelCmd_Get_cap_owner] = monitor_get_cap_owner,
1169 [KernelCmd_Set_cap_owner] = monitor_set_cap_owner,
1170 [KernelCmd_Lock_cap] = monitor_lock_cap,
1171 [KernelCmd_Unlock_cap] = monitor_unlock_cap,
1172 [KernelCmd_Retype] = monitor_handle_retype,
1173 [KernelCmd_Has_descendants] = monitor_handle_has_descendants,
1174 [KernelCmd_Delete_last] = monitor_handle_delete_last,
1175 [KernelCmd_Delete_foreigns] = monitor_handle_delete_foreigns,
1176 [KernelCmd_Revoke_mark_target] = monitor_handle_revoke_mark_tgt,
1177 [KernelCmd_Revoke_mark_relations] = monitor_handle_revoke_mark_rels,
1178 [KernelCmd_Delete_step] = monitor_handle_delete_step,
1179 [KernelCmd_Clear_step] = monitor_handle_clear_step,
1180 [KernelCmd_Sync_timer] = monitor_handle_sync_timer,
1181 [KernelCmd_IPI_Register] = kernel_ipi_register,
1182 [KernelCmd_IPI_Delete] = kernel_ipi_delete,
1183 [KernelCmd_GetGlobalPhys] = kernel_get_global_phys,
1184 [KernelCmd_Add_kcb] = kernel_add_kcb,
1185 [KernelCmd_Remove_kcb] = kernel_remove_kcb,
1186 [KernelCmd_Suspend_kcb_sched] = kernel_suspend_kcb_sched,
1189 [IPICmd_Send_Start] = kernel_send_start_ipi,
1190 [IPICmd_Send_Init] = kernel_send_init_ipi,
1192 [ObjType_IRQDest] = {
1193 [IRQDestCmd_Connect] = handle_irqdest_connect,
1194 [IRQDestCmd_GetVector] = handle_irqdest_get_vector
1196 [ObjType_IRQSrc] = {
1197 [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
1199 [ObjType_IRQTable] = {
1200 [IRQTableCmd_Alloc] = handle_irq_table_alloc,
1201 [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
1202 [IRQTableCmd_Set] = handle_irq_table_set,
1203 [IRQTableCmd_Delete] = handle_irq_table_delete
1206 [IOCmd_Outb] = handle_io,
1207 [IOCmd_Outw] = handle_io,
1208 [IOCmd_Outd] = handle_io,
1209 [IOCmd_Inb] = handle_io,
1210 [IOCmd_Inw] = handle_io,
1211 [IOCmd_Ind] = handle_io
1213 [ObjType_Notify_IPI] = {
1214 [NotifyCmd_Send] = handle_ipi_notify_send
1216 [ObjType_PerfMon] = {
1217 [PerfmonCmd_Activate] = performance_counter_activate,
1218 [PerfmonCmd_Deactivate] = performance_counter_deactivate,
1219 [PerfmonCmd_Write] = performance_counter_write,
1222 [IDCmd_Identify] = handle_idcap_identify,
1226 /* syscall C entry point; called only from entry.S so no prototype in header */
1227 struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
1228 uint64_t *args, uint64_t rflags, uint64_t rip);
1229 struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
1230 uint64_t *args, uint64_t rflags, uint64_t rip)
1232 struct sysret retval = { .error = SYS_ERR_OK, .value = 0 };
1235 case SYSCALL_INVOKE: /* Handle capability invocation */
1237 // unpack "header" word
1238 capaddr_t invoke_cptr = arg0 >> 32;
1239 uint8_t send_bits = arg0 >> 24;
1240 uint8_t invoke_bits = arg0 >> 16;
1241 uint8_t length_words = arg0 >> 8;
1242 uint8_t flags = arg0;
1244 debug(SUBSYS_SYSCALL, "sys_invoke(0x%x(%d), 0x%lx)\n",
1245 invoke_cptr, invoke_bits, arg1);
1247 // Capability to invoke
1248 struct capability *to = NULL;
1249 retval.error = caps_lookup_cap(&dcb_current->cspace.cap, invoke_cptr,
1250 invoke_bits, &to, CAPRIGHTS_READ);
1251 if (err_is_fail(retval.error)) {
1256 assert(to->type < ObjType_Num);
1258 // Endpoint cap, do LMP
1259 if (to->type == ObjType_EndPoint) {
1260 struct dcb *listener = to->u.endpoint.listener;
1261 assert(listener != NULL);
1263 if (listener->disp == 0) {
1264 retval.error = SYS_ERR_LMP_NO_TARGET;
1268 /* limit length of message from buggy/malicious sender */
1269 length_words = MIN(length_words, LMP_MSG_LENGTH);
1271 // does the sender want to yield their timeslice on success?
1272 bool sync = flags & LMP_FLAG_SYNC;
1273 // does the sender want to yield to the target if undeliverable?
1274 bool yield = flags & LMP_FLAG_YIELD;
1275 // is the cap (if present) to be deleted on send?
1276 bool give_away = flags & LMP_FLAG_GIVEAWAY;
1278 // try to deliver message
1279 retval.error = lmp_deliver(to, dcb_current, args, length_words,
1280 arg1, send_bits, give_away);
1282 /* Switch to reciever upon successful delivery with sync flag,
1283 * or (some cases of) unsuccessful delivery with yield flag */
1284 enum err_code err_code = err_no(retval.error);
1285 if ((sync && err_is_ok(retval.error)) ||
1286 (yield && (err_code == SYS_ERR_LMP_BUF_OVERFLOW
1287 || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
1288 || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
1289 || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED))
1291 if (err_is_fail(retval.error)) {
1292 struct dispatcher_shared_generic *current_disp =
1293 get_dispatcher_shared_generic(dcb_current->disp);
1294 struct dispatcher_shared_generic *listener_disp =
1295 get_dispatcher_shared_generic(listener->disp);
1296 debug(SUBSYS_DISPATCH, "LMP failed; %.*s yields to %.*s: %u\n",
1297 DISP_NAME_LEN, current_disp->name,
1298 DISP_NAME_LEN, listener_disp->name, err_code);
1301 // special-case context switch: ensure correct state in current DCB
1302 dispatcher_handle_t handle = dcb_current->disp;
1303 struct dispatcher_shared_x86_64 *disp =
1304 get_dispatcher_shared_x86_64(handle);
1305 dcb_current->disabled = dispatcher_is_disabled_ip(handle, rip);
1306 struct registers_x86_64 *save_area;
1307 if (dcb_current->disabled) {
1308 save_area = &disp->disabled_save_area;
1310 save_area = &disp->enabled_save_area;
1313 // Should be enabled. Else, how do we do an invocation??
1314 if(dcb_current->disabled) {
1315 panic("Dispatcher needs to be enabled for this invocation");
1318 // save calling dispatcher's registers, so that when the dispatcher
1319 // next runs, it has a valid state in the relevant save area.
1320 // Save RIP, RFLAGS, RSP and set RAX (return value) for later resume
1321 save_area->rax = retval.error; // XXX: x86 1st return register
1322 save_area->rip = rip;
1323 save_area->eflags = rflags;
1324 save_area->rsp = user_stack_save;
1326 if(!dcb_current->is_vm_guest) {
1327 /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
1328 __asm ("mov %%fs, %[fs] \n\t"
1329 "mov %%gs, %[gs] \n\t"
1330 "mov %[zero], %%fs \n\t"
1331 "mov %[zero], %%gs \n\t"
1334 [fs] "m" (save_area->fs),
1335 [gs] "m" (save_area->gs),
1341 lpaddr_t lpaddr = gen_phys_to_local_phys(dcb_current->guest_desc.vmcb.cap.u.frame.base);
1343 amd_vmcb_initialize(&vmcb, (void *)local_phys_to_mem(lpaddr));
1344 save_area->fs = amd_vmcb_fs_selector_rd(&vmcb);
1345 save_area->gs = amd_vmcb_gs_selector_rd(&vmcb);
1348 err = vmread(VMX_GUEST_FS_SEL, (uint64_t *)&save_area->fs);
1349 err += vmread(VMX_GUEST_GS_SEL, (uint64_t *)&save_area->gs);
1350 assert(err_is_ok(err));
1353 panic("VM Guests not supported on Xeon Phi");
1357 dispatch(to->u.endpoint.listener);
1358 panic("dispatch returned");
1360 } else { // not endpoint cap, call kernel handler through dispatch table
1361 uint64_t cmd = args[0];
1362 if (cmd >= CAP_MAX_CMD) {
1363 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1367 // Call the invocation
1368 invocation_handler_t invocation = invocations[to->type][cmd];
1369 if(invocation == NULL) {
1370 printk(LOG_WARN, "invocation not found. type: %"PRIu32", cmd: %"PRIu64"\n",
1372 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1374 retval = invocation(to, cmd, &args[1]);
1380 // Yield the CPU to the next dispatcher
1382 TRACE(KERNEL, SC_YIELD, 0);
1383 retval = sys_yield((capaddr_t)arg0);
1384 TRACE(KERNEL, SC_YIELD, 1);
1387 // NOP system call for benchmarking purposes
1391 // Debug print system call
1393 TRACE(KERNEL, SC_PRINT, 0);
1394 retval.error = sys_print((char *)arg0, arg1);
1395 TRACE(KERNEL, SC_PRINT, 1);
1399 // FIXME: this should be a kernel cap invocation or similarly restricted
1400 case SYSCALL_REBOOT:
1404 case SYSCALL_X86_FPU_TRAP_ON:
1408 case SYSCALL_X86_RELOAD_LDT:
1409 maybe_reload_ldt(dcb_current, true);
1412 // Temporarily suspend the CPU
1413 case SYSCALL_SUSPEND:
1414 TRACE(KERNEL, SC_SUSPEND, 0);
1415 retval = sys_suspend((bool)arg0);
1416 TRACE(KERNEL, SC_SUSPEND, 1);
1419 case SYSCALL_GET_ABS_TIME:
1420 retval = sys_get_absolute_time();
1425 case DEBUG_CONTEXT_COUNTER_RESET:
1426 dispatch_csc_reset();
1429 case DEBUG_CONTEXT_COUNTER_READ:
1430 retval.value = dispatch_get_csc();
1433 case DEBUG_TIMESLICE_COUNTER_READ:
1434 retval.value = kernel_now;
1437 case DEBUG_FLUSH_CACHE:
1441 case DEBUG_SEND_IPI:
1442 apic_send_std_ipi(arg1, args[0], args[1]);
1445 case DEBUG_SET_BREAKPOINT:
1446 debugregs_set_breakpoint(arg1, args[0], args[1]);
1449 case DEBUG_GET_TSC_PER_MS:
1450 retval.value = timing_get_tsc_per_ms();
1453 case DEBUG_GET_APIC_TIMER:
1454 retval.value = apic_timer_get_count();
1457 case DEBUG_GET_APIC_TICKS_PER_SEC:
1458 retval.value = timing_get_apic_ticks_per_sec();
1461 case DEBUG_TRACE_PMEM_CTRL:
1462 #ifdef TRACE_PMEM_CAPS
1464 caps_trace_ctrl(arg1, args[0], args[1]);
1466 caps_trace_ctrl(arg1, 0, 0);
1470 retval.error = SYS_ERR_OK;
1474 case DEBUG_GET_APIC_ID:
1475 retval.value = apic_get_id();
1478 case DEBUG_CREATE_IRQ_SRC_CAP:
1479 retval.error = irq_debug_create_src_cap(arg1, args[0], args[1], args[2]);
1483 printk(LOG_ERR, "invalid sys_debug msg type\n");
1488 printk(LOG_ERR, "sys_syscall: Illegal system call! "
1489 "(0x%lx, 0x%lx, 0x%lx)\n", syscall, arg0, arg1);
1490 retval.error = SYS_ERR_ILLEGAL_SYSCALL;
1494 // If dcb_current got removed, dispatch someone else
1495 if (dcb_current == NULL) {
1496 assert(err_is_ok(retval.error));
1497 dispatch(schedule());
1500 if (syscall == SYSCALL_INVOKE) {
1501 debug(SUBSYS_SYSCALL, "invoke returning 0x%lx 0x%lx\n",
1502 retval.error, retval.value);