|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: ! 53: /* ! 54: * host.c ! 55: * ! 56: * Non-ipc host functions. ! 57: */ ! 58: ! 59: #include <cpus.h> ! 60: #include <dipc.h> ! 61: #include <mach_host.h> ! 62: ! 63: #include <mach/boolean.h> ! 64: #include <kern/assert.h> ! 65: #include <kern/kalloc.h> ! 66: #include <kern/rtmalloc.h> ! 67: #include <kern/host.h> ! 68: #include <kern/host_statistics.h> ! 69: #include <kern/ipc_host.h> ! 70: #include <kern/misc_protos.h> ! 71: #include <mach/host_info.h> ! 72: #include <mach/kern_return.h> ! 73: #include <mach/machine.h> ! 74: #include <mach/port.h> ! 75: #include <kern/processor.h> ! 76: #include <mach/processor_info.h> ! 77: #include <mach/vm_param.h> ! 78: #include <mach/mach_host_server.h> ! 79: #if DIPC ! 80: #include <dipc/dipc_funcs.h> ! 81: #include <dipc/special_ports.h> ! 82: #endif ! 83: ! 84: vm_statistics_data_t vm_stat[NCPUS]; ! 85: ! 86: host_data_t realhost; ! 87: ! 88: kern_return_t ! 89: host_processors( ! 90: host_t host, ! 91: processor_array_t *processor_list, ! 92: mach_msg_type_number_t *countp) ! 93: { ! 94: register int i; ! 95: register processor_t *tp; ! 96: vm_offset_t addr; ! 97: unsigned int count; ! 98: boolean_t rt = FALSE; /* ### This boolean is FALSE, because there ! 99: * currently exists no mechanism to determine ! 100: * whether or not the reply port is an RT port ! 101: */ ! 102: ! 103: if (host == HOST_NULL) ! 104: return(KERN_INVALID_ARGUMENT); ! 105: ! 106: /* ! 107: * Determine how many processors we have. ! 108: * (This number shouldn't change.) ! 109: */ ! 110: ! 111: count = 0; ! 112: for (i = 0; i < NCPUS; i++) ! 113: if (machine_slot[i].is_cpu) ! 114: count++; ! 115: ! 116: if (count == 0) ! 117: panic("host_processors"); ! 118: ! 119: addr = KALLOC((vm_size_t) (count * sizeof(mach_port_t)), rt); ! 120: if (addr == 0) ! 121: return KERN_RESOURCE_SHORTAGE; ! 122: ! 123: tp = (processor_t *) addr; ! 124: for (i = 0; i < NCPUS; i++) ! 125: if (machine_slot[i].is_cpu) ! 126: *tp++ = cpu_to_processor(i); ! 127: ! 128: *countp = count; ! 129: *processor_list = (processor_array_t)addr; ! 130: ! 131: /* do the conversion that Mig should handle */ ! 132: ! 133: tp = (processor_t *) addr; ! 134: for (i = 0; i < count; i++) ! 135: ((mach_port_t *) tp)[i] = ! 136: (mach_port_t)convert_processor_to_port(tp[i]); ! 137: ! 138: return KERN_SUCCESS; ! 139: } ! 140: ! 141: kern_return_t ! 142: host_info( ! 143: host_t host, ! 144: host_flavor_t flavor, ! 145: host_info_t info, ! 146: mach_msg_type_number_t *count) ! 147: { ! 148: ! 149: if (host == HOST_NULL) ! 150: return(KERN_INVALID_ARGUMENT); ! 151: ! 152: switch(flavor) { ! 153: ! 154: case HOST_BASIC_INFO: ! 155: { register host_basic_info_t basic_info; ! 156: /* ! 157: * Basic information about this host. ! 158: */ ! 159: if (*count < HOST_BASIC_INFO_COUNT) ! 160: return(KERN_FAILURE); ! 161: ! 162: basic_info = (host_basic_info_t) info; ! 163: ! 164: basic_info->max_cpus = machine_info.max_cpus; ! 165: basic_info->avail_cpus = machine_info.avail_cpus; ! 166: basic_info->memory_size = machine_info.memory_size; ! 167: basic_info->cpu_type = ! 168: machine_slot[master_processor->slot_num].cpu_type; ! 169: basic_info->cpu_subtype = ! 170: machine_slot[master_processor->slot_num].cpu_subtype; ! 171: ! 172: *count = HOST_BASIC_INFO_COUNT; ! 173: return(KERN_SUCCESS); ! 174: } ! 175: ! 176: case HOST_SCHED_INFO: ! 177: { register host_sched_info_t sched_info; ! 178: extern int tick; /* XXX */ ! 179: /* ! 180: * Return scheduler information. ! 181: */ ! 182: if (*count < HOST_SCHED_INFO_COUNT) ! 183: return(KERN_FAILURE); ! 184: ! 185: sched_info = (host_sched_info_t) info; ! 186: ! 187: sched_info->min_timeout = tick / 1000; /* XXX */ ! 188: sched_info->min_quantum = tick / 1000; /* XXX */ ! 189: ! 190: *count = HOST_SCHED_INFO_COUNT; ! 191: return(KERN_SUCCESS); ! 192: } ! 193: ! 194: case HOST_RESOURCE_SIZES: ! 195: { ! 196: /* ! 197: * Return sizes of kernel data structures ! 198: */ ! 199: if (*count < HOST_RESOURCE_SIZES_COUNT) ! 200: return(KERN_FAILURE); ! 201: ! 202: /* XXX Fail until ledgers are implemented */ ! 203: return(KERN_INVALID_ARGUMENT); ! 204: } ! 205: ! 206: case HOST_PRIORITY_INFO: ! 207: { register host_priority_info_t priority_info; ! 208: ! 209: if (*count < HOST_PRIORITY_INFO_COUNT) ! 210: return(KERN_FAILURE); ! 211: ! 212: priority_info = (host_priority_info_t) info; ! 213: ! 214: priority_info->kernel_priority = BASEPRI_KERNEL; ! 215: priority_info->system_priority= BASEPRI_SYSTEM; ! 216: priority_info->server_priority= BASEPRI_SERVER; ! 217: priority_info->user_priority= BASEPRI_USER; ! 218: priority_info->depress_priority= DEPRESSPRI; ! 219: priority_info->idle_priority= IDLEPRI; ! 220: priority_info->minimum_priority= MINPRI; ! 221: priority_info->maximum_priority= 0; ! 222: ! 223: *count = HOST_PRIORITY_INFO_COUNT; ! 224: return(KERN_SUCCESS); ! 225: } ! 226: ! 227: /* ! 228: */ ! 229: default: ! 230: return(KERN_INVALID_ARGUMENT); ! 231: } ! 232: } ! 233: ! 234: kern_return_t ! 235: host_statistics( ! 236: host_t host, ! 237: host_flavor_t flavor, ! 238: host_info_t info, ! 239: mach_msg_type_number_t *count) ! 240: { ! 241: ! 242: if (host == HOST_NULL) ! 243: return(KERN_INVALID_HOST); ! 244: ! 245: switch(flavor) { ! 246: ! 247: case HOST_LOAD_INFO: { ! 248: register host_load_info_t load_info; ! 249: extern integer_t avenrun[3], mach_factor[3]; ! 250: ! 251: if (*count < HOST_LOAD_INFO_COUNT) ! 252: return(KERN_FAILURE); ! 253: ! 254: load_info = (host_load_info_t) info; ! 255: ! 256: bcopy((char *) avenrun, ! 257: (char *) load_info->avenrun, ! 258: sizeof avenrun); ! 259: bcopy((char *) mach_factor, ! 260: (char *) load_info->mach_factor, ! 261: sizeof mach_factor); ! 262: ! 263: *count = HOST_LOAD_INFO_COUNT; ! 264: return(KERN_SUCCESS); ! 265: } ! 266: ! 267: case HOST_VM_INFO: { ! 268: register vm_statistics_t stat; ! 269: vm_statistics_data_t host_vm_stat; ! 270: extern int vm_page_free_count, vm_page_active_count, ! 271: vm_page_inactive_count, vm_page_wire_count; ! 272: ! 273: if (*count < HOST_VM_INFO_COUNT) ! 274: return(KERN_FAILURE); ! 275: ! 276: stat = &vm_stat[0]; ! 277: host_vm_stat = *stat; ! 278: #if NCPUS > 1 ! 279: { ! 280: register int i; ! 281: ! 282: for (i = 1; i < NCPUS; i++) { ! 283: stat++; ! 284: host_vm_stat.zero_fill_count += ! 285: stat->zero_fill_count; ! 286: host_vm_stat.reactivations += ! 287: stat->reactivations; ! 288: host_vm_stat.pageins += stat->pageins; ! 289: host_vm_stat.pageouts += stat->pageouts; ! 290: host_vm_stat.faults += stat->faults; ! 291: host_vm_stat.cow_faults += stat->cow_faults; ! 292: host_vm_stat.lookups += stat->lookups; ! 293: host_vm_stat.hits += stat->hits; ! 294: } ! 295: } ! 296: #endif ! 297: ! 298: stat = (vm_statistics_t) info; ! 299: ! 300: stat->free_count = vm_page_free_count; ! 301: stat->active_count = vm_page_active_count; ! 302: stat->inactive_count = vm_page_inactive_count; ! 303: stat->wire_count = vm_page_wire_count; ! 304: stat->zero_fill_count = host_vm_stat.zero_fill_count; ! 305: stat->reactivations = host_vm_stat.reactivations; ! 306: stat->pageins = host_vm_stat.pageins; ! 307: stat->pageouts = host_vm_stat.pageouts; ! 308: stat->faults = host_vm_stat.faults; ! 309: stat->cow_faults = host_vm_stat.cow_faults; ! 310: stat->lookups = host_vm_stat.lookups; ! 311: stat->hits = host_vm_stat.hits; ! 312: ! 313: *count = HOST_VM_INFO_COUNT; ! 314: return(KERN_SUCCESS); ! 315: } ! 316: ! 317: case HOST_CPU_LOAD_INFO: { ! 318: host_cpu_load_info_t cpu_load_info; ! 319: unsigned long ticks_value1, ticks_value2; ! 320: int i; ! 321: ! 322: #define GET_TICKS_VALUE(__cpu,__state) \ ! 323: MACRO_BEGIN \ ! 324: do { \ ! 325: ticks_value1 = *(volatile integer_t *) \ ! 326: (&machine_slot[(__cpu)].cpu_ticks[(__state)]); \ ! 327: ticks_value2 = *(volatile integer_t *) \ ! 328: (&machine_slot[(__cpu)].cpu_ticks[(__state)]); \ ! 329: } while (ticks_value1 != ticks_value2); \ ! 330: cpu_load_info->cpu_ticks[(__state)] += ticks_value1; \ ! 331: MACRO_END ! 332: ! 333: if (*count < HOST_CPU_LOAD_INFO_COUNT) ! 334: return KERN_FAILURE; ! 335: ! 336: cpu_load_info = (host_cpu_load_info_t) info; ! 337: ! 338: cpu_load_info->cpu_ticks[CPU_STATE_USER] = 0; ! 339: cpu_load_info->cpu_ticks[CPU_STATE_NICE] = 0; ! 340: cpu_load_info->cpu_ticks[CPU_STATE_SYSTEM] = 0; ! 341: cpu_load_info->cpu_ticks[CPU_STATE_IDLE] = 0; ! 342: for (i = 0; i < NCPUS; i++) { ! 343: if (!machine_slot[i].is_cpu || ! 344: !machine_slot[i].running) ! 345: continue; ! 346: GET_TICKS_VALUE(i, CPU_STATE_USER); ! 347: GET_TICKS_VALUE(i, CPU_STATE_NICE); ! 348: GET_TICKS_VALUE(i, CPU_STATE_SYSTEM); ! 349: GET_TICKS_VALUE(i, CPU_STATE_IDLE); ! 350: } ! 351: ! 352: *count = HOST_CPU_LOAD_INFO_COUNT; ! 353: return KERN_SUCCESS; ! 354: } ! 355: ! 356: default: ! 357: return(KERN_INVALID_ARGUMENT); ! 358: } ! 359: } ! 360: ! 361: kern_return_t ! 362: host_page_size( ! 363: host_t host, ! 364: vm_size_t *out_page_size) ! 365: { ! 366: if (host == HOST_NULL) ! 367: return(KERN_INVALID_ARGUMENT); ! 368: ! 369: *out_page_size = PAGE_SIZE; ! 370: ! 371: return(KERN_SUCCESS); ! 372: } ! 373: ! 374: /* ! 375: * Return kernel version string (more than you ever ! 376: * wanted to know about what version of the kernel this is). ! 377: */ ! 378: ! 379: kern_return_t ! 380: host_kernel_version( ! 381: host_t host, ! 382: kernel_version_t out_version) ! 383: { ! 384: extern char version[]; ! 385: ! 386: if (host == HOST_NULL) ! 387: return(KERN_INVALID_ARGUMENT); ! 388: ! 389: (void) strncpy(out_version, version, sizeof(kernel_version_t)); ! 390: ! 391: return(KERN_SUCCESS); ! 392: } ! 393: ! 394: /* ! 395: * host_processor_sets: ! 396: * ! 397: * List all processor sets on the host. ! 398: */ ! 399: #if MACH_HOST ! 400: ! 401: kern_return_t ! 402: host_processor_sets( ! 403: host_t host, ! 404: processor_set_name_array_t *pset_list, ! 405: mach_msg_type_number_t *count) ! 406: { ! 407: unsigned int actual; /* this many psets */ ! 408: processor_set_t pset; ! 409: processor_set_t *psets; ! 410: int i; ! 411: boolean_t rt = FALSE; /* ### This boolean is FALSE, because there ! 412: * currently exists no mechanism to determine ! 413: * whether or not the reply port is an RT port ! 414: */ ! 415: ! 416: vm_size_t size; ! 417: vm_size_t size_needed; ! 418: vm_offset_t addr; ! 419: ! 420: if (host == HOST_NULL) ! 421: return KERN_INVALID_ARGUMENT; ! 422: ! 423: size = 0; addr = 0; ! 424: ! 425: for (;;) { ! 426: mutex_lock(&all_psets_lock); ! 427: actual = all_psets_count; ! 428: ! 429: /* do we have the memory we need? */ ! 430: ! 431: size_needed = actual * sizeof(mach_port_t); ! 432: if (size_needed <= size) ! 433: break; ! 434: ! 435: /* unlock and allocate more memory */ ! 436: mutex_unlock(&all_psets_lock); ! 437: ! 438: if (size != 0) ! 439: KFREE(addr, size, rt); ! 440: ! 441: assert(size_needed > 0); ! 442: size = size_needed; ! 443: ! 444: addr = KALLOC(size, rt); ! 445: if (addr == 0) ! 446: return KERN_RESOURCE_SHORTAGE; ! 447: } ! 448: ! 449: /* OK, have memory and the all_psets_lock */ ! 450: ! 451: psets = (processor_set_t *) addr; ! 452: ! 453: for (i = 0, pset = (processor_set_t) queue_first(&all_psets); ! 454: i < actual; ! 455: i++, pset = (processor_set_t) queue_next(&pset->all_psets)) { ! 456: /* take ref for convert_pset_name_to_port */ ! 457: pset_reference(pset); ! 458: psets[i] = pset; ! 459: } ! 460: assert(queue_end(&all_psets, (queue_entry_t) pset)); ! 461: ! 462: /* can unlock now that we've got the pset refs */ ! 463: mutex_unlock(&all_psets_lock); ! 464: ! 465: /* ! 466: * Always have default port. ! 467: */ ! 468: ! 469: assert(actual > 0); ! 470: ! 471: /* if we allocated too much, must copy */ ! 472: ! 473: if (size_needed < size) { ! 474: vm_offset_t newaddr; ! 475: ! 476: newaddr = KALLOC(size_needed, rt); ! 477: if (newaddr == 0) { ! 478: for (i = 0; i < actual; i++) ! 479: pset_deallocate(psets[i]); ! 480: KFREE(addr, size, rt); ! 481: return KERN_RESOURCE_SHORTAGE; ! 482: } ! 483: ! 484: bcopy((char *) addr, (char *) newaddr, size_needed); ! 485: KFREE(addr, size, rt); ! 486: psets = (processor_set_t *) newaddr; ! 487: } ! 488: ! 489: *pset_list = (mach_port_t *) psets; ! 490: *count = actual; ! 491: ! 492: /* do the conversion that Mig should handle */ ! 493: ! 494: for (i = 0; i < actual; i++) ! 495: ((ipc_port_t *) psets)[i] = convert_pset_name_to_port(psets[i]); ! 496: ! 497: return KERN_SUCCESS; ! 498: } ! 499: #else /* MACH_HOST */ ! 500: /* ! 501: * Only one processor set, the default processor set, in this case. ! 502: */ ! 503: kern_return_t ! 504: host_processor_sets( ! 505: host_t host, ! 506: processor_set_name_array_t *pset_list, ! 507: mach_msg_type_number_t *count) ! 508: { ! 509: vm_offset_t addr; ! 510: boolean_t rt = FALSE; /* ### This boolean is FALSE, because there ! 511: * currently exists no mechanism to determine ! 512: * whether or not the reply port is an RT port ! 513: */ ! 514: ! 515: if (host == HOST_NULL) ! 516: return KERN_INVALID_ARGUMENT; ! 517: ! 518: /* ! 519: * Allocate memory. Can be pageable because it won't be ! 520: * touched while holding a lock. ! 521: */ ! 522: ! 523: addr = KALLOC((vm_size_t) sizeof(mach_port_t), rt); ! 524: if (addr == 0) ! 525: return KERN_RESOURCE_SHORTAGE; ! 526: ! 527: /* take ref for convert_pset_name_to_port */ ! 528: pset_reference(&default_pset); ! 529: /* do the conversion that Mig should handle */ ! 530: *((ipc_port_t *) addr) = convert_pset_name_to_port(&default_pset); ! 531: ! 532: *pset_list = (processor_set_array_t)addr; ! 533: *count = 1; ! 534: ! 535: return KERN_SUCCESS; ! 536: } ! 537: #endif /* MACH_HOST */ ! 538: ! 539: /* ! 540: * host_processor_set_priv: ! 541: * ! 542: * Return control port for given processor set. ! 543: */ ! 544: kern_return_t ! 545: host_processor_set_priv( ! 546: host_t host, ! 547: processor_set_t pset_name, ! 548: processor_set_t *pset) ! 549: { ! 550: if ((host == HOST_NULL) || (pset_name == PROCESSOR_SET_NULL)) { ! 551: *pset = PROCESSOR_SET_NULL; ! 552: return(KERN_INVALID_ARGUMENT); ! 553: } ! 554: ! 555: *pset = pset_name; ! 556: pset_reference(*pset); ! 557: return(KERN_SUCCESS); ! 558: } ! 559: ! 560: /* ! 561: * host_processor_slots: ! 562: * ! 563: * Return number of slots with active processors in them ! 564: */ ! 565: kern_return_t ! 566: host_processor_slots( ! 567: host_t host, ! 568: processor_slot_t slots, ! 569: mach_msg_type_number_t *count) ! 570: { ! 571: int i; ! 572: ! 573: #ifdef lint ! 574: host++; ! 575: #endif /* lint */ ! 576: ! 577: if (*count < NCPUS) ! 578: return(KERN_INVALID_ARGUMENT); ! 579: ! 580: *count = 0; ! 581: for (i = 0; i < NCPUS; i++) { ! 582: if (machine_slot[i].is_cpu && ! 583: machine_slot[i].running) { ! 584: *slots++ = i; ! 585: (*count)++; ! 586: } ! 587: } ! 588: return(KERN_SUCCESS); ! 589: } ! 590: ! 591: ! 592: /* ! 593: * host_node_self ! 594: * ! 595: * Find the current host node number, if we are distributed. ! 596: */ ! 597: kern_return_t ! 598: host_node_self( ! 599: host_t host, ! 600: int *node) ! 601: { ! 602: #if DIPC ! 603: *node = dipc_node_self(); ! 604: return KERN_SUCCESS; ! 605: #else ! 606: *node = 0; ! 607: return KERN_SUCCESS; ! 608: #endif ! 609: } ! 610: ! 611: /* ! 612: * User interface for setting a special port. ! 613: * ! 614: * Only permits the user to set a user-owned special port ! 615: * ID, rejecting a kernel-owned special port ID. ! 616: * ! 617: * A special kernel port cannot be set up using this ! 618: * routine; use kernel_set_special_port() instead. ! 619: */ ! 620: kern_return_t ! 621: host_set_special_port( ! 622: host_t host, ! 623: int id, ! 624: ipc_port_t port) ! 625: { ! 626: #if DIPC ! 627: return norma_set_special_port(host, id, port); ! 628: #else ! 629: return KERN_FAILURE; ! 630: #endif ! 631: } ! 632: ! 633: ! 634: /* ! 635: * User interface for retrieving a special port. ! 636: * ! 637: * When all processing is local, this call does not block. ! 638: * If processing goes remote to discover a remote UID, ! 639: * this call blocks but not indefinitely. If the remote ! 640: * node does not exist, has panic'ed, or is booting but ! 641: * hasn't yet turned on DIPC, then we expect the transport ! 642: * to return an error. ! 643: * ! 644: * This routine always returns SUCCESS, even if there's ! 645: * no resulting port. ! 646: * ! 647: * Note that there is nothing to prevent a user special ! 648: * port from disappearing after it has been discovered by ! 649: * the caller; thus, using a special port can always result ! 650: * in a "port not valid" error. ! 651: */ ! 652: ! 653: kern_return_t ! 654: host_get_special_port( ! 655: host_t host, ! 656: int node, ! 657: int id, ! 658: ipc_port_t *portp) ! 659: { ! 660: #if DIPC ! 661: return norma_get_special_port(host, node, id, portp); ! 662: #else ! 663: return KERN_FAILURE; ! 664: #endif ! 665: } ! 666:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.