armv7-m (heteropanda) builds.
[barrelfish] / kernel / arch / arm / syscall.c
1 /*
2  * Copyright (c) 2009, 2011, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <kernel.h>
11
12 #include <barrelfish_kpi/lmp.h>
13 #include <barrelfish_kpi/syscalls.h>
14 #include <barrelfish_kpi/sys_debug.h>
15 #include <mdb/mdb_tree.h>
16
17 #include <arm_hal.h>
18 #include <irq.h>
19
20 #include <paging_kernel_arch.h>
21 #include <dispatch.h>
22 #include <exec.h>
23 #include <stdio.h>
24 #include <sys_debug.h>
25 #include <syscall.h>
26 #include <arch/arm/syscall_arm.h>
27 #include <start_aps.h>
28 #include <useraccess.h>
29
30 // helper macros  for invocation handler definitions
31 #define INVOCATION_HANDLER(func) \
32 static struct sysret \
33 func( \
34     struct capability *kernel_cap, \
35     arch_registers_state_t* context, \
36     int argc \
37     )
38
39 #define INVOCATION_PRELUDE(n) \
40     assert(n == argc); \
41     struct registers_arm_syscall_args* sa = &context->syscall_args
42
43 /* XXX - not revision-independent. */
44 #ifdef __ARCH_ARM_5__
45 #define NYI(str) printf("armv5: %s\n", str)
46 #elif __ARCH_ARM_7M__
47 #define NYI(str) printf("armv7-m: %s\n", str)
48 #else
49 #define NYI(str) printf("(arch?): %s\n", str)
50 #endif
51
52
53
54 __attribute__((noreturn)) void sys_syscall_kernel(void);
55 __attribute__((noreturn)) void sys_syscall(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(7 == argc);
71
72     struct registers_arm_syscall_args* sa = &context->syscall_args;
73
74     capaddr_t   odptr    = sa->arg2;
75     capaddr_t   cptr     = sa->arg3;
76     uintptr_t rundepth = sa->arg4;
77     int       depth    = rundepth & 0xff;
78     int       run      = rundepth >> 8;
79     capaddr_t   vptr     = sa->arg5;
80     capaddr_t   dptr     = sa->arg6;
81
82     return sys_dispatcher_setup(to, cptr, depth, vptr, dptr, run, odptr);
83 }
84
85 static struct sysret
86 handle_dispatcher_properties(
87     struct capability* to,
88     arch_registers_state_t* context,
89     int argc
90     )
91 {
92     assert(8 == argc);
93
94     struct registers_arm_syscall_args* sa = &context->syscall_args;
95
96     enum task_type type = (enum task_type)(sa->arg3 >> 16);
97     uint16_t weight = sa->arg3 & 0xffff;
98
99     return sys_dispatcher_properties(to, type, sa->arg4,
100                                      sa->arg5, sa->arg6, sa->arg7, weight);
101 }
102
103 static struct sysret
104 handle_dispatcher_perfmon(
105     struct capability* to,
106     arch_registers_state_t* context,
107     int argc
108     )
109 {
110     /* XXX - implement this? */
111     return SYSRET(SYS_ERR_PERFMON_NOT_AVAILABLE);
112 }
113
114 static struct sysret
115 handle_frame_identify(
116     struct capability* to,
117     arch_registers_state_t* context,
118     int argc
119     )
120 {
121     assert(2 == argc);
122
123     assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame);
124     assert((to->u.frame.base & BASE_PAGE_MASK) == 0);
125     assert(to->u.frame.bits < BASE_PAGE_SIZE);
126
127     return (struct sysret) {
128         .error = SYS_ERR_OK,
129         .value = to->u.frame.base | to->u.frame.bits,
130     };
131 }
132
133 static struct sysret
134 handle_frame_modify_flags(
135         struct capability *to,
136         arch_registers_state_t *context,
137         int argc
138         )
139 {
140     // Modify flags of (part of) mapped region of frame
141     assert (5 == argc);
142
143     assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame);
144
145     // unpack arguments
146     struct registers_arm_syscall_args* sa = &context->syscall_args;
147     size_t offset = sa->arg2; // in pages; of first page to modify from first
148                               // page in mapped region
149     size_t pages  = sa->arg3; // #pages to modify
150     size_t flags  = sa->arg4; // new flags
151
152     paging_modify_flags(to, offset, pages, flags);
153
154     return (struct sysret) {
155         .error = SYS_ERR_OK,
156         .value = 0,
157     };
158 }
159
160 static struct sysret
161 handle_mint(
162     struct capability* root,
163     arch_registers_state_t* context,
164     int argc
165     )
166 {
167     assert(7 == argc);
168
169     struct registers_arm_syscall_args* sa = &context->syscall_args;
170
171     capaddr_t destcn_cptr  = sa->arg2;
172     capaddr_t source_cptr  = sa->arg3;
173     capaddr_t dest_slot    = sa->arg4 >> 16;
174     int     destcn_vbits = (sa->arg4 >> 8) & 0xff;
175     int     source_vbits = sa->arg4 & 0xff;
176
177     return sys_copy_or_mint(root, destcn_cptr, dest_slot, source_cptr,
178                             destcn_vbits, source_vbits, sa->arg5, sa->arg6, true);
179 }
180
181 static struct sysret
182 handle_copy(
183     struct capability* root,
184     arch_registers_state_t* context,
185     int argc
186     )
187 {
188     assert(5 == argc);
189
190     struct registers_arm_syscall_args* sa = &context->syscall_args;
191
192     capaddr_t destcn_cptr  = sa->arg2;
193     capaddr_t source_cptr  = sa->arg3;
194     capaddr_t dest_slot    = sa->arg4 >> 16;
195     int     destcn_vbits = (sa->arg4 >> 8) & 0xff;
196     int     source_vbits = sa->arg4 & 0xff;
197
198     return sys_copy_or_mint(root, destcn_cptr, dest_slot, source_cptr,
199                             destcn_vbits, source_vbits, 0, 0, false);
200 }
201
202 static struct sysret
203 handle_retype_common(
204     struct capability* root,
205     bool from_monitor,
206     arch_registers_state_t* context,
207     int argc
208     )
209 {
210     assert(6 == argc);
211
212     struct registers_arm_syscall_args* sa = &context->syscall_args;
213
214     // Source capability cptr
215     capaddr_t source_cptr      = sa->arg2;
216     uintptr_t word           = sa->arg3;
217     // Type to retype to
218     enum objtype type        = word >> 16;
219     // Object bits for variable-sized types
220     uint8_t objbits          = (word >> 8) & 0xff;
221     // Destination cnode cptr
222     capaddr_t  dest_cnode_cptr = sa->arg4;
223     // Destination slot number
224     capaddr_t dest_slot        = sa->arg5;
225     // Valid bits in destination cnode cptr
226     uint8_t dest_vbits       = (word & 0xff);
227
228     return sys_retype(root, source_cptr, type, objbits, dest_cnode_cptr,
229                       dest_slot, dest_vbits, from_monitor);
230 }
231
232 static struct sysret
233 handle_retype(
234     struct capability* root,
235     arch_registers_state_t* context,
236     int argc
237     )
238 {
239     return handle_retype_common(root, false, context, argc);
240 }
241
242 static struct sysret
243 handle_delete(
244     struct capability* root,
245     arch_registers_state_t* context,
246     int argc
247     )
248 {
249     assert(4 == argc);
250
251     struct registers_arm_syscall_args* sa = &context->syscall_args;
252
253     capaddr_t cptr = (capaddr_t)sa->arg2;
254     int     bits = (int)sa->arg3;
255
256     return sys_delete(root, cptr, bits);
257 }
258
259 static struct sysret
260 handle_create(
261     struct capability* root,
262     arch_registers_state_t* context,
263     int argc
264     )
265 {
266     assert(5 == argc);
267
268     struct registers_arm_syscall_args* sa = &context->syscall_args;
269
270     enum objtype type      = (sa->arg2 >> 16) & 0xffff;
271     uint8_t      objbits   = (sa->arg2 >> 8) & 0xff;
272     capaddr_t    dest_cptr = sa->arg3;
273     cslot_t      dest_slot = sa->arg4;
274     int          bits      = sa->arg2 & 0xff;
275     printk(LOG_NOTE, "type = %d, bits = %d\n", type, bits);
276
277     return sys_create(root, type, objbits, dest_cptr, dest_slot, bits);
278 }
279
280 static struct sysret
281 handle_revoke(
282     struct capability* root,
283     arch_registers_state_t* context,
284     int argc
285     )
286 {
287     assert(4 == argc);
288
289     struct registers_arm_syscall_args* sa = &context->syscall_args;
290
291     capaddr_t cptr = (capaddr_t)sa->arg2;
292     int     bits = (int)sa->arg3;
293
294     return sys_revoke(root, cptr, bits);
295 }
296
297 static struct sysret
298 handle_get_state(
299     struct capability* root,
300     arch_registers_state_t* context,
301     int argc
302     )
303 {
304     assert(4 == argc);
305
306     struct registers_arm_syscall_args* sa = &context->syscall_args;
307
308     capaddr_t cptr = (capaddr_t)sa->arg2;
309     int       bits = (int)sa->arg3;
310
311     return sys_get_state(root, cptr, bits);
312 }
313
314 static struct sysret
315 handle_map(
316     struct capability *ptable,
317     arch_registers_state_t *context,
318     int argc
319     )
320 {
321     assert(7 == argc);
322
323     struct registers_arm_syscall_args* sa = &context->syscall_args;
324
325     /* Retrieve arguments */
326     capaddr_t  source_cptr   = (capaddr_t)sa->arg2;
327     capaddr_t dest_slot      = ((capaddr_t)sa->arg3) >> 16;
328     int      source_vbits  = ((int)sa->arg3) & 0xff;
329     uintptr_t flags, offset,pte_count;
330     flags = (uintptr_t)sa->arg4;
331     offset = (uintptr_t)sa->arg5;
332     pte_count = (uintptr_t)sa->arg6;
333
334     return sys_map(ptable, dest_slot, source_cptr, source_vbits,
335                    flags, offset, pte_count);
336 }
337
338 static struct sysret
339 handle_unmap(
340     struct capability* ptable,
341     arch_registers_state_t* context,
342     int argc
343     )
344 {
345     assert(4 == argc);
346
347     struct registers_arm_syscall_args* sa = &context->syscall_args;
348
349     /* Retrieve arguments */
350     capaddr_t  mapping_cptr  = (capaddr_t)sa->arg2;
351     int mapping_bits         = (((int)sa->arg3) >> 24) & 0xff;
352     size_t pte_count         = (((size_t)sa->arg3) >> 12) & 0xfff;
353     pte_count               += 1;
354     size_t entry             = ((size_t)sa->arg3) & 0xfff;
355
356     errval_t err;
357     struct cte *mapping = NULL;
358     err = caps_lookup_slot(&dcb_current->cspace.cap, mapping_cptr, mapping_bits,
359                            &mapping, CAPRIGHTS_READ_WRITE);
360     if (err_is_fail(err)) {
361         return SYSRET(err_push(err, SYS_ERR_CAP_NOT_FOUND));
362     }
363
364     err = page_mappings_unmap(ptable, mapping, entry, pte_count);
365     return SYSRET(err);
366 }
367
368 /// Different handler for cap operations performed by the monitor
369 INVOCATION_HANDLER(monitor_handle_retype)
370 {
371     INVOCATION_PRELUDE(8);
372     errval_t err;
373
374     struct capability *root;
375     err = caps_lookup_cap(&dcb_current->cspace.cap, sa->arg6,
376             sa->arg7, &root, CAPRIGHTS_READ);
377     if (err_is_fail(err)) {
378         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
379     }
380
381     /* XXX: this hides the first argument which retype_common doesn't know
382      * about */
383     return handle_retype_common(root, true, context, 6);
384 }
385
386 INVOCATION_HANDLER(monitor_handle_has_descendants)
387 {
388     INVOCATION_PRELUDE(3);
389     // check access to user pointer
390     if (!access_ok(ACCESS_READ, sa->arg2, sizeof(struct capability))) {
391         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
392     }
393
394     struct capability *src = (struct capability *)sa->arg2;
395
396     struct cte *next = mdb_find_greater(src, false);
397
398     return (struct sysret) {
399         .error = SYS_ERR_OK,
400         .value = (next && is_ancestor(&next->cap, src)),
401     };
402 }
403
404 INVOCATION_HANDLER(monitor_handle_delete_last)
405 {
406     INVOCATION_PRELUDE(7);
407     capaddr_t root_caddr = sa->arg2;
408     capaddr_t target_caddr = sa->arg3;
409     capaddr_t retcn_caddr = sa->arg4;
410     cslot_t retcn_slot = sa->arg5;
411     uint8_t target_vbits = (sa->arg6>>16)&0xff;
412     uint8_t root_vbits = (sa->arg6>>8)&0xff;
413     uint8_t retcn_vbits = sa->arg6&0xff;
414
415     return sys_monitor_delete_last(root_caddr, root_vbits, target_caddr,
416                                    target_vbits, retcn_caddr, retcn_vbits, retcn_slot);
417 }
418
419 INVOCATION_HANDLER(monitor_handle_delete_foreigns)
420 {
421     INVOCATION_PRELUDE(4);
422     capaddr_t caddr = sa->arg2;
423     uint8_t bits = sa->arg3;
424     return sys_monitor_delete_foreigns(caddr, bits);
425 }
426
427 INVOCATION_HANDLER(monitor_handle_revoke_mark_tgt)
428 {
429     INVOCATION_PRELUDE(6);
430     capaddr_t root_caddr   = sa->arg2;
431     uint8_t root_vbits     = sa->arg3;
432     capaddr_t target_caddr = sa->arg4;
433     uint8_t target_vbits   = sa->arg5;
434
435     return sys_monitor_revoke_mark_tgt(root_caddr, root_vbits,
436                                        target_caddr, target_vbits);
437 }
438
439 INVOCATION_HANDLER(monitor_handle_revoke_mark_rels)
440 {
441     INVOCATION_PRELUDE(3);
442     // user pointer to src cap, check access
443     if (!access_ok(ACCESS_READ, sa->arg2, sizeof(struct capability))) {
444         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
445     }
446     struct capability *base = (struct capability*)sa->arg2;
447
448     return sys_monitor_revoke_mark_rels(base);
449 }
450
451 INVOCATION_HANDLER(monitor_handle_delete_step)
452 {
453     INVOCATION_PRELUDE(5);
454     capaddr_t ret_cn_addr = sa->arg2;
455     capaddr_t ret_cn_bits = sa->arg3;
456     capaddr_t ret_slot    = sa->arg4;
457
458     return sys_monitor_delete_step(ret_cn_addr, ret_cn_bits, ret_slot);
459 }
460
461 INVOCATION_HANDLER(monitor_handle_clear_step)
462 {
463     INVOCATION_PRELUDE(5);
464     capaddr_t ret_cn_addr = sa->arg2;
465     capaddr_t ret_cn_bits = sa->arg3;
466     capaddr_t ret_slot    = sa->arg4;
467
468     return sys_monitor_clear_step(ret_cn_addr, ret_cn_bits, ret_slot);
469 }
470
471
472 static struct sysret
473 monitor_get_core_id(
474     struct capability* to,
475     arch_registers_state_t* context,
476     int argc
477     )
478 {
479     assert(2 == argc);
480
481     return (struct sysret) { .error = SYS_ERR_OK, .value = my_core_id };
482 }
483
484 static struct sysret
485 monitor_get_arch_id(
486     struct capability* to,
487     arch_registers_state_t* context,
488     int argc
489     )
490 {
491     assert(2 == argc);
492
493     // TODO: ARM doesn't support multicore yet...
494     return (struct sysret) { .error = SYS_ERR_OK, .value = my_core_id };
495 }
496
497 INVOCATION_HANDLER(monitor_handle_domain_id)
498 {
499     INVOCATION_PRELUDE(4);
500     capaddr_t cptr       = sa->arg2;
501     domainid_t domain_id = sa->arg3;
502
503     return sys_monitor_domain_id(cptr, domain_id);
504 }
505
506 INVOCATION_HANDLER(monitor_get_cap_owner)
507 {
508     INVOCATION_PRELUDE(6);
509     capaddr_t root_addr = sa->arg2;
510     uint8_t root_bits   = sa->arg3;
511     capaddr_t cptr      = sa->arg4;
512     uint8_t bits        = sa->arg5;
513
514     return sys_get_cap_owner(root_addr, root_bits, cptr, bits);
515 }
516
517 INVOCATION_HANDLER(monitor_set_cap_owner)
518 {
519     INVOCATION_PRELUDE(7);
520     capaddr_t root_addr = sa->arg2;
521     uint8_t root_bits   = sa->arg3;
522     capaddr_t cptr      = sa->arg4;
523     uint8_t bits        = sa->arg5;
524     coreid_t owner      = sa->arg6;
525
526     return sys_set_cap_owner(root_addr, root_bits, cptr, bits, owner);
527 }
528
529 INVOCATION_HANDLER(monitor_lock_cap)
530 {
531     INVOCATION_PRELUDE(6);
532     capaddr_t root_addr = sa->arg2;
533     uint8_t root_bits   = sa->arg3;
534     capaddr_t cptr      = sa->arg4;
535     uint8_t bits        = sa->arg5;
536
537     return sys_lock_cap(root_addr, root_bits, cptr, bits);
538 }
539
540 INVOCATION_HANDLER(monitor_unlock_cap)
541 {
542     INVOCATION_PRELUDE(6);
543     capaddr_t root_addr = sa->arg2;
544     uint8_t root_bits   = sa->arg3;
545     capaddr_t cptr      = sa->arg4;
546     uint8_t bits        = sa->arg5;
547
548     return sys_unlock_cap(root_addr, root_bits, cptr, bits);
549 }
550
551 static struct sysret
552 monitor_handle_register(
553     struct capability* to,
554     arch_registers_state_t* context,
555     int argc
556     )
557 {
558     assert(3 == argc);
559
560     struct registers_arm_syscall_args* sa = &context->syscall_args;
561
562     capaddr_t ep_caddr = (capaddr_t)sa->arg2;
563
564     return sys_monitor_register(ep_caddr);
565 }
566
567 INVOCATION_HANDLER(monitor_cap_has_relations)
568 {
569     INVOCATION_PRELUDE(5);
570     capaddr_t caddr = sa->arg2;
571     uint8_t vbits = sa->arg3;
572     uint8_t mask = sa->arg4;
573
574     return sys_cap_has_relations(caddr, vbits, mask);
575 }
576
577 INVOCATION_HANDLER(monitor_remote_relations)
578 {
579     INVOCATION_PRELUDE(7);
580     capaddr_t root_addr = sa->arg2;
581     int root_bits       = sa->arg3;
582     capaddr_t cptr      = sa->arg4;
583     int bits            = sa->arg5;
584     uint8_t relations   = sa->arg6 & 0xFF;
585     uint8_t mask        = (sa->arg6 >> 8) & 0xFF;
586
587     return sys_monitor_remote_relations(root_addr, root_bits, cptr, bits,
588                                         relations, mask);
589 }
590
591 INVOCATION_HANDLER(monitor_copy_existing)
592 {
593     INVOCATION_PRELUDE(6);
594     capaddr_t cnode_cptr = sa->arg2;
595     int cnode_vbits    = sa->arg3;
596     size_t slot        = sa->arg4;
597
598     // user pointer to src cap, check access
599     if (!access_ok(ACCESS_READ, sa->arg5, sizeof(struct capability))) {
600         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
601     }
602     /* Get the raw metadata of the capability to create from user pointer */
603     struct capability *src = (struct capability *)sa->arg5;
604
605     return sys_monitor_copy_existing(src, cnode_cptr, cnode_vbits, slot);
606 }
607
608 INVOCATION_HANDLER(monitor_nullify_cap)
609 {
610     INVOCATION_PRELUDE(4);
611     capaddr_t cptr = sa->arg2;
612     int bits       = sa->arg3;
613
614     return sys_monitor_nullify_cap(cptr, bits);
615 }
616
617 static struct sysret
618 monitor_create_cap(
619     struct capability *kernel_cap,
620     arch_registers_state_t* context,
621     int argc
622     )
623 {
624     assert(7 == argc);
625
626     struct registers_arm_syscall_args* sa = &context->syscall_args;
627
628     /* XXX - not 64-bit clean */
629     //printf("%d: %"PRIu32", %"PRIu32", %"PRIu32", %"PRIu32", %"PRIu32", %"PRIu32"\n",
630     //        argc, sa->arg0, sa->arg1, sa->arg2, sa->arg3, sa->arg4, sa->arg5);
631
632     /* Create the cap in the destination */
633     capaddr_t cnode_cptr = sa->arg2;
634     int cnode_vbits      = sa->arg3;
635     size_t slot          = sa->arg4;
636     coreid_t owner       = sa->arg5;
637     struct capability *src =
638         (struct capability*)sa->arg6;
639
640     /* Cannot create null caps */
641     if (src->type == ObjType_Null ) {
642         return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
643     }
644
645     /* For certain types, only foreign copies can be created here */
646     if ((src->type == ObjType_EndPoint || src->type == ObjType_Dispatcher
647          || src->type == ObjType_Kernel || src->type == ObjType_IRQTable)
648         && owner == my_core_id)
649     {
650         return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
651     }
652
653     return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
654                                             cnode_cptr, cnode_vbits,
655                                             slot, owner, src));
656 }
657
658 /**
659  * \brief Spawn a new core and create a kernel cap for it.
660  */
661 static struct sysret
662 monitor_spawn_core(
663         struct capability *kernel_cap,
664     arch_registers_state_t* context,
665     int argc)
666 {
667     /* XXX - Why is this commented out? */
668         //assert(3 == argc);
669
670         struct registers_arm_syscall_args* sa = &context->syscall_args;
671
672         coreid_t core_id       = sa->arg2;
673     enum cpu_type cpu_type = sa->arg3;
674     genvaddr_t entry       = sa->arg5;
675
676     return sys_monitor_spawn_core(core_id, cpu_type, entry);
677 }
678
679 static struct sysret
680 monitor_identify_cap(
681         struct capability *kernel_cap,
682     arch_registers_state_t* context,
683     int argc)
684 {
685         struct registers_arm_syscall_args* sa = &context->syscall_args;
686
687         capaddr_t cptr = sa->arg2;
688         int bits = sa->arg3;
689         struct capability *retbuf = (void *)sa->arg4;
690
691     return sys_monitor_identify_cap(&dcb_current->cspace.cap, cptr, bits, retbuf);
692 }
693
694 INVOCATION_HANDLER(monitor_identify_domains_cap)
695 {
696     /* XXX - why is this not used consistently? */
697     INVOCATION_PRELUDE(7);
698     errval_t err;
699
700     capaddr_t root_caddr = sa->arg2;
701     capaddr_t root_vbits = sa->arg3;
702     capaddr_t cptr       = sa->arg4;
703     int bits             = sa->arg5;
704     struct capability *retbuf = (void *)sa->arg6;
705
706     struct capability *root;
707     err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
708                           &root, CAPRIGHTS_READ);
709     if (err_is_fail(err)) {
710         return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
711     }
712
713     return sys_monitor_identify_cap(root, cptr, bits, retbuf);
714 }
715
716 static struct sysret handle_irq_table_set( struct capability* to,
717         arch_registers_state_t* context,
718         int argc
719         )
720 {
721 /* XXX - not revision-independent. */
722 /* XXX - this seems like a pretty serious limitation. */
723 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_5__)
724     NYI("can not handle userspace IRQs yet");
725     return SYSRET(SYS_ERR_IRQ_INVALID);
726 #else
727     struct registers_arm_syscall_args* sa = &context->syscall_args;
728
729     return SYSRET(irq_table_set(sa->arg2, sa->arg3));
730 #endif
731 }
732
733
734 static struct sysret handle_irq_table_delete( struct capability* to,
735         arch_registers_state_t* context,
736         int argc
737         )
738 {
739 /* XXX - not revision-independent. */
740 /* XXX - this seems like a pretty serious limitation. */
741 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_5__)
742     NYI("can not handle userspace IRQs yet");
743     return SYSRET(SYS_ERR_IRQ_INVALID);
744 #else
745     struct registers_arm_syscall_args* sa = &context->syscall_args;
746
747     return SYSRET(irq_table_delete(sa->arg2));
748 #endif
749 }
750
751
752 static struct sysret dispatcher_dump_ptables(
753     struct capability* to,
754     arch_registers_state_t* context,
755     int argc
756     )
757 {
758     assert(to->type == ObjType_Dispatcher);
759     assert(2 == argc);
760
761     printf("kernel_dump_ptables\n");
762
763     struct dcb *dispatcher = to->u.dispatcher.dcb;
764
765     paging_dump_tables(dispatcher);
766
767     return SYSRET(SYS_ERR_OK);
768 }
769
770 static struct sysret dispatcher_dump_capabilities(struct capability *cap,
771         arch_registers_state_t* context, int argc)
772 {
773     assert(cap->type == ObjType_Dispatcher);
774     assert(2 == argc);
775     struct dcb *dispatcher = cap->u.dispatcher.dcb;
776     errval_t err = debug_print_cababilities(dispatcher);
777     return SYSRET(err);
778 }
779
780 static struct sysret handle_idcap_identify(struct capability *to,
781                                            arch_registers_state_t *context,
782                                            int argc)
783 {
784     assert(to->type == ObjType_ID);
785     assert(3 == argc);
786
787     struct registers_arm_syscall_args* sa = &context->syscall_args;
788     idcap_id_t *idp = (idcap_id_t *) sa->arg2;
789
790     // Check validity of user space pointer
791     if (!access_ok(ACCESS_WRITE, (lvaddr_t) idp, sizeof(*idp)))  {
792         return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
793     }
794
795     return sys_idcap_identify(to, idp);
796 }
797
798
799 static struct sysret handle_kcb_identify(struct capability *to,
800                                   arch_registers_state_t *context,
801                                   int argc)
802 {
803     return sys_handle_kcb_identify(to);
804 }
805
806 typedef struct sysret (*invocation_t)(struct capability*, arch_registers_state_t*, int);
807
808 static invocation_t invocations[ObjType_Num][CAP_MAX_CMD] = {
809     [ObjType_Dispatcher] = {
810         [DispatcherCmd_Setup]       = handle_dispatcher_setup,
811         [DispatcherCmd_Properties]  = handle_dispatcher_properties,
812         [DispatcherCmd_PerfMon]     = handle_dispatcher_perfmon,
813         [DispatcherCmd_DumpPTables]  = dispatcher_dump_ptables,
814         [DispatcherCmd_DumpCapabilities] = dispatcher_dump_capabilities
815     },
816     [ObjType_KernelControlBlock] = {
817         [FrameCmd_Identify] = handle_kcb_identify
818     },
819     [ObjType_Frame] = {
820         [FrameCmd_Identify] = handle_frame_identify,
821         [FrameCmd_ModifyFlags] = handle_frame_modify_flags,
822     },
823     [ObjType_DevFrame] = {
824         [FrameCmd_Identify] = handle_frame_identify,
825         [FrameCmd_ModifyFlags] = handle_frame_modify_flags,
826     },
827     [ObjType_CNode] = {
828         [CNodeCmd_Copy]     = handle_copy,
829         [CNodeCmd_Mint]     = handle_mint,
830         [CNodeCmd_Retype]   = handle_retype,
831         [CNodeCmd_Delete]   = handle_delete,
832         [CNodeCmd_Revoke]   = handle_revoke,
833         [CNodeCmd_Create]   = handle_create,
834         [CNodeCmd_GetState] = handle_get_state,
835     },
836     [ObjType_VNode_ARM_l1] = {
837         [VNodeCmd_Map]   = handle_map,
838         [VNodeCmd_Unmap] = handle_unmap,
839     },
840     [ObjType_VNode_ARM_l2] = {
841         [VNodeCmd_Map]   = handle_map,
842         [VNodeCmd_Unmap] = handle_unmap,
843     },
844     [ObjType_IRQTable] = {
845             [IRQTableCmd_Set] = handle_irq_table_set,
846             [IRQTableCmd_Delete] = handle_irq_table_delete,
847         },
848     [ObjType_Kernel] = {
849         [KernelCmd_Cap_has_relations] = monitor_cap_has_relations,
850         [KernelCmd_Clear_step]        = monitor_handle_clear_step,
851         [KernelCmd_Copy_existing]     = monitor_copy_existing,
852         [KernelCmd_Create_cap]        = monitor_create_cap,
853         [KernelCmd_Delete_foreigns]   = monitor_handle_delete_foreigns,
854         [KernelCmd_Delete_last]       = monitor_handle_delete_last,
855         [KernelCmd_Delete_step]       = monitor_handle_delete_step,
856         [KernelCmd_Domain_Id]         = monitor_handle_domain_id,
857         [KernelCmd_Get_arch_id]       = monitor_get_arch_id,
858         [KernelCmd_Get_cap_owner]     = monitor_get_cap_owner,
859         [KernelCmd_Get_core_id]       = monitor_get_core_id,
860         [KernelCmd_Has_descendants]   = monitor_handle_has_descendants,
861         [KernelCmd_Identify_cap]      = monitor_identify_cap,
862         [KernelCmd_Identify_domains_cap] = monitor_identify_domains_cap,
863         [KernelCmd_Lock_cap]          = monitor_lock_cap,
864         [KernelCmd_Nullify_cap]       = monitor_nullify_cap,
865         [KernelCmd_Register]          = monitor_handle_register,
866         [KernelCmd_Remote_relations]  = monitor_remote_relations,
867         [KernelCmd_Retype]            = monitor_handle_retype,
868         [KernelCmd_Revoke_mark_relations] = monitor_handle_revoke_mark_rels,
869         [KernelCmd_Revoke_mark_target] = monitor_handle_revoke_mark_tgt,
870         [KernelCmd_Set_cap_owner]     = monitor_set_cap_owner,
871         /* XXX - why is this commented out? */
872         //[KernelCmd_Setup_trace]       = handle_trace_setup,
873         [KernelCmd_Spawn_core]        = monitor_spawn_core,
874         [KernelCmd_Unlock_cap]        = monitor_unlock_cap,
875     },
876     [ObjType_IPI] = {
877         [IPICmd_Send_Start]  = monitor_spawn_core,
878     },
879     [ObjType_ID] = {
880         [IDCmd_Identify] = handle_idcap_identify
881     }
882 };
883
884 static struct sysret
885 handle_invoke(arch_registers_state_t *context, int argc)
886 {
887     struct registers_arm_syscall_args* sa = &context->syscall_args;
888
889     /* XXX - can we generate them from the same source? */
890     //
891     // Must match lib/barrelfish/include/arch/arm/arch/invocations.h
892     //
893     uint8_t  flags       = (sa->arg0 >> 24) & 0xf;
894     uint8_t  invoke_bits = (sa->arg0 >> 16) & 0xff;
895     capaddr_t  invoke_cptr = sa->arg1;
896
897     debug(SUBSYS_SYSCALL, "sys_invoke(0x%"PRIxCADDR"(%d))\n",
898                 invoke_cptr, invoke_bits);
899
900     struct sysret r = { .error = SYS_ERR_OK, .value = 0 };
901
902     struct capability* to;
903     r.error = caps_lookup_cap(&dcb_current->cspace.cap,
904                               invoke_cptr, invoke_bits,
905                               &to, CAPRIGHTS_READ);
906     if (err_is_ok(r.error))
907     {
908         assert(to != NULL);
909         assert(to->type < ObjType_Num);
910
911         if (ObjType_EndPoint == to->type)
912         {
913             struct dcb *listener = to->u.endpoint.listener;
914             assert(listener != NULL);
915
916             if (listener->disp) {
917                 /* XXX - not 64-bit clean */
918                 uint8_t length_words = (sa->arg0 >> 28) & 0xff;
919                 uint8_t send_bits = (sa->arg0 >> 8) & 0xff;
920                 capaddr_t send_cptr = sa->arg2;
921                 /* limit length of message from buggy/malicious sender */
922                 length_words = min(length_words, LMP_MSG_LENGTH);
923
924                 // does the sender want to yield their timeslice on success?
925                 bool sync = flags & LMP_FLAG_SYNC;
926                 // does the sender want to yield to the target
927                 // if undeliverable?
928                 bool yield = flags & LMP_FLAG_YIELD;
929                 // is the cap (if present) to be deleted on send?
930                 bool give_away = flags & LMP_FLAG_GIVEAWAY;
931
932                 // Message registers in context are
933                 // discontinguous for now so copy message words
934                 // to temporary container. This is fixable, but
935                 // not in this pass.
936                 uintptr_t msg_words[LMP_MSG_LENGTH];
937                 msg_words[0] = sa->arg3;
938                 msg_words[1] = sa->arg4;
939                 msg_words[2] = sa->arg5;
940                 msg_words[3] = sa->arg6;
941                 msg_words[4] = sa->arg7;
942                 msg_words[5] = sa->arg8;
943                 msg_words[6] = sa->arg9;
944                 msg_words[7] = sa->arg10;
945                 msg_words[8] = sa->arg11;
946                 STATIC_ASSERT(LMP_MSG_LENGTH == 9, "Oops");
947
948                 // try to deliver message
949                 r.error = lmp_deliver(to, dcb_current, msg_words,
950                                       length_words, send_cptr, send_bits, give_away);
951
952                 /* Switch to reciever upon successful delivery
953                  * with sync flag, or (some cases of)
954                  * unsuccessful delivery with yield flag */
955                 enum err_code err_code = err_no(r.error);
956                 if ((sync && err_is_ok(r.error)) ||
957                     (yield && (err_code == SYS_ERR_LMP_BUF_OVERFLOW
958                                || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
959                                || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
960                                || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED))
961                    ) {
962                     if (err_is_fail(r.error)) {
963                         struct dispatcher_shared_generic *current_disp =
964                             get_dispatcher_shared_generic(dcb_current->disp);
965                         struct dispatcher_shared_generic *listener_disp =
966                             get_dispatcher_shared_generic(listener->disp);
967                         debug(SUBSYS_DISPATCH, "LMP failed; %.*s yields to %.*s: %u\n",
968                               DISP_NAME_LEN, current_disp->name,
969                               DISP_NAME_LEN, listener_disp->name, err_code);
970                     }
971
972                     // special-case context switch: ensure correct state in current DCB
973                     dispatcher_handle_t handle = dcb_current->disp;
974                     struct dispatcher_shared_arm *disp =
975                         get_dispatcher_shared_arm(handle);
976                     dcb_current->disabled = dispatcher_is_disabled_ip(handle, context->named.pc);
977                     if (dcb_current->disabled) {
978                         assert(context == &disp->disabled_save_area);
979                         context->named.r0 = r.error;
980                     }
981                     else {
982                         assert(context == &disp->enabled_save_area);
983                         context->named.r0 = r.error;
984                     }
985                     dispatch(listener);
986                 }
987             }
988             else {
989                 r.error = SYS_ERR_LMP_NO_TARGET;
990             }
991         }
992         else
993         {
994             uint8_t cmd = (sa->arg0 >> 8)  & 0xff;
995             if (cmd < CAP_MAX_CMD)
996             {
997                 invocation_t invocation = invocations[to->type][cmd];
998                 if (invocation)
999                 {
1000                     r = invocation(to, context, argc);
1001                     if (!dcb_current)
1002                     {
1003                         // dcb_current was removed, dispatch someone else
1004                         assert(err_is_ok(r.error));
1005                         dispatch(schedule());
1006                     }
1007                     return r;
1008                 }
1009             }
1010             printk(LOG_ERR, "Bad invocation type %d cmd %d\n", to->type, cmd);
1011             r.error = SYS_ERR_ILLEGAL_INVOCATION;
1012         }
1013     }
1014
1015     return r;
1016 }
1017
1018 static struct sysret handle_debug_syscall(int msg)
1019 {
1020     struct sysret retval = { .error = SYS_ERR_OK };
1021     switch (msg) {
1022 #if !defined(__ARM_ARCH_7M__)
1023         case DEBUG_FLUSH_CACHE:
1024             cp15_invalidate_i_and_d_caches_fast();
1025             break;
1026 #endif
1027
1028         case DEBUG_CONTEXT_COUNTER_RESET:
1029             dispatch_csc_reset();
1030             break;
1031
1032         case DEBUG_CONTEXT_COUNTER_READ:
1033             retval.value = dispatch_get_csc();
1034             break;
1035
1036         case DEBUG_TIMESLICE_COUNTER_READ:
1037             retval.value = kernel_now;
1038             break;
1039
1040         case DEBUG_HARDWARE_TIMER_READ:
1041             retval.value = tsc_read();
1042             break;
1043
1044         case DEBUG_HARDWARE_TIMER_HERTZ_READ:
1045             retval.value = tsc_get_hz();
1046             break;
1047
1048         /* XXX - not revision-independent. */
1049 #if defined(__pandaboard__) && !defined(__ARM_ARCH_7M__)
1050         case DEBUG_HARDWARE_GLOBAL_TIMER_LOW:
1051             retval.value = gt_read_low();
1052             break;
1053
1054         case DEBUG_HARDWARE_GLOBAL_TIMER_HIGH:
1055             retval.value = gt_read_high();
1056             break;
1057 #endif
1058
1059         default:
1060             printk(LOG_ERR, "invalid sys_debug msg type %d\n", msg);
1061             retval.error = err_push(retval.error, SYS_ERR_ILLEGAL_SYSCALL);
1062     }
1063     return retval;
1064 }
1065
1066 /* XXX - function documentation is inconsistent. */
1067 /**
1068  * System call dispatch routine.
1069  *
1070  * @return struct sysret for all calls except yield / invoke.
1071  */
1072 /* XXX - why is this commented out? */
1073 //__attribute__((noreturn))
1074 void sys_syscall(arch_registers_state_t* context)
1075 {
1076     STATIC_ASSERT_OFFSETOF(struct sysret, error, 0);
1077
1078     struct registers_arm_syscall_args* sa = &context->syscall_args;
1079
1080     uintptr_t   syscall = sa->arg0 & 0xf;
1081     uintptr_t   argc    = (sa->arg0 >> 4) & 0xf;
1082
1083     struct sysret r = { .error = SYS_ERR_INVARGS_SYSCALL, .value = 0 };
1084
1085     switch (syscall)
1086     {
1087         case SYSCALL_INVOKE:
1088             r = handle_invoke(context, argc);
1089             break;
1090
1091         case SYSCALL_YIELD:
1092             if (argc == 2)
1093             {
1094                 r = sys_yield((capaddr_t)sa->arg1);
1095             }
1096             break;
1097
1098         case SYSCALL_NOP:
1099             break;
1100
1101         case SYSCALL_PRINT:
1102             if (argc == 3)
1103             {
1104                 r.error = sys_print((const char*)sa->arg1, (size_t)sa->arg2);
1105             }
1106             break;
1107
1108         case SYSCALL_DEBUG:
1109             if (argc == 2) {
1110                 r = handle_debug_syscall(sa->arg1);
1111             }
1112             break;
1113             
1114 /* XXX - not revision-independent. */
1115 #ifdef  __ARM_ARCH_7M__
1116     //help the dispatcher resume a context that can not be restored whithout a mode change
1117         case SYSCALL_RESUME_CONTEXT:
1118             if (argc == 2)
1119                 r.error = sys_resume_context((arch_registers_state_t*) sa->arg1);
1120             break;
1121 #endif  //__ARM_ARCH_7M__
1122
1123         default:
1124             panic("Illegal syscall");
1125             r.error = SYS_ERR_ILLEGAL_SYSCALL;
1126             break;
1127     }
1128
1129     if (r.error) {
1130         /* XXX - not 64-bit clean, not AArch64-compatible. */
1131         debug(SUBSYS_SYSCALL, "syscall failed %08"PRIx32" => %08"PRIxERRV"\n",
1132               sa->arg0, r.error);
1133     }
1134
1135     context->named.r0 = r.error;
1136     context->named.r1 = r.value;
1137
1138     resume(context);
1139 }
1140
1141 /* XXX - this looks like a big hack. */
1142 #ifdef __ARM_ARCH_7M__    //armv7-m: cortex-m3 on pandaboard
1143 /*
1144     needed because to resume an interrupted IT block, there literally is only one way:
1145     exiting handler mode, restoring the context
1146     if the dispatcher has to restore a context with IT-bits set, it can only do so with help
1147     from the kernel. 
1148 */
1149 errval_t __attribute__ ((noreturn)) sys_resume_context(arch_registers_state_t* registers){
1150     debug(SUBSYS_SYSCALL, "restoring context for dispatcher\n");
1151     //because we come from a syscall, r9 does not yet point to current dispatcher.
1152     //the context we restore probably has the right one, exept if it is in systemcall
1153     //related code (e.g. restoring registers after a syscall)
1154     
1155     //we want the correct dispatcher, because we want to set disabled = 0
1156     //we can not do that in the calling code, because then the act of calling us
1157     //would set the enabled area (i.e. it could be restored which we don't want)
1158     struct dispatcher_shared_generic *disp_gen
1159         = get_dispatcher_shared_generic(dcb_current->disp);//find the correct current dispatcher
1160     
1161     
1162     //resume looks at our value of the rtls register, so we need to set it
1163     arch_set_thread_register(disp_gen->udisp);
1164     
1165     //set dispatcher->disabled = 0, because the resume code would also do that
1166     disp_gen->disabled = 0;
1167     
1168     //((struct dispatcher_shared_generic*) registers->named.rtls)->disabled = 0;
1169
1170     resume(registers);
1171 }
1172 #endif //__ARM_ARCH_7M__
1173