armv8: Port irq cap invocations
[barrelfish] / kernel / arch / armv8 / syscall.c
1 /*
2  * Copyright (c) 2009,2011,2015, ETH Zurich.
3  * Copyright (c) 2015, Hewlett Packard Enterprise Development LP.
4  * All rights reserved.
5  *
6  * This file is distributed under the terms in the attached LICENSE file.
7  * If you do not find this file, copies can be found by writing to:
8  * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
9  */
10
11 #include <kernel.h>
12
13 #include <barrelfish_kpi/lmp.h>
14 #include <barrelfish_kpi/syscalls.h>
15 #include <barrelfish_kpi/sys_debug.h>
16 #include <barrelfish_kpi/platform.h>
17 #include <mdb/mdb_tree.h>
18
19 #include <arm_hal.h>
20 #include <irq.h>
21
22 #include <paging_kernel_arch.h>
23 #include <dispatch.h>
24 #include <exec.h>
25 #include <stdio.h>
26 #include <sys_debug.h>
27 #include <syscall.h>
28 #include <start_aps.h>
29 #include <useraccess.h>
30 #include <systime.h>
31 #include <psci.h>
32 #include <arch/arm/gic.h>
33 #include <arch/arm/platform.h>
34 #include <arch/arm/syscall_arm.h>
35
36 // helper macros  for invocation handler definitions
37 #define INVOCATION_HANDLER(func) \
38 static struct sysret \
39 func( \
40     struct capability *kernel_cap, \
41     arch_registers_state_t* context, \
42     int argc \
43     )
44
45 #define INVOCATION_PRELUDE(n) \
46     assert(n == argc); \
47     struct registers_aarch64_syscall_args* sa = &context->syscall_args
48
49 #define NYI(str) printf("armv8: %s\n", str)
50
51 __attribute__((noreturn)) void sys_syscall_kernel(void);
52 __attribute__((noreturn))
53 void sys_syscall(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3,
54                  uint64_t a4, uint64_t a5, uint64_t a6,
55                  arch_registers_state_t *context);
56
57 __attribute__((noreturn))
58 void sys_syscall_kernel(void)
59 {
60     panic("Why is the kernel making a system call?");
61 }
62
63 static struct sysret
64 handle_dispatcher_setup(
65     struct capability* to,
66     arch_registers_state_t* context,
67     int argc
68     )
69 {
70     assert(8 == argc);
71
72     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
73
74     capaddr_t root  = sa->arg2;
75     uint8_t   level = sa->arg3;
76     capaddr_t vptr  = sa->arg4;
77     capaddr_t dptr  = sa->arg5;
78     bool      run   = sa->arg6;
79     capaddr_t odptr = sa->arg7;
80
81     return sys_dispatcher_setup(to, root, level, vptr, dptr, run, odptr);
82 }
83
84 static struct sysret
85 handle_dispatcher_properties(
86     struct capability* to,
87     arch_registers_state_t* context,
88     int argc
89     )
90 {
91     assert(8 == argc);
92
93     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
94
95     enum task_type type = (enum task_type)(sa->arg3 >> 16);
96     uint16_t weight = sa->arg3 & 0xffff;
97
98     return sys_dispatcher_properties(to, type, sa->arg4,
99                                      sa->arg5, sa->arg6, sa->arg7, weight);
100 }
101
102 static struct sysret
103 handle_dispatcher_perfmon(
104     struct capability* to,
105     arch_registers_state_t* context,
106     int argc
107     )
108 {
109     /* XXX - implement this? */
110     return SYSRET(SYS_ERR_PERFMON_NOT_AVAILABLE);
111 }
112
113 static struct sysret copy_or_mint(struct capability *root,
114                                   struct registers_aarch64_syscall_args* args,
115                                   bool mint)
116 {
117     /* Retrieve arguments */
118     capaddr_t dest_cspace_cptr = args->arg2;
119     capaddr_t destcn_cptr      = args->arg3;
120     uint64_t  dest_slot        = args->arg4;
121     capaddr_t source_croot_ptr = args->arg5;
122     capaddr_t source_cptr      = args->arg6;
123     uint8_t destcn_level       = args->arg7;
124     uint8_t source_level       = args->x8;
125     uint64_t param1, param2;
126     // params only sent if mint operation
127     if (mint) {
128         param1 = args->x9;
129         param2 = args->x10;
130     } else {
131         param1 = param2 = 0;
132     }
133
134     struct sysret sr = sys_copy_or_mint(root, dest_cspace_cptr, destcn_cptr, dest_slot,
135                                         source_croot_ptr, source_cptr,
136                                         destcn_level, source_level,
137                                         param1, param2, mint);
138     return sr;
139 }
140
141 static struct sysret
142 handle_mint(
143     struct capability* root,
144     arch_registers_state_t* context,
145     int argc
146     )
147 {
148     assert(11 == argc);
149
150     return copy_or_mint(root, &context->syscall_args, true);
151 }
152
153 static struct sysret
154 handle_copy(
155     struct capability* root,
156     arch_registers_state_t* context,
157     int argc
158     )
159 {
160     assert(9 == argc);
161
162     return copy_or_mint(root, &context->syscall_args, false);
163 }
164
165 static struct sysret
166 handle_retype_common(
167     struct capability* root,
168     bool from_monitor,
169     arch_registers_state_t* context,
170     int argc
171     )
172 {
173     assert(11 == argc);
174
175     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
176
177     // Source capability cptr
178     capaddr_t source_croot     = sa->arg2;
179     capaddr_t source_cptr      = sa->arg3;
180     gensize_t offset           = sa->arg4;
181     uint32_t word              = sa->arg5;
182     // Type to retype to
183     enum objtype type          = word & 0xFFFF;
184     assert(type < ObjType_Num);
185     // Object size for variable-sized types
186     gensize_t objsize          = sa->arg6;
187     // number of new objects
188     size_t count               = sa->arg7;
189     // Destination cspace cptr
190     capaddr_t dest_cspace_cptr = sa->x8;
191     // Destination cnode cptr
192     capaddr_t dest_cnode_cptr  = sa->x9;
193     // Destination slot number
194     capaddr_t dest_slot        = sa->x10;
195     // Level of destination cnode in destination cspace
196     uint8_t dest_cnode_level   = (word >> 16) & 0xF;
197
198     return sys_retype(root, source_croot, source_cptr, offset, type,
199                       objsize, count, dest_cspace_cptr, dest_cnode_cptr,
200                       dest_cnode_level, dest_slot, from_monitor);
201 }
202
203 static struct sysret
204 handle_retype(
205     struct capability* root,
206     arch_registers_state_t* context,
207     int argc
208     )
209 {
210     return handle_retype_common(root, false, context, argc);
211 }
212
213 static struct sysret
214 handle_delete(
215     struct capability* root,
216     arch_registers_state_t* context,
217     int argc
218     )
219 {
220     assert(4 == argc);
221
222     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
223
224     capaddr_t cptr = (capaddr_t)sa->arg2;
225     int     bits = (int)sa->arg3;
226
227     return sys_delete(root, cptr, bits);
228 }
229
230 static struct sysret
231 handle_create(
232     struct capability* root,
233     arch_registers_state_t* context,
234     int argc
235     )
236 {
237     assert(7 == argc);
238
239     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
240
241     enum objtype type      = sa->arg2;
242     size_t       objsize   = sa->arg3;
243     capaddr_t    dest_cptr = sa->arg4;
244     uint8_t      dest_level= sa->arg5;
245     cslot_t      dest_slot = sa->arg6;
246     printk(LOG_NOTE, "type = %d, bytes = %zu\n", type, objsize);
247
248     return sys_create(root, type, objsize, dest_cptr, dest_level, dest_slot);
249 }
250
251 static struct sysret
252 handle_revoke(
253     struct capability* root,
254     arch_registers_state_t* context,
255     int argc
256     )
257 {
258     assert(4 == argc);
259
260     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
261
262     capaddr_t cptr = (capaddr_t)sa->arg2;
263     int     bits = (int)sa->arg3;
264
265     return sys_revoke(root, cptr, bits);
266 }
267
268 static struct sysret
269 handle_get_state(
270     struct capability* root,
271     arch_registers_state_t* context,
272     int argc
273     )
274 {
275     assert(4 == argc);
276
277     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
278
279     capaddr_t cptr = (capaddr_t)sa->arg2;
280     int       bits = (int)sa->arg3;
281
282     return sys_get_state(root, cptr, bits);
283 }
284
285 static struct sysret
286 handle_get_size(
287     struct capability* root,
288     arch_registers_state_t* context,
289     int argc
290     )
291 {
292     assert(2 == argc);
293     return sys_get_size_l1cnode(root);
294 }
295
296 static struct sysret
297 handle_resize(
298     struct capability* root,
299     arch_registers_state_t* context,
300     int argc
301     )
302 {
303     INVOCATION_PRELUDE(5);
304
305     capaddr_t newroot_ptr = sa->arg2;
306     capaddr_t retcn_ptr   = sa->arg3;
307     cslot_t   retslot     = sa->arg4;
308
309     return sys_resize_l1cnode(root, newroot_ptr, retcn_ptr, retslot);
310 }
311
312 static struct sysret
313 handle_map(
314     struct capability *ptable,
315     arch_registers_state_t *context,
316     int argc
317     )
318 {
319     assert(10 == argc);
320
321     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
322
323     /* Retrieve arguments */
324     capaddr_t source_root_cptr = (capaddr_t)sa->arg2;
325     capaddr_t source_cptr      = (capaddr_t)sa->arg3;
326     uintptr_t flags            = (uintptr_t)sa->arg4;
327     uintptr_t offset           = (uintptr_t)sa->arg5;
328     uintptr_t pte_count        = (uintptr_t)sa->arg6;
329     capaddr_t mcn_root         = (capaddr_t)sa->arg7;
330     capaddr_t mcn_addr         = (capaddr_t)sa->x8;
331     uint32_t  word             = sa->x9;
332     uint8_t   source_level     = word & 0xF;
333     uint8_t   mcn_level        = (word >> 4) & 0xF;
334     cslot_t   mapping_slot     = (word >> 8) & 0xFF;
335     cslot_t   slot             = (word >> 16) & 0xFFFF;
336
337     return sys_map(ptable, slot, source_root_cptr, source_cptr, source_level,
338                    flags, offset, pte_count, mcn_root, mcn_addr, mcn_level,
339                    mapping_slot);
340 }
341
342 static struct sysret
343 handle_unmap(
344     struct capability* ptable,
345     arch_registers_state_t* context,
346     int argc
347     )
348 {
349     assert(4 == argc);
350
351     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
352
353     /* Retrieve arguments */
354     capaddr_t  mapping_cptr  = (capaddr_t)sa->arg2;
355     int mapping_bits         = (int)sa->arg3 & 0xff;
356
357     errval_t err;
358     struct cte *mapping = NULL;
359     err = caps_lookup_slot(&dcb_current->cspace.cap, mapping_cptr, mapping_bits,
360                            &mapping, CAPRIGHTS_READ_WRITE);
361     if (err_is_fail(err)) {
362         printk(LOG_NOTE, "%s: caps_lookup_slot: %ld\n", __FUNCTION__, err);
363         return SYSRET(err_push(err, SYS_ERR_CAP_NOT_FOUND));
364     }
365
366     err = page_mappings_unmap(ptable, mapping);
367     if (err_is_fail(err)) {
368         printk(LOG_NOTE, "%s: page_mappings_unmap: %ld\n", __FUNCTION__, err);
369     }
370     return SYSRET(err);
371 }
372
373 static struct sysret
374 handle_mapping_destroy(
375         struct capability *to,
376         arch_registers_state_t *context,
377         int argc)
378 {
379     panic("NYI!");
380     return SYSRET(SYS_ERR_OK);
381 }
382
383 static struct sysret
384 handle_mapping_modify(
385         struct capability *to,
386         arch_registers_state_t *context,
387         int argc
388         )
389 {
390     assert(6 == argc);
391     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
392
393     // Modify flags of (part of) mapped region of frame
394     assert(type_is_mapping(to->type));
395
396     // unpack arguments
397     size_t offset = sa->arg2; // in pages; of first page to modify from first
398                              // page in mapped region
399     size_t pages  = sa->arg3; // #pages to modify
400     size_t flags  = sa->arg4; // new flags
401
402     errval_t err = paging_modify_flags(to, offset, pages, flags);
403
404     return (struct sysret) {
405         .error = err,
406         .value = 0,
407     };
408 }
409
410 /// Different handler for cap operations performed by the monitor
411 INVOCATION_HANDLER(monitor_handle_retype)
412 {
413     assert(argc == 11);
414     return handle_retype_common(&dcb_current->cspace.cap, true, context, argc);
415 }
416
417 INVOCATION_HANDLER(monitor_handle_has_descendants)
418 {
419     INVOCATION_PRELUDE(3);
420     // check access to user pointer
421     if (!access_ok(ACCESS_READ, sa->arg2, sizeof(struct capability))) {
422         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
423     }
424
425     struct capability *src = (struct capability *)sa->arg2;
426
427     struct cte *next = mdb_find_greater(src, false);
428
429     return (struct sysret) {
430         .error = SYS_ERR_OK,
431         .value = (next && is_ancestor(&next->cap, src)),
432     };
433 }
434
435 INVOCATION_HANDLER(monitor_handle_is_retypeable)
436 {
437     INVOCATION_PRELUDE(6);
438     // check access to user pointer
439     if (!access_ok(ACCESS_READ, sa->arg2, sizeof(struct capability))) {
440         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
441     }
442
443     struct capability *src = (struct capability *)sa->arg2;
444
445     uintptr_t offset  = sa->arg3;
446     uintptr_t objsize = sa->arg4;
447     uintptr_t count   = sa->arg5;
448
449     return sys_monitor_is_retypeable(src, offset, objsize, count);
450 }
451
452 INVOCATION_HANDLER(monitor_handle_delete_last)
453 {
454     INVOCATION_PRELUDE(9);
455     capaddr_t root_caddr   = sa->arg2;
456     uint8_t   root_level   = sa->arg3;
457     capaddr_t target_caddr = sa->arg4;
458     uint8_t   target_level = sa->arg5;
459     capaddr_t retcn_caddr  = sa->arg6;
460     uint8_t retcn_level    = sa->arg7;
461     cslot_t retcn_slot     = sa->x8;
462
463     return sys_monitor_delete_last(root_caddr, root_level, target_caddr,
464                                    target_level, retcn_caddr, retcn_level, retcn_slot);
465 }
466
467 INVOCATION_HANDLER(monitor_handle_delete_foreigns)
468 {
469     INVOCATION_PRELUDE(4);
470     capaddr_t caddr = sa->arg2;
471     uint8_t bits = sa->arg3;
472     return sys_monitor_delete_foreigns(caddr, bits);
473 }
474
475 INVOCATION_HANDLER(monitor_handle_revoke_mark_tgt)
476 {
477     INVOCATION_PRELUDE(6);
478     capaddr_t root_caddr   = sa->arg2;
479     uint8_t root_vbits     = sa->arg3;
480     capaddr_t target_caddr = sa->arg4;
481     uint8_t target_vbits   = sa->arg5;
482
483     return sys_monitor_revoke_mark_tgt(root_caddr, root_vbits,
484                                        target_caddr, target_vbits);
485 }
486
487 INVOCATION_HANDLER(monitor_handle_revoke_mark_rels)
488 {
489     INVOCATION_PRELUDE(3);
490     // user pointer to src cap, check access
491     if (!access_ok(ACCESS_READ, sa->arg2, sizeof(struct capability))) {
492         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
493     }
494     struct capability *base = (struct capability*)sa->arg2;
495
496     return sys_monitor_revoke_mark_rels(base);
497 }
498
499 INVOCATION_HANDLER(monitor_handle_delete_step)
500 {
501     INVOCATION_PRELUDE(5);
502     capaddr_t ret_cn_addr = sa->arg2;
503     capaddr_t ret_cn_bits = sa->arg3;
504     capaddr_t ret_slot    = sa->arg4;
505
506     return sys_monitor_delete_step(ret_cn_addr, ret_cn_bits, ret_slot);
507 }
508
509 INVOCATION_HANDLER(monitor_handle_clear_step)
510 {
511     INVOCATION_PRELUDE(5);
512     capaddr_t ret_cn_addr = sa->arg2;
513     capaddr_t ret_cn_bits = sa->arg3;
514     capaddr_t ret_slot    = sa->arg4;
515
516     return sys_monitor_clear_step(ret_cn_addr, ret_cn_bits, ret_slot);
517 }
518
519
520 static struct sysret
521 monitor_get_core_id(
522     struct capability* to,
523     arch_registers_state_t* context,
524     int argc
525     )
526 {
527     assert(2 == argc);
528
529     return (struct sysret) { .error = SYS_ERR_OK, .value = my_core_id };
530 }
531
532 static struct sysret
533 monitor_get_arch_id(
534     struct capability* to,
535     arch_registers_state_t* context,
536     int argc
537     )
538 {
539     assert(2 == argc);
540
541     // TODO: ARM doesn't support multicore yet...
542     return (struct sysret) { .error = SYS_ERR_OK, .value = my_core_id };
543 }
544
545 INVOCATION_HANDLER(monitor_handle_domain_id)
546 {
547     INVOCATION_PRELUDE(4);
548     capaddr_t cptr       = sa->arg2;
549     domainid_t domain_id = sa->arg3;
550
551     return sys_monitor_domain_id(cptr, domain_id);
552 }
553
554 INVOCATION_HANDLER(monitor_get_cap_owner)
555 {
556     INVOCATION_PRELUDE(6);
557     capaddr_t root_addr = sa->arg2;
558     uint8_t root_bits   = sa->arg3;
559     capaddr_t cptr      = sa->arg4;
560     uint8_t bits        = sa->arg5;
561
562     return sys_get_cap_owner(root_addr, root_bits, cptr, bits);
563 }
564
565 INVOCATION_HANDLER(monitor_set_cap_owner)
566 {
567     INVOCATION_PRELUDE(7);
568     capaddr_t root_addr = sa->arg2;
569     uint8_t root_bits   = sa->arg3;
570     capaddr_t cptr      = sa->arg4;
571     uint8_t bits        = sa->arg5;
572     coreid_t owner      = sa->arg6;
573
574     return sys_set_cap_owner(root_addr, root_bits, cptr, bits, owner);
575 }
576
577 INVOCATION_HANDLER(monitor_lock_cap)
578 {
579     INVOCATION_PRELUDE(6);
580     capaddr_t root_addr = sa->arg2;
581     uint8_t root_bits   = sa->arg3;
582     capaddr_t cptr      = sa->arg4;
583     uint8_t bits        = sa->arg5;
584
585     return sys_lock_cap(root_addr, root_bits, cptr, bits);
586 }
587
588 INVOCATION_HANDLER(monitor_unlock_cap)
589 {
590     INVOCATION_PRELUDE(6);
591     capaddr_t root_addr = sa->arg2;
592     uint8_t root_bits   = sa->arg3;
593     capaddr_t cptr      = sa->arg4;
594     uint8_t bits        = sa->arg5;
595
596     return sys_unlock_cap(root_addr, root_bits, cptr, bits);
597 }
598
599 static struct sysret
600 monitor_handle_register(
601     struct capability* to,
602     arch_registers_state_t* context,
603     int argc
604     )
605 {
606     assert(3 == argc);
607
608     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
609
610     capaddr_t ep_caddr = (capaddr_t)sa->arg2;
611
612     return sys_monitor_register(ep_caddr);
613 }
614
615 INVOCATION_HANDLER(monitor_cap_has_relations)
616 {
617     INVOCATION_PRELUDE(5);
618     capaddr_t caddr = sa->arg2;
619     uint8_t vbits = sa->arg3;
620     uint8_t mask = sa->arg4;
621
622     return sys_cap_has_relations(caddr, vbits, mask);
623 }
624
625 INVOCATION_HANDLER(monitor_remote_relations)
626 {
627     INVOCATION_PRELUDE(7);
628     capaddr_t root_addr = sa->arg2;
629     int root_bits       = sa->arg3;
630     capaddr_t cptr      = sa->arg4;
631     int bits            = sa->arg5;
632     uint8_t relations   = sa->arg6 & 0xFF;
633     uint8_t mask        = (sa->arg6 >> 8) & 0xFF;
634
635     return sys_monitor_remote_relations(root_addr, root_bits, cptr, bits,
636                                         relations, mask);
637 }
638
639 INVOCATION_HANDLER(monitor_copy_existing)
640 {
641     INVOCATION_PRELUDE(7);
642     capaddr_t croot_cptr = sa->arg2;
643     capaddr_t cnode_cptr = sa->arg3;
644     int cnode_level      = sa->arg4;
645     size_t slot          = sa->arg5;
646
647     // user pointer to src cap, check access
648     if (!access_ok(ACCESS_READ, sa->arg6, sizeof(struct capability))) {
649         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
650     }
651     /* Get the raw metadata of the capability to create from user pointer */
652     struct capability *src = (struct capability *)sa->arg6;
653
654     return sys_monitor_copy_existing(src, croot_cptr, cnode_cptr, cnode_level, slot);
655 }
656
657 INVOCATION_HANDLER(monitor_nullify_cap)
658 {
659     INVOCATION_PRELUDE(4);
660     capaddr_t cptr = sa->arg2;
661     int bits       = sa->arg3;
662
663     return sys_monitor_nullify_cap(cptr, bits);
664 }
665
666 static struct sysret
667 monitor_create_cap(
668     struct capability *kernel_cap,
669     arch_registers_state_t* context,
670     int argc
671     )
672 {
673     assert(7 == argc);
674
675     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
676
677     /* Create the cap in the destination */
678     capaddr_t cnode_cptr = sa->arg2;
679     int cnode_vbits      = sa->arg3;
680     size_t slot          = sa->arg4;
681     coreid_t owner       = sa->arg5;
682     struct capability *src =
683         (struct capability*)sa->arg6;
684
685     /* Cannot create null caps */
686     if (src->type == ObjType_Null ) {
687         return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
688     }
689
690     /* For certain types, only foreign copies can be created here */
691     if ((src->type == ObjType_EndPointLMP || src->type == ObjType_Dispatcher
692          || src->type == ObjType_Kernel || src->type == ObjType_IRQTable)
693         && owner == my_core_id)
694     {
695         return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
696     }
697
698     return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
699                                             cnode_cptr, cnode_vbits,
700                                             slot, owner, src));
701 }
702
703 INVOCATION_HANDLER(monitor_get_platform)
704 {
705     INVOCATION_PRELUDE(3);
706     // check args
707     if (!access_ok(ACCESS_WRITE, sa->arg2, sizeof(struct platform_info))) {
708         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
709     }
710
711     platform_get_info((struct platform_info*)sa->arg2);
712
713     return SYSRET(SYS_ERR_OK);
714 }
715
716 INVOCATION_HANDLER(monitor_reclaim_ram)
717 {
718     INVOCATION_PRELUDE(5);
719     capaddr_t ret_cn_addr  = sa->arg2;
720     capaddr_t ret_cn_level = sa->arg3;
721     capaddr_t ret_slot     = sa->arg4;
722
723     return sys_monitor_reclaim_ram(ret_cn_addr, ret_cn_level, ret_slot);
724 }
725
726 /**
727  * \brief Spawn a new core and create a kernel cap for it.
728  */
729 static struct sysret
730 monitor_spawn_core(
731     struct capability *kernel_cap,
732     arch_registers_state_t* context,
733     int argc)
734 {
735     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
736
737     hwid_t core_id         = sa->arg2;
738     enum cpu_type cpu_type = sa->arg3;
739     genvaddr_t entry       = sa->arg4;
740     genpaddr_t context_id  = sa->arg5;
741     uint64_t psci_use_hvc  = sa->arg6;
742
743     psci_set_use_hvc(psci_use_hvc);
744     return sys_monitor_spawn_core(core_id, cpu_type, entry, context_id);
745 }
746
747 static struct sysret
748 monitor_identify_cap(
749     struct capability *kernel_cap,
750     arch_registers_state_t* context,
751     int argc)
752 {
753     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
754
755     capaddr_t cptr = sa->arg2;
756     int bits = sa->arg3;
757     struct capability *retbuf = (void *)sa->arg4;
758
759     return sys_monitor_identify_cap(&dcb_current->cspace.cap, cptr, bits, retbuf);
760 }
761
762 INVOCATION_HANDLER(monitor_identify_domains_cap)
763 {
764     /* XXX - why is this not used consistently? */
765     INVOCATION_PRELUDE(7);
766     errval_t err;
767
768     capaddr_t root_caddr = sa->arg2;
769     capaddr_t root_vbits = sa->arg3;
770     capaddr_t cptr       = sa->arg4;
771     int bits             = sa->arg5;
772     struct capability *retbuf = (void *)sa->arg6;
773
774     struct capability *root;
775     err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
776                           &root, CAPRIGHTS_READ);
777     if (err_is_fail(err)) {
778         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
779     }
780
781     return sys_monitor_identify_cap(root, cptr, bits, retbuf);
782 }
783
784 static struct sysret handle_irqsrc_get_vec_start(struct capability *to,
785         arch_registers_state_t* context,
786         int argc)
787 {
788     struct sysret ret;
789     ret.error = SYS_ERR_OK;
790     ret.value = to->u.irqsrc.vec_start;
791     return ret;
792 }
793
794 static struct sysret handle_irqsrc_get_vec_end(struct capability *to,
795         arch_registers_state_t* context,
796         int argc)
797 {
798     struct sysret ret;
799     ret.error = SYS_ERR_OK;
800     ret.value = to->u.irqsrc.vec_end;
801     return ret;
802 }
803
804
805 static struct sysret handle_irqdest_connect(struct capability* to,
806         arch_registers_state_t* context,
807         int argc)
808
809 {
810     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
811     return SYSRET(irq_connect(to, sa->arg2));
812 }
813
814 static struct sysret handle_irqdest_get_vector(struct capability *to,
815         arch_registers_state_t* context,
816         int argc)
817 {
818     struct sysret ret;
819     ret.error = SYS_ERR_OK;
820     ret.value = to->u.irqdest.vector;
821     return ret;
822 }
823
824 static struct sysret handle_irqdest_get_cpu(struct capability *to,
825         arch_registers_state_t* context,
826         int argc)
827 {
828     struct sysret ret;
829     ret.error = SYS_ERR_OK;
830     ret.value = to->u.irqdest.cpu;
831     return ret;
832 }
833
834 static struct sysret handle_irq_table_alloc_dest_cap(struct capability* to,
835         arch_registers_state_t* context,
836         int argc
837         )
838 {
839     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
840     return SYSRET(irq_table_alloc_dest_cap(sa->arg2, sa->arg3, sa->arg4, sa->arg5));
841 }
842
843 static struct sysret dispatcher_dump_ptables(
844     struct capability* to, arch_registers_state_t* context, int argc)
845 {
846     assert(to->type == ObjType_Dispatcher);
847     assert(2 == argc);
848
849     printf("kernel_dump_ptables\n");
850
851    // struct dcb *dispatcher = to->u.dispatcher.dcb;
852
853    // paging_dump_tables(dispatcher);
854
855     return SYSRET(SYS_ERR_OK);
856 }
857
858 static struct sysret dispatcher_dump_capabilities(struct capability *cap,
859         arch_registers_state_t* context, int argc)
860 {
861     assert(cap->type == ObjType_Dispatcher);
862     assert(2 == argc);
863     struct dcb *dispatcher = cap->u.dispatcher.dcb;
864     errval_t err = debug_print_cababilities(dispatcher);
865     return SYSRET(err);
866 }
867
868 static struct sysret handle_idcap_identify(struct capability *cap,
869                                            arch_registers_state_t *context,
870                                            int argc)
871 {
872     assert(cap->type == ObjType_ID);
873     assert(2 == argc);
874
875     idcap_id_t id;
876     struct sysret sysret = sys_idcap_identify(cap, &id);
877     sysret.value = id;
878
879     return sysret;
880 }
881
882 static struct sysret handle_cap_identify(struct capability *root,
883                                          arch_registers_state_t *context, int argc)
884 {
885     assert(5 == argc);
886
887     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
888
889     capaddr_t cptr = sa->arg2;
890     uint8_t level = sa->arg3;
891     struct capability *cap = (void *)sa->arg4;
892
893     return sys_identify_cap(root, cptr, level, cap);
894 }
895
896 static struct sysret handle_devid_create(struct capability *cap,
897                                          arch_registers_state_t *context,
898                                          int argc)
899 {
900     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
901
902     assert(cap->type == ObjType_DeviceIDManager);
903
904     capaddr_t cnode_cptr = sa->arg2;
905     capaddr_t cnode_level = sa->arg3;
906     uint16_t slot = sa->arg4;
907
908     uint32_t address = sa->arg5;
909     uint32_t segflags = sa->arg6;
910
911     struct capability devid;
912     devid.type = ObjType_DeviceID;
913     devid.u.deviceid.bus      = (uint8_t)(address >> 16);
914     devid.u.deviceid.device   = (uint8_t)(address >> 8);
915     devid.u.deviceid.function = (uint8_t)(address);
916     devid.u.deviceid.type     = (uint8_t)(address >> 24);
917     devid.u.deviceid.segment  = (uint16_t)(segflags >> 16);
918     devid.u.deviceid.flags    = (uint16_t)(segflags);
919
920     return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
921                                             cnode_cptr, cnode_level,
922                                             slot, my_core_id, &devid));
923 }
924
925 static struct sysret handle_kcb_identify(struct capability *to,
926                                   arch_registers_state_t *context,
927                                   int argc)
928 {
929     assert(3 == argc);
930
931     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
932
933     return sys_handle_kcb_identify(to, (struct frame_identity *)sa->arg2);
934 }
935
936 typedef struct sysret (*invocation_t)(struct capability*,
937                                       arch_registers_state_t*, int);
938
939 static invocation_t invocations[ObjType_Num][CAP_MAX_CMD] = {
940     [ObjType_Dispatcher] = {
941         [DispatcherCmd_Setup]       = handle_dispatcher_setup,
942         [DispatcherCmd_Properties]  = handle_dispatcher_properties,
943         [DispatcherCmd_PerfMon]     = handle_dispatcher_perfmon,
944         [DispatcherCmd_DumpPTables]  = dispatcher_dump_ptables,
945         [DispatcherCmd_DumpCapabilities] = dispatcher_dump_capabilities
946     },
947     [ObjType_KernelControlBlock] = {
948         [KCBCmd_Identify] = handle_kcb_identify
949     },
950     [ObjType_L1CNode] = {
951         [CNodeCmd_Copy]   = handle_copy,
952         [CNodeCmd_Mint]   = handle_mint,
953         [CNodeCmd_Retype] = handle_retype,
954         [CNodeCmd_Create] = handle_create,
955         [CNodeCmd_Delete] = handle_delete,
956         [CNodeCmd_Revoke] = handle_revoke,
957         [CNodeCmd_GetState] = handle_get_state,
958         [CNodeCmd_GetSize] = handle_get_size,
959         [CNodeCmd_Resize] = handle_resize,
960         [CNodeCmd_CapIdentify] = handle_cap_identify,
961     },
962     [ObjType_L2CNode] = {
963         [CNodeCmd_Copy]   = handle_copy,
964         [CNodeCmd_Mint]   = handle_mint,
965         [CNodeCmd_Retype] = handle_retype,
966         [CNodeCmd_Create] = handle_create,
967         [CNodeCmd_Delete] = handle_delete,
968         [CNodeCmd_Revoke] = handle_revoke,
969         [CNodeCmd_GetState] = handle_get_state,
970         [CNodeCmd_Resize] = handle_resize,
971         [CNodeCmd_CapIdentify] = handle_cap_identify,
972     },
973     [ObjType_VNode_AARCH64_l0] = {
974         [VNodeCmd_Map]   = handle_map,
975         [VNodeCmd_Unmap] = handle_unmap,
976     },
977     [ObjType_VNode_AARCH64_l1] = {
978         [VNodeCmd_Map]   = handle_map,
979         [VNodeCmd_Unmap] = handle_unmap,
980     },
981     [ObjType_VNode_AARCH64_l2] = {
982         [VNodeCmd_Map]   = handle_map,
983         [VNodeCmd_Unmap] = handle_unmap,
984     },
985     [ObjType_VNode_AARCH64_l3] = {
986         [VNodeCmd_Map]   = handle_map,
987         [VNodeCmd_Unmap] = handle_unmap,
988     },
989     [ObjType_Frame_Mapping] = {
990         [MappingCmd_Destroy] = handle_mapping_destroy,
991         [MappingCmd_Modify] = handle_mapping_modify,
992     },
993     [ObjType_DevFrame_Mapping] = {
994         [MappingCmd_Destroy] = handle_mapping_destroy,
995         [MappingCmd_Modify] = handle_mapping_modify,
996     },
997     [ObjType_VNode_AARCH64_l0_Mapping] = {
998         [MappingCmd_Destroy] = handle_mapping_destroy,
999         [MappingCmd_Modify] = handle_mapping_modify,
1000     },
1001     [ObjType_VNode_AARCH64_l1_Mapping] = {
1002         [MappingCmd_Destroy] = handle_mapping_destroy,
1003         [MappingCmd_Modify] = handle_mapping_modify,
1004     },
1005     [ObjType_VNode_AARCH64_l2_Mapping] = {
1006         [MappingCmd_Destroy] = handle_mapping_destroy,
1007         [MappingCmd_Modify] = handle_mapping_modify,
1008     },
1009     [ObjType_VNode_AARCH64_l3_Mapping] = {
1010         [MappingCmd_Destroy] = handle_mapping_destroy,
1011         [MappingCmd_Modify] = handle_mapping_modify,
1012     },
1013         [ObjType_IRQSrc] = {
1014         [IRQSrcCmd_GetVecStart] = handle_irqsrc_get_vec_start,
1015         [IRQSrcCmd_GetVecEnd] = handle_irqsrc_get_vec_end
1016         },
1017         [ObjType_IRQDest] = {
1018         [IRQDestCmd_Connect] = handle_irqdest_connect,
1019         [IRQDestCmd_GetVector] = handle_irqdest_get_vector,
1020         [IRQDestCmd_GetCpu] = handle_irqdest_get_cpu
1021         },
1022     [ObjType_IRQTable] = {
1023             [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
1024         },
1025     [ObjType_Kernel] = {
1026         [KernelCmd_Cap_has_relations] = monitor_cap_has_relations,
1027         [KernelCmd_Clear_step]        = monitor_handle_clear_step,
1028         [KernelCmd_Copy_existing]     = monitor_copy_existing,
1029         [KernelCmd_Create_cap]        = monitor_create_cap,
1030         [KernelCmd_Delete_foreigns]   = monitor_handle_delete_foreigns,
1031         [KernelCmd_Delete_last]       = monitor_handle_delete_last,
1032         [KernelCmd_Delete_step]       = monitor_handle_delete_step,
1033         [KernelCmd_Domain_Id]         = monitor_handle_domain_id,
1034         [KernelCmd_Get_arch_id]       = monitor_get_arch_id,
1035         [KernelCmd_Get_cap_owner]     = monitor_get_cap_owner,
1036         [KernelCmd_Get_core_id]       = monitor_get_core_id,
1037         [KernelCmd_Has_descendants]   = monitor_handle_has_descendants,
1038         [KernelCmd_Identify_cap]      = monitor_identify_cap,
1039         [KernelCmd_Identify_domains_cap] = monitor_identify_domains_cap,
1040         [KernelCmd_Is_retypeable]     = monitor_handle_is_retypeable,
1041         [KernelCmd_Lock_cap]          = monitor_lock_cap,
1042         [KernelCmd_Nullify_cap]       = monitor_nullify_cap,
1043         [KernelCmd_Register]          = monitor_handle_register,
1044         [KernelCmd_Remote_relations]  = monitor_remote_relations,
1045         [KernelCmd_Retype]            = monitor_handle_retype,
1046         [KernelCmd_Revoke_mark_relations] = monitor_handle_revoke_mark_rels,
1047         [KernelCmd_Revoke_mark_target] = monitor_handle_revoke_mark_tgt,
1048         [KernelCmd_Set_cap_owner]     = monitor_set_cap_owner,
1049         /* XXX - why is this commented out? */
1050         //[KernelCmd_Setup_trace]       = handle_trace_setup,
1051         [KernelCmd_Spawn_core]        = monitor_spawn_core,
1052         [KernelCmd_Unlock_cap]        = monitor_unlock_cap,
1053         [KernelCmd_Get_platform]        = monitor_get_platform,
1054         [KernelCmd_ReclaimRAM]        = monitor_reclaim_ram,
1055     },
1056     [ObjType_IPI] = {
1057         [IPICmd_Send_Start]  = monitor_spawn_core,
1058     },
1059     [ObjType_ID] = {
1060         [IDCmd_Identify] = handle_idcap_identify
1061     },
1062     [ObjType_DeviceIDManager] = {
1063             [DeviceIDManager_CreateID] = handle_devid_create,
1064     },
1065 };
1066
1067 static struct sysret
1068 handle_invoke(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3,
1069               uint64_t a4, uint64_t a5, uint64_t a6,
1070               arch_registers_state_t *context)
1071 {
1072     struct registers_aarch64_syscall_args* sa = &context->syscall_args;
1073
1074     /* XXX - can we generate them from the same source? */
1075     //
1076     // Must match lib/barrelfish/include/arch/aarch64/arch/invocations.h
1077     //
1078     uint8_t   flags       = FIELD(24,4,a0);
1079     uint8_t   invoke_bits = FIELD(16,8,a0);
1080     capaddr_t invoke_cptr = a1;
1081
1082 // printf("%s: %zd %zd\n", __func__, systime_now(), armv8_CNTP_TVAL_EL0_rd(NULL));
1083     debug(SUBSYS_SYSCALL, "sys_invoke(0x%"PRIxCADDR"(%d))\n",
1084                 invoke_cptr, invoke_bits);
1085
1086     struct sysret r = { .error = SYS_ERR_OK, .value = 0 };
1087
1088     struct capability* to;
1089     r.error = caps_lookup_cap(&dcb_current->cspace.cap,
1090                               invoke_cptr, invoke_bits,
1091                               &to, CAPRIGHTS_READ);
1092     if (err_is_ok(r.error))
1093     {
1094         assert(to != NULL);
1095         assert(to->type < ObjType_Num);
1096
1097         if (ObjType_EndPointLMP == to->type && !(flags & LMP_FLAG_IDENTIFY))
1098         {
1099             struct dcb *listener = to->u.endpointlmp.listener;
1100             assert(listener != NULL);
1101
1102             if (listener->disp) {
1103                 uint8_t length_words = FIELD(28,8,a0);
1104                 uint8_t send_bits    = FIELD(8,8,a0);
1105                 capaddr_t send_cptr = a2;
1106                 /* limit length of message from buggy/malicious sender */
1107                 length_words = min(length_words, LMP_MSG_LENGTH);
1108
1109                 // does the sender want to yield their timeslice on success?
1110                 bool sync = flags & LMP_FLAG_SYNC;
1111                 // does the sender want to yield to the target
1112                 // if undeliverable?
1113                 bool yield = flags & LMP_FLAG_YIELD;
1114                 // is the cap (if present) to be deleted on send?
1115                 bool give_away = flags & LMP_FLAG_GIVEAWAY;
1116
1117                 // Message registers in context are
1118                 // discontinguous for now so copy message words
1119                 // to temporary container. This is fixable, but
1120                 // not in this pass.
1121                 uintptr_t msg_words[LMP_MSG_LENGTH];
1122                 msg_words[0] = a3;
1123                 msg_words[1] = a4;
1124                 msg_words[2] = a5;
1125                 msg_words[3] = a6;
1126                 STATIC_ASSERT(LMP_MSG_LENGTH == 4, "Oops");
1127
1128                 // try to deliver message
1129                 r.error = lmp_deliver(to, dcb_current, msg_words,
1130                                       length_words, send_cptr, send_bits, give_away);
1131
1132                 /* Switch to reciever upon successful delivery
1133                  * with sync flag, or (some cases of)
1134                  * unsuccessful delivery with yield flag */
1135                 enum err_code err_code = err_no(r.error);
1136                 if ((sync && err_is_ok(r.error)) ||
1137                     (yield && (err_code == SYS_ERR_LMP_BUF_OVERFLOW
1138                                || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
1139                                || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
1140                                || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED))
1141                    ) {
1142                     if (err_is_fail(r.error)) {
1143                         struct dispatcher_shared_generic *current_disp =
1144                             get_dispatcher_shared_generic(dcb_current->disp);
1145                         struct dispatcher_shared_generic *listener_disp =
1146                             get_dispatcher_shared_generic(listener->disp);
1147                         debug(SUBSYS_DISPATCH, "LMP failed; %.*s yields to %.*s: %u\n",
1148                               DISP_NAME_LEN, current_disp->name,
1149                               DISP_NAME_LEN, listener_disp->name, err_code);
1150                     }
1151
1152                     // special-case context switch: ensure correct state in
1153                     // current DCB
1154                     dispatcher_handle_t handle = dcb_current->disp;
1155                     struct dispatcher_shared_aarch64 *disp =
1156                         get_dispatcher_shared_aarch64(handle);
1157                     dcb_current->disabled =
1158                         dispatcher_is_disabled_ip(handle, context->named.pc);
1159                     if (dcb_current->disabled) {
1160                         assert(context == &disp->disabled_save_area);
1161                         context->named.x0 = r.error;
1162                     }
1163                     else {
1164                         assert(context == &disp->enabled_save_area);
1165                         context->named.x0 = r.error;
1166                     }
1167                     dispatch(listener);
1168                 }
1169             }
1170             else {
1171                 r.error = SYS_ERR_LMP_NO_TARGET;
1172             }
1173         }
1174         else
1175         {
1176             uint8_t cmd = FIELD(8,8,a0);
1177             int argc    = FIELD(4,4,a0);
1178             if (cmd < CAP_MAX_CMD)
1179             {
1180                 invocation_t invocation = invocations[to->type][cmd];
1181                 if (invocation)
1182                 {
1183                     /* XXX - Until we improve the syscall path, we're stacking
1184                      * all of the argument registers here.  Yuck. */
1185                     sa->arg0 = a0;
1186                     sa->arg1 = a1;
1187                     sa->arg2 = a2;
1188                     sa->arg3 = a3;
1189                     sa->arg4 = a4;
1190                     sa->arg5 = a5;
1191                     sa->arg6 = a6;
1192
1193                     r = invocation(to, context, argc);
1194                     if (!dcb_current)
1195                     {
1196                         // dcb_current was removed, dispatch someone else
1197                         assert(err_is_ok(r.error));
1198                         dispatch(schedule());
1199                     }
1200                     return r;
1201                 }
1202             }
1203             printk(LOG_ERR, "Bad invocation type %d cmd %d\n", to->type, cmd);
1204             r.error = SYS_ERR_ILLEGAL_INVOCATION;
1205         }
1206     }
1207
1208     return r;
1209 }
1210
1211 static struct sysret handle_debug_syscall(int msg)
1212 {
1213     struct sysret retval = { .error = SYS_ERR_OK };
1214     switch (msg) {
1215         case DEBUG_FLUSH_CACHE:
1216             /* XXX - implement me */
1217             break;
1218
1219         case DEBUG_CONTEXT_COUNTER_RESET:
1220             dispatch_csc_reset();
1221             break;
1222
1223         case DEBUG_CONTEXT_COUNTER_READ:
1224             retval.value = dispatch_get_csc();
1225             break;
1226
1227         case DEBUG_TIMESLICE_COUNTER_READ:
1228             retval.value = systime_now();
1229             break;
1230
1231         case DEBUG_HARDWARE_TIMER_READ:
1232             retval.value = systime_now();
1233             break;
1234
1235         case DEBUG_HARDWARE_TIMER_HERTZ_READ:
1236             retval.value = systime_frequency;
1237             break;
1238
1239         case DEBUG_GET_TSC_PER_MS:
1240             // XXX: Implement if possible at all.
1241             retval.value = 1;
1242             break;
1243
1244         default:
1245             printk(LOG_ERR, "invalid sys_debug msg type %d\n", msg);
1246             retval.error = err_push(retval.error, SYS_ERR_ILLEGAL_SYSCALL);
1247     }
1248     return retval;
1249 }
1250
1251
1252 /* XXX - function documentation is inconsistent. */
1253 /**
1254  * System call dispatch routine.
1255  *
1256  * @return struct sysret for all calls except yield / invoke.
1257  *
1258  * The first 8 syscall arguments are passed in registers, preserved by the
1259  * assembly stub.
1260  *
1261  */
1262 void sys_syscall(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3,
1263                  uint64_t a4, uint64_t a5, uint64_t a6,
1264                  arch_registers_state_t *context)
1265 {
1266     // XXX
1267     // Set dcb_current->disabled correctly.  This should really be
1268     // done in exceptions.S
1269     // XXX
1270
1271     assert(dcb_current != NULL);
1272     dispatcher_handle_t handle = dcb_current->disp;
1273     struct dispatcher_shared_generic *disp =
1274         get_dispatcher_shared_generic(handle);
1275     assert((struct dispatcher_shared_generic *)(dcb_current->disp) == disp);
1276     if (dispatcher_is_disabled_ip((dispatcher_handle_t)disp, context->named.pc)) {
1277         assert(context == dispatcher_get_disabled_save_area((dispatcher_handle_t)disp));
1278         dcb_current->disabled = true;
1279     } else {
1280         assert(context == dispatcher_get_enabled_save_area((dispatcher_handle_t)disp));
1281         dcb_current->disabled = false;
1282     }
1283     // TODO: ARMv7 gets this from assembly code.
1284     // assert(disabled == dcb_current->disabled);
1285
1286     STATIC_ASSERT_OFFSETOF(struct sysret, error, 0);
1287
1288     int syscall = FIELD(0,4,a0);
1289     int argc    = FIELD(4,4,a0);
1290
1291
1292     debug(SUBSYS_SYSCALL, "syscall: syscall=%d, argc=%d\n", syscall, argc);
1293 //    debug(SUBSYS_SYSCALL, "syscall: disabled=%d\n", disabled);
1294     debug(SUBSYS_SYSCALL, "syscall: context=0x%"PRIxLVADDR", disp=0x%"PRIxLVADDR"\n",
1295             context, disp );
1296
1297     struct sysret r = { .error = SYS_ERR_INVARGS_SYSCALL, .value = 0 };
1298
1299     switch (syscall)
1300     {
1301         case SYSCALL_INVOKE:
1302             r = handle_invoke(a0, a1, a2, a3, a4, a5, a6, context);
1303             break;
1304
1305         case SYSCALL_YIELD:
1306             if (argc == 2) {
1307                 r = sys_yield((capaddr_t)a1);
1308             }
1309             break;
1310
1311         case SYSCALL_NOP:
1312             r.error = SYS_ERR_OK;
1313             break;
1314
1315         case SYSCALL_PRINT:
1316             if (argc == 3) {
1317                 /* XXX - The user can pass arbitrary bad pointers and lengths
1318                  * here! */
1319                 r.error = sys_print((const char*)a1, (size_t)a2);
1320             }
1321             break;
1322
1323         case SYSCALL_DEBUG:
1324             if (a1 == DEBUG_CREATE_IRQ_SRC_CAP) {
1325                 r.error = irq_debug_create_src_cap(a2, a3, a4, a5, a6);
1326             } else if (argc == 2) {
1327                 r = handle_debug_syscall(a1);
1328             }
1329
1330             break;
1331
1332         default:
1333             printf("Illegal syscall %u\n", syscall);
1334             r.error = SYS_ERR_ILLEGAL_SYSCALL;
1335             break;
1336     }
1337
1338     if (r.error) {
1339         debug(SUBSYS_SYSCALL, "syscall failed %016"PRIx64
1340                               " => %016"PRIxERRV"\n", a0, r.error);
1341     }
1342
1343     /* XXX - shouldn't stack & unstack these. */
1344     context->named.x0 = r.error;
1345     context->named.x1 = r.value;
1346
1347     debug(SUBSYS_SYSCALL, "syscall: Resuming; dcb->disabled=%d, disp->disabled=%d\n",
1348           dcb_current->disabled, disp->disabled);
1349
1350     resume(context);
1351 }