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