2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28 * All Rights Reserved.
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.
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.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
53 * File: kern/machine.c
54 * Author: Avadis Tevanian, Jr.
57 * Support for machine independent machine abstraction.
63 #include <mach/boolean.h>
64 #include <mach/kern_return.h>
65 #include <mach/mach_types.h>
66 #include <mach/machine.h>
67 #include <mach/host_info.h>
68 #include <mach/host_reboot.h>
69 #include <kern/counters.h>
70 #include <kern/cpu_data.h>
71 #include <kern/ipc_host.h>
72 #include <kern/host.h>
73 #include <kern/lock.h>
74 #include <kern/machine.h>
75 #include <kern/processor.h>
76 #include <kern/queue.h>
77 #include <kern/sched.h>
78 #include <kern/task.h>
79 #include <kern/thread.h>
80 #include <kern/thread_swap.h>
81 #include <kern/misc_protos.h>
83 #include <kern/mk_sp.h>
89 struct machine_info machine_info
;
90 struct machine_slot machine_slot
[NCPUS
];
92 thread_t machine_wake_thread
;
95 void processor_doshutdown(
96 processor_t processor
);
101 * Flag specified cpu as up and running. Called when a processor comes
108 processor_t processor
= cpu_to_processor(cpu
);
109 processor_set_t pset
= &default_pset
;
110 struct machine_slot
*ms
;
114 processor_lock(processor
);
115 init_ast_check(processor
);
116 ms
= &machine_slot
[cpu
];
118 machine_info
.avail_cpus
++;
119 simple_lock(&pset
->sched_lock
);
120 pset_add_processor(pset
, processor
);
121 enqueue_tail(&pset
->active_queue
, (queue_entry_t
)processor
);
122 processor
->deadline
= UINT64_MAX
;
123 processor
->state
= PROCESSOR_RUNNING
;
124 simple_unlock(&pset
->sched_lock
);
125 processor_unlock(processor
);
132 * Flag specified cpu as down. Called when a processor is about to
139 processor_t processor
;
140 struct machine_slot
*ms
;
143 processor
= cpu_to_processor(cpu
);
146 processor_lock(processor
);
147 ms
= &machine_slot
[cpu
];
149 machine_info
.avail_cpus
--;
151 * processor has already been removed from pset.
153 processor
->state
= PROCESSOR_OFF_LINE
;
154 processor_unlock(processor
);
160 host_priv_t host_priv
,
163 if (host_priv
== HOST_PRIV_NULL
)
164 return (KERN_INVALID_HOST
);
166 assert(host_priv
== &realhost
);
168 if (options
& HOST_REBOOT_DEBUGGER
) {
169 Debugger("Debugger");
170 return (KERN_SUCCESS
);
173 halt_all_cpus(!(options
& HOST_REBOOT_HALT
));
175 return (KERN_SUCCESS
);
180 processor_t processor
,
181 processor_set_t new_pset
,
185 processor
++; new_pset
++; wait
++;
187 return (KERN_FAILURE
);
192 processor_t processor
)
194 processor_set_t pset
;
198 processor_lock(processor
);
199 if ( processor
->state
== PROCESSOR_OFF_LINE
||
200 processor
->state
== PROCESSOR_SHUTDOWN
) {
202 * Success if already shutdown or being shutdown.
204 processor_unlock(processor
);
207 return (KERN_SUCCESS
);
210 if (processor
->state
== PROCESSOR_START
) {
212 * Failure if currently being started.
214 processor_unlock(processor
);
217 return (KERN_FAILURE
);
221 * Processor must be in a processor set. Must lock the scheduling
222 * lock to get at the processor state.
224 pset
= processor
->processor_set
;
225 simple_lock(&pset
->sched_lock
);
228 * If the processor is dispatching, let it finish - it will set its
229 * state to running very soon.
231 while (*(volatile int *)&processor
->state
== PROCESSOR_DISPATCHING
) {
232 simple_unlock(&pset
->sched_lock
);
234 simple_lock(&pset
->sched_lock
);
237 if (processor
->state
== PROCESSOR_IDLE
) {
238 remqueue(&pset
->idle_queue
, (queue_entry_t
)processor
);
242 if (processor
->state
== PROCESSOR_RUNNING
)
243 remqueue(&pset
->active_queue
, (queue_entry_t
)processor
);
245 panic("processor_request_action");
247 processor
->state
= PROCESSOR_SHUTDOWN
;
249 simple_unlock(&pset
->sched_lock
);
251 processor_unlock(processor
);
253 processor_doshutdown(processor
);
256 return (KERN_SUCCESS
);
260 * Called at splsched.
263 processor_doshutdown(
264 processor_t processor
)
266 thread_t old_thread
, self
= current_thread();
267 processor_set_t pset
;
271 * Get onto the processor to shutdown
273 prev
= thread_bind(self
, processor
);
274 thread_block(THREAD_CONTINUE_NULL
);
276 processor_lock(processor
);
277 pset
= processor
->processor_set
;
278 simple_lock(&pset
->sched_lock
);
280 if (pset
->processor_count
== 1) {
282 extern void start_cpu_thread(void);
284 simple_unlock(&pset
->sched_lock
);
285 processor_unlock(processor
);
288 * Create the thread, and point it at the routine.
290 thread
= kernel_thread_create(start_cpu_thread
, MAXPRI_KERNEL
);
293 machine_wake_thread
= thread
;
294 thread
->state
= TH_RUN
;
295 pset_run_incr(thread
->processor_set
);
296 thread_unlock(thread
);
298 processor_lock(processor
);
299 simple_lock(&pset
->sched_lock
);
302 assert(processor
->state
== PROCESSOR_SHUTDOWN
);
304 pset_remove_processor(pset
, processor
);
305 simple_unlock(&pset
->sched_lock
);
306 processor_unlock(processor
);
311 thread_bind(self
, prev
);
312 old_thread
= switch_to_shutdown_context(self
,
313 processor_offline
, processor
);
314 if (processor
!= current_processor())
315 timer_call_shutdown(processor
);
316 thread_dispatch(old_thread
);
320 * Actually do the processor shutdown. This is called at splsched,
321 * running on the processor's shutdown stack.
326 processor_t processor
)
328 register thread_t old_thread
= processor
->active_thread
;
329 register int cpu
= processor
->slot_num
;
331 timer_call_cancel(&processor
->quantum_timer
);
332 timer_switch(&kernel_timer
[cpu
]);
333 processor
->active_thread
= processor
->idle_thread
;
334 machine_thread_set_current(processor
->active_thread
);
335 thread_dispatch(old_thread
);
338 * OK, now exit this cpu.
340 PMAP_DEACTIVATE_KERNEL(cpu
);
343 panic("zombie processor");
349 host_priv_t host_priv
,
350 kernel_boot_info_t boot_info
)
353 extern char *machine_boot_info(
354 kernel_boot_info_t boot_info
,
357 if (host_priv
== HOST_PRIV_NULL
)
358 return (KERN_INVALID_HOST
);
360 assert(host_priv
== &realhost
);
363 * Copy first operator string terminated by '\0' followed by
364 * standardized strings generated from boot string.
366 src
= machine_boot_info(boot_info
, KERNEL_BOOT_INFO_MAX
);
367 if (src
!= boot_info
)
368 (void) strncpy(boot_info
, src
, KERNEL_BOOT_INFO_MAX
);
370 return (KERN_SUCCESS
);