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