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