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