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