|
|
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.