1/**
2 * \file
3 * \brief System calls implementation.
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <kernel.h>
16#include <sys_debug.h>
17#include <syscall.h>
18#include <barrelfish_kpi/syscalls.h>
19#include <capabilities.h>
20#include <mdb/mdb.h>
21#include <dispatch.h>
22#include <paging_kernel_arch.h>
23#include <exec.h>
24#include <arch/x86/apic.h>
25#include <arch/x86/perfmon_intel.h>
26#include <arch/x86/global.h>
27#include <barrelfish_kpi/sys_debug.h>
28#include <barrelfish_kpi/lmp.h>
29#include <barrelfish_kpi/dispatcher_shared_target.h>
30#include <barrelfish_kpi/syscall_overflows_arch.h>
31#include <trace/trace.h>
32#include <arch/x86/debugregs.h>
33#include <arch/x86/syscall.h>
34#include <arch/x86/timing.h>
35#include <mdb/mdb_tree.h>
36#include <useraccess.h>
37#include <arch/x86/perfmon_amd.h>
38#include <arch/x86/ipi_notify.h>
39
40/* FIXME: lots of missing argument checks in this function */
41static struct sysret handle_dispatcher_setup(struct capability *to,
42                                             int cmd, uintptr_t *args)
43{
44    capaddr_t odptr = args[0];
45    capaddr_t cptr = args[1];
46    uintptr_t rundepth = args[2];
47    int depth = rundepth & 0xff;
48    bool run = rundepth >> 8;
49    capaddr_t vptr = args[3];
50    capaddr_t dptr = args[4];
51
52    return sys_dispatcher_setup(to, cptr, depth, vptr, dptr, run, odptr);
53
54}
55
56static struct sysret handle_dispatcher_properties(struct capability *to,
57                                                  int cmd, uintptr_t *args)
58{
59    enum task_type type = args[0] >> 16;
60    unsigned short weight = args[0] & 0xffff;
61    unsigned long deadline = args[1];
62    unsigned long wcet = args[2];
63    unsigned long period = args[3];
64    unsigned long release = args[4];
65
66    return sys_dispatcher_properties(to, type, deadline, wcet, period,
67                                     release, weight);
68}
69
70// XXX: FIXME: cleanup and handle errors!
71static struct sysret handle_dispatcher_perfmon(struct capability *to,
72                                               int cmd, uintptr_t *args)
73{
74#if 1
75    return SYSRET(SYS_ERR_PERFMON_NOT_AVAILABLE);
76
77#else
78    perfmon_counter_t idx = (perfmon_counter_t)(args[0]);
79
80    // Currently only AMD perfmon is supported
81    if(!perfmon_amd_supported()) {
82        return SYSRET(SYS_ERR_PERFMON_NOT_AVAILABLE);
83    }
84
85    uint64_t operation = args[1];
86    switch(operation) {
87    case 0: {
88        perfmon_event_t event = args[2];
89        perfmon_mask_t umask = args[3];
90        bool os = args[4];
91        perfmon_amd_measure_start(event, umask, os ? true : false, idx);
92        break;
93    }
94
95    case 1: {
96        uint64_t val = args[2];
97        perfmon_amd_measure_write(val, idx);
98        break;
99    }
100
101    default:
102        panic("Unknown performance monitoring function!");
103    }
104
105    return SYSRET(SYS_ERR_OK);
106#endif
107}
108
109static struct sysret handle_retype_common(struct capability *root,
110                                          uintptr_t *args,
111                                          bool from_monitor)
112{
113    // Source capability cptr
114    capaddr_t source_cptr      = args[0];
115    // Type to retype to
116    enum objtype type        = args[1] >> 16;
117    // Object bits for variable-sized types
118    uint8_t objbits          = (args[1] >> 8) & 0xff;
119    // Destination cnode cptr
120    capaddr_t  dest_cnode_cptr = args[2];
121    // Destination slot number
122    capaddr_t dest_slot        = args[3];
123    // Valid bits in destination cnode cptr
124    uint64_t dest_vbits      = args[1] & 0xff;
125
126    return sys_retype(root, source_cptr, type, objbits, dest_cnode_cptr,
127                      dest_slot, dest_vbits, from_monitor);
128}
129
130static struct sysret handle_retype(struct capability *root, int cmd, uintptr_t *args)
131{
132    return handle_retype_common(root, args, false);
133}
134
135static struct sysret handle_create(struct capability *root, int cmd,
136                                   uintptr_t *args)
137{
138    /* Retrieve arguments */
139    enum objtype type         = args[0] >> 16;
140    uint8_t objbits           = (args[0] >> 8) & 0xff;
141    capaddr_t dest_cnode_cptr = args[1];
142    capaddr_t dest_slot       = args[2];
143    uint8_t dest_vbits        = args[0] & 0xff;
144
145    return sys_create(root, type, objbits, dest_cnode_cptr, dest_slot,
146                      dest_vbits);
147}
148
149/**
150 * Common code for copying and minting except the mint flag and param passing
151 */
152static struct sysret copy_or_mint(struct capability *root,
153                                  uintptr_t *args, bool mint)
154{
155    /* Retrive arguments */
156    capaddr_t  destcn_cptr   = args[0];
157    capaddr_t  source_cptr   = args[1];
158    capaddr_t dest_slot      = args[2] >> 16;
159    int      destcn_vbits  = (args[2] >> 8) & 0xff;
160    int      source_vbits  = args[2] & 0xff;
161    uintptr_t param1, param2;
162    // params only sent if mint operation
163    if (mint) {
164        param1 = args[3];
165        param2 = args[4];
166    } else {
167        param1 = param2 = 0;
168    }
169
170    return sys_copy_or_mint(root, destcn_cptr, dest_slot, source_cptr,
171                            destcn_vbits, source_vbits, param1, param2, mint);
172}
173
174static struct sysret handle_mint(struct capability *root, int cmd, uintptr_t *args)
175{
176    return copy_or_mint(root, args, true);
177}
178
179static struct sysret handle_copy(struct capability *root,
180                                 int cmd, uintptr_t *args)
181{
182    return copy_or_mint(root, args, false);
183}
184
185static struct sysret handle_delete(struct capability *root, int cmd, uintptr_t *args)
186{
187    capaddr_t cptr = args[0];
188    int bits     = args[1];
189    return  sys_delete(root, cptr, bits);
190}
191
192static struct sysret handle_revoke(struct capability *root,
193                                   int cmd, uintptr_t *args)
194{
195    capaddr_t cptr = args[0];
196    int bits     = args[1];
197    return  sys_revoke(root, cptr, bits);
198}
199
200static struct sysret handle_get_state(struct capability *root,
201                                      int cmd, uintptr_t *args)
202{
203    capaddr_t cptr = args[0];
204    int bits = args[1];
205    return sys_get_state(root, cptr, bits);
206}
207
208static struct sysret handle_map(struct capability *pgtable,
209                                int cmd, uintptr_t *args)
210{
211    /* Retrieve arguments */
212    capaddr_t  source_cptr  = args[0];
213    int        source_vbits = args[1] & 0xff;
214    int        mcn_vbits    = (args[1] >> 8) & 0xff;
215    cslot_t    mapping_slot = args[1] >> 16;
216    capaddr_t  mcn_addr     = args[2];
217    cslot_t    dest_slot    = args[3] >> 16;
218    uintptr_t  pte_count    = args[3] & 0xffff;
219    uint64_t  *overflow     = (uint64_t *)args[4];
220    uint64_t   offset       = overflow[0];
221    uint64_t   flags        = overflow[1];
222
223    return sys_map(pgtable, dest_slot, source_cptr, source_vbits,
224                   flags, offset, pte_count, mcn_addr, mcn_vbits, mapping_slot);
225}
226
227static struct sysret handle_unmap(struct capability *pgtable,
228                                  int cmd, uintptr_t *args)
229{
230    size_t mapping_caddr = args[0];
231    int    mapping_bits  = args[1];
232
233    errval_t err;
234    struct cte *mapping = NULL;
235    err = caps_lookup_slot(&dcb_current->cspace.cap, mapping_caddr, mapping_bits,
236                           &mapping, CAPRIGHTS_READ_WRITE);
237    if (err_is_fail(err)) {
238        return SYSRET(err_push(err, SYS_ERR_CAP_NOT_FOUND));
239    }
240
241    err = page_mappings_unmap(pgtable, mapping);
242    return SYSRET(err);
243}
244
245static struct sysret handle_mapping_destroy(struct capability *mapping,
246                                            int cmd, uintptr_t *args)
247{
248    panic("NYI!");
249    return SYSRET(SYS_ERR_OK);
250}
251
252static struct sysret handle_mapping_modify(struct capability *mapping,
253                                           int cmd, uintptr_t *args)
254{
255    // Modify flags of (part of) mapped region of frame
256    assert(type_is_mapping(mapping->type));
257
258    // unpack arguments
259    size_t offset = args[0]; // in pages; of first page to modify from first
260                             // page in mapped region
261    size_t pages  = args[1]; // #pages to modify
262    size_t flags  = args[2]; // new flags
263    genvaddr_t va = args[3]; // virtual addr hint
264
265    errval_t err = page_mappings_modify_flags(mapping, offset, pages, flags, va);
266
267    return (struct sysret) {
268        .error = err,
269        .value = 0,
270    };
271}
272
273
274/// Different handler for cap operations performed by the monitor
275static struct sysret monitor_handle_retype(struct capability *kernel_cap,
276                                           int cmd, uintptr_t *args)
277{
278    errval_t err;
279
280    struct remote_retype_syscall_overflow *rootcap = (void*)args[0];
281
282    struct capability *root;
283    err = caps_lookup_cap(&dcb_current->cspace.cap, rootcap->rootcap_addr,
284            rootcap->rootcap_vbits, &root, CAPRIGHTS_READ);
285    if (err_is_fail(err)) {
286        return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
287    }
288
289    /* XXX: this hides the first argument which retype_common doesn't know
290     * about */
291    return handle_retype_common(root, &args[1], true);
292}
293
294static struct sysret monitor_handle_has_descendants(struct capability *kernel_cap,
295                                                    int cmd, uintptr_t *args)
296{
297    // check access to user pointer
298    if (!access_ok(ACCESS_READ, args[0], sizeof(struct capability))) {
299        return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
300    }
301
302    struct capability *src = (struct capability *)args[0];
303
304    struct cte *next = mdb_find_greater(src, false);
305
306    return (struct sysret) {
307        .error = SYS_ERR_OK,
308        .value = (next && is_ancestor(&next->cap, src)),
309    };
310}
311
312static struct sysret monitor_handle_delete_last(struct capability *kernel_cap,
313                                                int cmd, uintptr_t *args)
314{
315    capaddr_t root_caddr = args[0];
316    capaddr_t target_caddr = args[1];
317    capaddr_t retcn_caddr = args[2];
318    cslot_t retcn_slot = args[3];
319    uint8_t target_vbits = (args[4]>>16)&0xff;
320    uint8_t root_vbits = (args[4]>>8)&0xff;
321    uint8_t retcn_vbits = args[4]&0xff;
322
323    return sys_monitor_delete_last(root_caddr, root_vbits, target_caddr,
324                                   target_vbits, retcn_caddr, retcn_vbits, retcn_slot);
325}
326
327static struct sysret monitor_handle_delete_foreigns(struct capability *kernel_cap,
328                                                    int cmd, uintptr_t *args)
329{
330    capaddr_t caddr = args[0];
331    uint8_t bits = args[1];
332    return sys_monitor_delete_foreigns(caddr, bits);
333}
334
335static struct sysret monitor_handle_revoke_mark_tgt(struct capability *kernel_cap,
336                                                    int cmd, uintptr_t *args)
337{
338    capaddr_t root_caddr = args[0];
339    uint8_t root_vbits = args[1];
340    capaddr_t target_caddr = args[2];
341    uint8_t target_vbits = args[3];
342
343    return sys_monitor_revoke_mark_tgt(root_caddr, root_vbits,
344                                       target_caddr, target_vbits);
345}
346
347static struct sysret monitor_handle_revoke_mark_rels(struct capability *kernel_cap,
348                                                     int cmd, uintptr_t *args)
349{
350    // user pointer to src cap, check access
351    if (!access_ok(ACCESS_READ, args[0], sizeof(struct capability))) {
352        return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
353    }
354    struct capability *base = (struct capability*)args[0];
355
356    return sys_monitor_revoke_mark_rels(base);
357}
358
359static struct sysret monitor_handle_delete_step(struct capability *kernel_cap,
360                                                int cmd, uintptr_t *args)
361{
362    capaddr_t ret_cn_addr = args[0];
363    capaddr_t ret_cn_bits = args[1];
364    capaddr_t ret_slot = args[2];
365    return sys_monitor_delete_step(ret_cn_addr, ret_cn_bits, ret_slot);
366}
367
368static struct sysret monitor_handle_clear_step(struct capability *kernel_cap,
369                                               int cmd, uintptr_t *args)
370{
371    capaddr_t ret_cn_addr = args[0];
372    capaddr_t ret_cn_bits = args[1];
373    capaddr_t ret_slot = args[2];
374    return sys_monitor_clear_step(ret_cn_addr, ret_cn_bits, ret_slot);
375}
376
377
378static struct sysret monitor_handle_register(struct capability *kernel_cap,
379                                             int cmd, uintptr_t *args)
380{
381    capaddr_t ep_caddr = args[0];
382    return sys_monitor_register(ep_caddr);
383}
384
385static struct sysret monitor_get_core_id(struct capability *kernel_cap,
386                                         int cmd, uintptr_t *args)
387{
388    return (struct sysret) {
389        .error = SYS_ERR_OK,
390        .value = my_core_id
391    };
392}
393
394static struct sysret monitor_get_arch_id(struct capability *kernel_cap,
395                                         int cmd, uintptr_t *args)
396{
397    return (struct sysret) {
398        .error = SYS_ERR_OK,
399        .value = apic_id
400    };
401}
402
403static struct sysret monitor_identify_cap_common(struct capability *kernel_cap,
404                                                 struct capability *root,
405                                                 uintptr_t *args)
406{
407    capaddr_t cptr = args[0];
408    int bits = args[1];
409    struct capability *retbuf = (void *)args[2];
410
411    return sys_monitor_identify_cap(root, cptr, bits, retbuf);
412}
413
414static struct sysret monitor_identify_cap(struct capability *kernel_cap,
415                                          int cmd, uintptr_t *args)
416{
417    return monitor_identify_cap_common(kernel_cap, &dcb_current->cspace.cap, args);
418}
419
420static struct sysret monitor_identify_domains_cap(struct capability *kernel_cap,
421                                                  int cmd, uintptr_t *args)
422{
423    errval_t err;
424
425    capaddr_t root_caddr = args[0];
426    capaddr_t root_vbits = args[1];
427
428    struct capability *root;
429    err = caps_lookup_cap(&dcb_current->cspace.cap, root_caddr, root_vbits,
430                          &root, CAPRIGHTS_READ);
431    if (err_is_fail(err)) {
432        return SYSRET(err_push(err, SYS_ERR_ROOT_CAP_LOOKUP));
433    }
434
435    /* XXX: conceal first two words of arguments */
436    return monitor_identify_cap_common(kernel_cap, root, &args[2]);
437}
438
439static struct sysret monitor_cap_has_relations(struct capability *kernel_cap,
440                                               int cmd, uintptr_t *args)
441{
442    capaddr_t caddr = args[0];
443    uint8_t vbits = args[1];
444    uint8_t mask = args[2];
445
446    return sys_cap_has_relations(caddr, vbits, mask);
447}
448
449static struct sysret monitor_remote_relations(struct capability *kernel_cap,
450                                              int cmd, uintptr_t *args)
451{
452    capaddr_t root_addr = args[0];
453    int root_bits = args[1];
454    capaddr_t cptr = args[2];
455    int bits = args[3];
456    uint8_t relations = args[4] & 0xFF;
457    uint8_t mask = (args[4] >> 8) & 0xFF;
458
459    return sys_monitor_remote_relations(root_addr, root_bits, cptr, bits,
460                                        relations, mask);
461}
462
463
464static struct sysret monitor_create_cap(struct capability *kernel_cap,
465                                        int cmd, uintptr_t *args)
466{
467    /* Create the cap in the destination */
468    capaddr_t cnode_cptr = args[0];
469    int cnode_vbits      = args[1];
470    size_t slot          = args[2];
471    coreid_t owner       = args[3];
472    struct capability *src =
473        (struct capability*)args[4];
474
475    /* Cannot create null caps */
476    if (src->type == ObjType_Null) {
477        return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
478    }
479
480    /* For certain types, only foreign copies can be created here */
481    if ((src->type == ObjType_EndPoint || src->type == ObjType_Dispatcher
482         || src->type == ObjType_Kernel || src->type == ObjType_IRQTable)
483        && owner == my_core_id)
484    {
485        return SYSRET(SYS_ERR_ILLEGAL_DEST_TYPE);
486    }
487
488    return SYSRET(caps_create_from_existing(&dcb_current->cspace.cap,
489                                            cnode_cptr, cnode_vbits,
490                                            slot, owner, src));
491}
492
493static struct sysret monitor_copy_existing(struct capability *kernel_cap,
494                                        int cmd, uintptr_t *args)
495{
496    capaddr_t cnode_cptr = args[0];
497    int cnode_vbits    = args[1];
498    size_t slot        = args[2];
499
500    // user pointer to src cap, check access
501    if (!access_ok(ACCESS_READ, args[3], sizeof(struct capability))) {
502        return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
503    }
504    /* Get the raw metadata of the capability to create from user pointer */
505    struct capability *src = (struct capability *)args[3];
506
507    return sys_monitor_copy_existing(src, cnode_cptr, cnode_vbits, slot);
508}
509
510
511static struct sysret monitor_nullify_cap(struct capability *kernel_cap,
512                                         int cmd, uintptr_t *args)
513{
514    capaddr_t cptr = args[0];
515    int bits = args[1];
516
517    return sys_monitor_nullify_cap(cptr, bits);
518}
519
520static struct sysret monitor_handle_sync_timer(struct capability *kern_cap,
521                                               int cmd, uintptr_t *args)
522{
523    uint64_t synctime = (uint64_t)args[0] << 32;
524    synctime |= (uint64_t)args[1];
525    return sys_monitor_handle_sync_timer(synctime);
526}
527
528static struct sysret handle_frame_identify(struct capability *to,
529                                           int cmd, uintptr_t *args)
530{
531    // Return with physical base address of frame
532    // XXX: pack size into bottom bits of base address
533    assert(to->type == ObjType_Frame || to->type == ObjType_DevFrame);
534    assert((to->u.frame.base & BASE_PAGE_MASK) == 0);
535    assert(to->u.frame.bits < BASE_PAGE_SIZE);
536    return (struct sysret) {
537        .error = SYS_ERR_OK,
538        .value = to->u.frame.base | to->u.frame.bits,
539    };
540}
541
542static struct sysret handle_io(struct capability *to, int cmd, uintptr_t *args)
543{
544    uint32_t    port = args[0];
545    uint32_t    data = args[1];
546
547    return sys_io(to, cmd, port, data);
548}
549
550static struct sysret monitor_handle_domain_id(struct capability *monitor_cap,
551                                              int cmd, uintptr_t *args)
552{
553    capaddr_t cptr = args[0];
554    domainid_t domain_id = args[1];
555
556    return sys_monitor_domain_id(cptr, domain_id);
557}
558
559static struct sysret monitor_get_cap_owner(struct capability *monitor_cap,
560                                           int cmd, uintptr_t *args)
561{
562    capaddr_t root_addr = args[0];
563    uint8_t root_bits = args[1];
564    capaddr_t cptr = args[2];
565    uint8_t bits = args[3];
566
567    return sys_get_cap_owner(root_addr, root_bits, cptr, bits);
568}
569
570static struct sysret monitor_set_cap_owner(struct capability *monitor_cap,
571                                           int cmd, uintptr_t *args)
572{
573    capaddr_t root_addr = args[0];
574    uint8_t root_bits = args[1];
575    capaddr_t cptr = args[2];
576    uint8_t bits = args[3];
577    coreid_t owner = args[4];
578
579    return sys_set_cap_owner(root_addr, root_bits, cptr, bits, owner);
580}
581
582static struct sysret monitor_lock_cap(struct capability *monitor_cap,
583                                      int cmd, uintptr_t *args)
584{
585    capaddr_t root_addr = args[0];
586    uint8_t root_bits = args[1];
587    capaddr_t cptr = args[2];
588    uint8_t bits = args[3];
589
590    return sys_lock_cap(root_addr, root_bits, cptr, bits);
591}
592
593static struct sysret monitor_unlock_cap(struct capability *monitor_cap,
594                                        int cmd, uintptr_t *args)
595{
596    capaddr_t root_addr = args[0];
597    uint8_t root_bits = args[1];
598    capaddr_t cptr = args[2];
599    uint8_t bits = args[3];
600
601    return sys_unlock_cap(root_addr, root_bits, cptr, bits);
602}
603
604/**
605 * \brief Set up tracing in the kernel
606 */
607static struct sysret handle_trace_setup(struct capability *cap,
608                                        int cmd, uintptr_t *args)
609{
610    struct capability *frame;
611    errval_t err;
612
613    /* lookup passed cap */
614    capaddr_t cptr = args[0];
615    err = caps_lookup_cap(&dcb_current->cspace.cap, cptr, CPTR_BITS, &frame,
616                          CAPRIGHTS_READ_WRITE);
617    if (err_is_fail(err)) {
618        return SYSRET(err);
619    }
620
621    lpaddr_t lpaddr = gen_phys_to_local_phys(frame->u.frame.base);
622    kernel_trace_buf = local_phys_to_mem(lpaddr);
623    //printf("kernel.%u: handle_trace_setup at %lx\n", apic_id, kernel_trace_buf);
624
625    // Copy boot applications.
626	trace_copy_boot_applications();
627
628    return SYSRET(SYS_ERR_OK);
629}
630
631static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
632        uintptr_t *args)
633{
634    struct sysret ret;
635    ret.error = SYS_ERR_OK;
636    ret.value = to->u.irqsrc.vector;
637    return ret;
638
639}
640
641
642static struct sysret handle_irqdest_get_vector(struct capability *to, int cmd,
643                                            uintptr_t *args)
644{
645    struct sysret ret;
646    ret.error = SYS_ERR_OK;
647    ret.value = to->u.irqdest.vector;
648    return ret;
649}
650
651static struct sysret handle_irqdest_connect(struct capability *to, int cmd,
652                                            uintptr_t *args)
653{
654    return SYSRET(irq_connect(to, args[0]));
655}
656
657static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
658                                            uintptr_t *args)
659{
660    struct sysret ret;
661    int outvec;
662    ret.error = irq_table_alloc(&outvec);
663    ret.value = outvec;
664    return ret;
665}
666
667static struct sysret handle_irq_table_alloc_dest_cap(struct capability *to, int cmd,
668                                            uintptr_t *args)
669{
670    return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2]));
671}
672
673static struct sysret handle_irq_table_set(struct capability *to, int cmd, uintptr_t *args)
674{
675    return SYSRET(irq_table_set(args[0], args[1]));
676}
677
678static struct sysret handle_irq_table_delete(struct capability *to, int cmd, uintptr_t *args)
679{
680    return SYSRET(irq_table_delete(args[0]));
681}
682
683/**
684 * \brief Return system-wide unique ID of this ID cap.
685 */
686static struct sysret handle_idcap_identify(struct capability *cap, int cmd,
687                                           uintptr_t *args)
688{
689    idcap_id_t *idp = (idcap_id_t *) args[0];
690
691    // Check validity of user space pointer
692    if (!access_ok(ACCESS_WRITE, (lvaddr_t) idp, sizeof(*idp)))  {
693        return SYSRET(SYS_ERR_INVALID_USER_BUFFER);
694    }
695
696    return sys_idcap_identify(cap, idp);
697}
698
699static struct sysret kernel_send_init_ipi(struct capability *cap, int cmd,
700                                          uintptr_t *args)
701{
702    coreid_t destination = args[0];
703    apic_send_init_assert(destination, xapic_none);
704    apic_send_init_deassert();
705
706    return SYSRET(SYS_ERR_OK);
707}
708
709static struct sysret kernel_send_start_ipi(struct capability *cap,
710                                           int cmd,
711                                           uintptr_t *args)
712{
713    coreid_t destination = args[0];
714    genvaddr_t start_vector = X86_32_REAL_MODE_SEGMENT_TO_REAL_MODE_PAGE(X86_32_REAL_MODE_SEGMENT);
715    apic_send_start_up(destination, xapic_none, start_vector);
716
717    return SYSRET(SYS_ERR_OK);
718}
719
720
721static struct sysret kernel_get_global_phys(struct capability *cap,
722                                           int cmd,
723                                           uintptr_t *args)
724{
725
726    struct sysret sysret;
727    sysret.value = mem_to_local_phys((lvaddr_t)global);
728    sysret.error = SYS_ERR_OK;
729
730    return sysret;
731}
732
733static struct sysret kernel_ipi_register(struct capability *cap,
734                                         int cmd, uintptr_t *args)
735{
736    assert(cap->type == ObjType_Kernel);
737    capaddr_t ep = args[0];
738    int chanid = args[1];
739    return SYSRET(ipi_register_notification(ep, chanid));
740}
741
742static struct sysret kernel_ipi_delete(struct capability *cap,
743                                       int cmd, uintptr_t *args)
744{
745    assert(cap->type == ObjType_Kernel);
746    assert(!"NYI");
747    return SYSRET(SYS_ERR_OK);
748}
749
750static struct sysret handle_ipi_notify_send(struct capability *cap,
751                                            int cmd, uintptr_t *args)
752{
753    assert(cap->type == ObjType_Notify_IPI);
754    return ipi_raise_notify(cap->u.notify_ipi.coreid, cap->u.notify_ipi.chanid);
755}
756
757static struct sysret dispatcher_dump_ptables(struct capability *cap,
758                                             int cmd, uintptr_t *args)
759{
760    assert(cap->type == ObjType_Dispatcher);
761
762    printf("kernel_dump_ptables\n");
763
764    struct dcb *dispatcher = cap->u.dispatcher.dcb;
765
766    paging_dump_tables(dispatcher);
767
768    return SYSRET(SYS_ERR_OK);
769}
770
771static struct sysret dispatcher_dump_capabilities(struct capability *cap,
772                                             int cmd, uintptr_t *args)
773{
774    assert(cap->type == ObjType_Dispatcher);
775    struct dcb *dispatcher = cap->u.dispatcher.dcb;
776    errval_t err = debug_print_cababilities(dispatcher);
777    return SYSRET(err);
778}
779
780
781static struct sysret kernel_add_kcb(struct capability *kern_cap,
782                                    int cmd, uintptr_t *args)
783{
784    uintptr_t kcb_addr = args[0];
785    struct kcb *new_kcb = (struct kcb *)kcb_addr;
786
787    return sys_kernel_add_kcb(new_kcb);
788}
789
790static struct sysret kernel_remove_kcb(struct capability *kern_cap,
791                                       int cmd, uintptr_t *args)
792{
793    printk(LOG_NOTE, "in kernel_remove_kcb invocation!\n");
794    uintptr_t kcb_addr = args[0];
795    struct kcb *to_remove = (struct kcb *)kcb_addr;
796
797    return sys_kernel_remove_kcb(to_remove);
798}
799
800static struct sysret kernel_suspend_kcb_sched(struct capability *kern_cap,
801                                              int cmd, uintptr_t *args)
802{
803    printk(LOG_NOTE, "in kernel_suspend_kcb_sched invocation!\n");
804    return sys_kernel_suspend_kcb_sched((bool)args[0]);
805}
806
807static struct sysret handle_kcb_identify(struct capability *to,
808                                         int cmd, uintptr_t *args)
809{
810    return sys_handle_kcb_identify(to);
811}
812
813typedef struct sysret (*invocation_handler_t)(struct capability *to,
814                                              int cmd, uintptr_t *args);
815
816static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
817    [ObjType_Dispatcher] = {
818        [DispatcherCmd_Setup]        = handle_dispatcher_setup,
819        [DispatcherCmd_Properties]   = handle_dispatcher_properties,
820        [DispatcherCmd_PerfMon]      = handle_dispatcher_perfmon,
821        [DispatcherCmd_DumpPTables]  = dispatcher_dump_ptables,
822        [DispatcherCmd_DumpCapabilities] = dispatcher_dump_capabilities
823    },
824    [ObjType_KernelControlBlock] = {
825        [FrameCmd_Identify] = handle_kcb_identify,
826    },
827    [ObjType_Frame] = {
828        [FrameCmd_Identify] = handle_frame_identify,
829    },
830    [ObjType_DevFrame] = {
831        [FrameCmd_Identify] = handle_frame_identify,
832    },
833    [ObjType_L1CNode] = {
834        [CNodeCmd_Copy]   = handle_copy,
835        [CNodeCmd_Mint]   = handle_mint,
836        [CNodeCmd_Retype] = handle_retype,
837        [CNodeCmd_Create] = handle_create,
838        [CNodeCmd_Delete] = handle_delete,
839        [CNodeCmd_Revoke] = handle_revoke,
840        [CNodeCmd_GetState] = handle_get_state,
841    },
842    [ObjType_VNode_x86_32_pdpt] = {
843        [VNodeCmd_Map]   = handle_map,
844        [VNodeCmd_Unmap] = handle_unmap,
845    },
846    [ObjType_VNode_x86_32_pdir] = {
847        [VNodeCmd_Map]   = handle_map,
848        [VNodeCmd_Unmap] = handle_unmap,
849    },
850    [ObjType_VNode_x86_32_ptable] = {
851        [VNodeCmd_Map]   = handle_map,
852        [VNodeCmd_Unmap] = handle_unmap,
853    },
854    [ObjType_Frame_Mapping] = {
855        [MappingCmd_Destroy] = handle_mapping_destroy,
856        [MappingCmd_Modify] = handle_mapping_modify,
857    },
858    [ObjType_DevFrame_Mapping] = {
859        [MappingCmd_Destroy] = handle_mapping_destroy,
860        [MappingCmd_Modify] = handle_mapping_modify,
861    },
862    [ObjType_VNode_x86_32_pdpt_Mapping] = {
863        [MappingCmd_Destroy] = handle_mapping_destroy,
864        [MappingCmd_Modify] = handle_mapping_modify,
865    },
866    [ObjType_VNode_x86_32_pdir_Mapping] = {
867        [MappingCmd_Destroy] = handle_mapping_destroy,
868        [MappingCmd_Modify] = handle_mapping_modify,
869    },
870    [ObjType_VNode_x86_32_ptable_Mapping] = {
871        [MappingCmd_Destroy] = handle_mapping_destroy,
872        [MappingCmd_Modify] = handle_mapping_modify,
873    },
874    [ObjType_Kernel] = {
875        [KernelCmd_Get_core_id]  = monitor_get_core_id,
876        [KernelCmd_Get_arch_id]  = monitor_get_arch_id,
877        [KernelCmd_Identify_cap] = monitor_identify_cap,
878        [KernelCmd_Identify_domains_cap] = monitor_identify_domains_cap,
879        [KernelCmd_Remote_relations] = monitor_remote_relations,
880        [KernelCmd_Cap_has_relations] = monitor_cap_has_relations,
881        [KernelCmd_Create_cap]   = monitor_create_cap,
882        [KernelCmd_Copy_existing] = monitor_copy_existing,
883        [KernelCmd_Nullify_cap]  = monitor_nullify_cap,
884        [KernelCmd_Setup_trace]  = handle_trace_setup,
885        [KernelCmd_Register]     = monitor_handle_register,
886        [KernelCmd_Domain_Id]    = monitor_handle_domain_id,
887        [KernelCmd_Get_cap_owner] = monitor_get_cap_owner,
888        [KernelCmd_Set_cap_owner] = monitor_set_cap_owner,
889        [KernelCmd_Lock_cap]     = monitor_lock_cap,
890        [KernelCmd_Unlock_cap]   = monitor_unlock_cap,
891        [KernelCmd_Retype]       = monitor_handle_retype,
892        [KernelCmd_Has_descendants] = monitor_handle_has_descendants,
893        [KernelCmd_Delete_last]  = monitor_handle_delete_last,
894        [KernelCmd_Delete_foreigns] = monitor_handle_delete_foreigns,
895        [KernelCmd_Revoke_mark_target] = monitor_handle_revoke_mark_tgt,
896        [KernelCmd_Revoke_mark_relations] = monitor_handle_revoke_mark_rels,
897        [KernelCmd_Delete_step] = monitor_handle_delete_step,
898        [KernelCmd_Clear_step] = monitor_handle_clear_step,
899        [KernelCmd_Sync_timer]   = monitor_handle_sync_timer,
900        [KernelCmd_IPI_Register] = kernel_ipi_register,
901        [KernelCmd_IPI_Delete]   = kernel_ipi_delete,
902        [KernelCmd_GetGlobalPhys] = kernel_get_global_phys,
903        [KernelCmd_Add_kcb]      = kernel_add_kcb,
904        [KernelCmd_Remove_kcb]   = kernel_remove_kcb,
905        [KernelCmd_Suspend_kcb_sched]   = kernel_suspend_kcb_sched
906    },
907    [ObjType_IPI] = {
908        [IPICmd_Send_Start] = kernel_send_start_ipi,
909        [IPICmd_Send_Init] = kernel_send_init_ipi,
910    },
911    [ObjType_IRQDest] = {
912        [IRQDestCmd_Connect] = handle_irqdest_connect,
913        [IRQDestCmd_GetVector] = handle_irqdest_get_vector
914    },
915    [ObjType_IRQSrc] = {
916        [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
917    },
918    [ObjType_IRQTable] = {
919        [IRQTableCmd_Alloc] = handle_irq_table_alloc,
920        [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
921        [IRQTableCmd_Set] = handle_irq_table_set,
922        [IRQTableCmd_Delete] = handle_irq_table_delete
923    },
924    [ObjType_IO] = {
925        [IOCmd_Outb] = handle_io,
926        [IOCmd_Outw] = handle_io,
927        [IOCmd_Outd] = handle_io,
928        [IOCmd_Inb] = handle_io,
929        [IOCmd_Inw] = handle_io,
930        [IOCmd_Ind] = handle_io
931    },
932    [ObjType_ID] = {
933        [IDCmd_Identify] = handle_idcap_identify
934    },
935    [ObjType_Notify_IPI] = {
936        [NotifyCmd_Send] = handle_ipi_notify_send
937    }
938};
939
940/* syscall C entry point; called only from entry.S so no prototype in header */
941struct sysret sys_syscall(uintptr_t arg0, uintptr_t arg1, uintptr_t *args,
942                          uintptr_t *cpu_save_frame);
943struct sysret sys_syscall(uintptr_t arg0, uintptr_t arg1, uintptr_t *args,
944                          uintptr_t *cpu_save_frame)
945{
946    struct sysret retval = { .error = SYS_ERR_OK, .value = 0 };
947    uint8_t syscall = arg0 & 0xff;
948
949    switch(syscall) {
950    case SYSCALL_INVOKE: ; /* Handle capability invocation */
951        uint8_t flags = (arg0 >> 24) & 0xf;
952        uint8_t invoke_bits = (arg0 >> 16) & 0xff;
953        capaddr_t invoke_cptr = arg1;
954
955        debug(SUBSYS_SYSCALL, "sys_invoke(0x%"PRIxCADDR"(%d))\n",
956              invoke_cptr, invoke_bits);
957
958        // Capability to invoke
959        struct capability *to = NULL;
960        retval.error = caps_lookup_cap(&dcb_current->cspace.cap, invoke_cptr,
961                                       invoke_bits, &to, CAPRIGHTS_READ);
962        if (err_is_fail(retval.error)) {
963            break;
964        }
965        assert(to != NULL);
966        assert(to->type < ObjType_Num);
967
968        // Endpoint cap, do LMP
969        if (to->type == ObjType_EndPoint) {
970            struct dcb *listener = to->u.endpointlmp.listener;
971            assert(listener != NULL);
972
973            if (listener->disp == 0) {
974                retval.error = SYS_ERR_LMP_NO_TARGET;
975                break;
976            }
977
978            uint8_t length_words = (arg0 >> 28) & 0xf;
979            uint8_t send_bits = (arg0 >> 8) & 0xff;
980            capaddr_t send_cptr = args[0];
981
982            /* limit length of message from buggy/malicious sender */
983            length_words = min(length_words, LMP_MSG_LENGTH);
984
985            // does the sender want to yield their timeslice on success?
986            bool sync = flags & LMP_FLAG_SYNC;
987            // does the sender want to yield to the target if undeliverable?
988            bool yield = flags & LMP_FLAG_YIELD;
989            // is the cap (if present) to be deleted on send?
990            bool give_away = flags & LMP_FLAG_GIVEAWAY;
991
992            // try to deliver message
993            retval.error = lmp_deliver(to, dcb_current, &args[1], length_words,
994                                       send_cptr, send_bits, give_away);
995
996            /* Switch to reciever upon successful delivery with sync flag,
997             * or (some cases of) unsuccessful delivery with yield flag */
998            enum err_code err_code = err_no(retval.error);
999            if ((sync && err_is_ok(retval.error)) ||
1000                (yield && (err_code == SYS_ERR_LMP_BUF_OVERFLOW
1001                           || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
1002                           || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
1003                           || err_code == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED))
1004                    ) {
1005                if (err_is_fail(retval.error)) {
1006                    struct dispatcher_shared_generic *current_disp =
1007                        get_dispatcher_shared_generic(dcb_current->disp);
1008                    struct dispatcher_shared_generic *listener_disp =
1009                        get_dispatcher_shared_generic(listener->disp);
1010                    debug(SUBSYS_DISPATCH, "LMP failed; %.*s yields to %.*s: %u\n",
1011                          DISP_NAME_LEN, current_disp->name,
1012                          DISP_NAME_LEN, listener_disp->name, err_code);
1013                }
1014
1015                // special-case context switch: ensure correct state in current DCB
1016                dispatcher_handle_t handle = dcb_current->disp;
1017                struct dispatcher_shared_x86_32 *disp =
1018                    get_dispatcher_shared_x86_32(handle);
1019                dcb_current->disabled = dispatcher_is_disabled_ip(handle, cpu_save_frame[0]);
1020                struct registers_x86_32 *save_area;
1021                if (dcb_current->disabled) {
1022                    save_area = &disp->disabled_save_area;
1023                } else {
1024                    save_area = &disp->enabled_save_area;
1025                }
1026
1027                // save calling dispatcher's registers, so that when the dispatcher
1028                // next runs, it has a valid state in the relevant save area.
1029                // Save EIP, EFLAGS, ESP and set EAX (return value) for later resume
1030                save_area->eax = retval.error; // x86 1st return register
1031                // save frame contains: eip, cs, eflags, esp, ss
1032                save_area->eip = cpu_save_frame[0];
1033                save_area->cs = cpu_save_frame[1];
1034                save_area->eflags = cpu_save_frame[2];
1035                save_area->esp = cpu_save_frame[3];
1036                save_area->ss = cpu_save_frame[4];
1037
1038                /* save FS/GS selectors (they're unmodified by the syscall path) */
1039                __asm ("mov     %%fs, %[fs]     \n\t"
1040                       "mov     %%gs, %[gs]     \n\t"
1041                       : /* No output */
1042                       :
1043                       [fs] "m" (save_area->fs),
1044                       [gs] "m" (save_area->gs)
1045                       );
1046
1047                dispatch(to->u.endpointlmp.listener);
1048                panic("dispatch returned");
1049            }
1050        } else { // not endpoint cap, call kernel handler through dispatch table
1051            uint8_t cmd = arg0 >> 8;
1052            if (cmd >= CAP_MAX_CMD) {
1053                retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1054                break;
1055            }
1056
1057            // Call the invocation
1058            invocation_handler_t invocation = invocations[to->type][cmd];
1059            if(invocation == NULL) {
1060                printf("No invocation handler for type = %d, cmd = %d\n", to->type, cmd);
1061                retval.error = SYS_ERR_ILLEGAL_INVOCATION;
1062                break;
1063            } else {
1064                retval = invocation(to, cmd, args);
1065            }
1066        }
1067        break;
1068
1069        // Yield the CPU to the next dispatcher
1070    case SYSCALL_YIELD:
1071        retval = sys_yield((capaddr_t)arg1);
1072        break;
1073
1074        // NOP system call for benchmarking purposes
1075    case SYSCALL_NOP:
1076        break;
1077
1078        // Debug print system call
1079    case SYSCALL_PRINT:
1080        retval.error = sys_print((char *)arg1, args[0]);
1081        break;
1082
1083        // Reboot!
1084        // FIXME: this should be a kernel cap invocation or similarly restricted
1085    case SYSCALL_REBOOT:
1086        reboot();
1087        break;
1088
1089    case SYSCALL_DEBUG:
1090        switch(arg1) {
1091        case DEBUG_CONTEXT_COUNTER_RESET:
1092            dispatch_csc_reset();
1093            break;
1094
1095        case DEBUG_CONTEXT_COUNTER_READ:
1096            retval.value = dispatch_get_csc();
1097            break;
1098
1099        case DEBUG_TIMESLICE_COUNTER_READ:
1100            retval.value = kernel_now;
1101            break;
1102
1103        case DEBUG_FLUSH_CACHE:
1104            wbinvd();
1105            break;
1106
1107        case DEBUG_SEND_IPI:
1108            apic_send_std_ipi(args[0], args[1], args[2]);
1109            break;
1110
1111        case DEBUG_SET_BREAKPOINT:
1112            debugregs_set_breakpoint(args[0], args[1], args[2]);
1113            break;
1114
1115        case DEBUG_GET_TSC_PER_MS:
1116            retval.value = timing_get_tsc_per_ms();
1117            break;
1118
1119        case DEBUG_FEIGN_FRAME_CAP:
1120            {
1121                uint8_t bits = args[2] & 0xff;
1122                uint8_t cap_bits = (args[2] >> 8) & 0xff;
1123                uint8_t recv_slot = (args[2] >> 16) & 0xff;
1124                struct cte *slot;
1125                struct capability *recv_cnode_cap;
1126
1127/*                printf("arg1 = %" PRIx64 ", arg2 = %" PRIx64 "\n",
1128                        (uint64_t)args[1], (uint64_t)args[2]);
1129*/
1130                errval_t err = caps_lookup_cap(&dcb_current->cspace.cap,
1131                      args[0], cap_bits, &recv_cnode_cap, CAPRIGHTS_READ_WRITE);
1132                if(err_is_fail(err)) {
1133                    retval.error = err;
1134                    break;
1135                }
1136
1137                // Check for cnode type
1138                if (recv_cnode_cap->type != ObjType_CNode) {
1139                    retval.error = SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID;
1140                    break;
1141                }
1142                // The slot within the cnode
1143                slot = caps_locate_slot(recv_cnode_cap->u.cnode.cnode,
1144                                        recv_slot);
1145
1146                retval.error = caps_create_new(ObjType_DevFrame, args[1], bits,
1147                        bits, my_core_id, slot);
1148            }
1149            break;
1150
1151        default:
1152            printk(LOG_ERR, "invalid sys_debug msg type\n");
1153        }
1154        break;
1155
1156    default:
1157        printk(LOG_ERR, "sys_syscall: Illegal system call! "
1158               "(0x%x, 0x%"PRIxPTR")\n", syscall, arg1);
1159        retval.error = SYS_ERR_ILLEGAL_SYSCALL;
1160        break;
1161    }
1162
1163    // If dcb_current got removed, dispatch someone else
1164    if (dcb_current == NULL) {
1165        assert(err_is_ok(retval.error));
1166        dispatch(schedule());
1167    }
1168
1169    if (syscall == SYSCALL_INVOKE) {
1170        debug(SUBSYS_SYSCALL, "invoke returning 0x%"PRIxERRV" 0x%"PRIxPTR"\n",
1171              retval.error, retval.value);
1172    }
1173
1174    return retval;
1175}
1176