2 * Copyright (c) 2000-2004 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.
62 #include <mach/mach_types.h>
63 #include <mach/boolean.h>
64 #include <mach/kern_return.h>
65 #include <mach/machine.h>
66 #include <mach/host_info.h>
67 #include <mach/host_reboot.h>
68 #include <mach/host_priv_server.h>
69 #include <mach/processor_server.h>
71 #include <kern/kern_types.h>
72 #include <kern/counters.h>
73 #include <kern/cpu_data.h>
74 #include <kern/ipc_host.h>
75 #include <kern/host.h>
76 #include <kern/lock.h>
77 #include <kern/machine.h>
78 #include <kern/misc_protos.h>
79 #include <kern/processor.h>
80 #include <kern/queue.h>
81 #include <kern/sched.h>
82 #include <kern/task.h>
83 #include <kern/thread.h>
90 struct machine_info machine_info
;
93 void processor_doshutdown(
94 processor_t processor
);
99 * Flag processor as up and running, and available
104 processor_t processor
)
106 processor_set_t pset
= &default_pset
;
110 processor_lock(processor
);
111 init_ast_check(processor
);
112 simple_lock(&pset
->sched_lock
);
113 pset_add_processor(pset
, processor
);
114 enqueue_tail(&pset
->active_queue
, (queue_entry_t
)processor
);
115 processor
->state
= PROCESSOR_RUNNING
;
116 simple_unlock(&pset
->sched_lock
);
117 hw_atomic_add(&machine_info
.avail_cpus
, 1);
119 processor_unlock(processor
);
125 host_priv_t host_priv
,
128 if (host_priv
== HOST_PRIV_NULL
)
129 return (KERN_INVALID_HOST
);
131 assert(host_priv
== &realhost
);
133 if (options
& HOST_REBOOT_DEBUGGER
) {
134 Debugger("Debugger");
135 return (KERN_SUCCESS
);
138 halt_all_cpus(!(options
& HOST_REBOOT_HALT
));
140 return (KERN_SUCCESS
);
145 __unused processor_t processor
,
146 __unused processor_set_t new_pset
,
147 __unused boolean_t wait
)
149 return (KERN_FAILURE
);
154 processor_t processor
)
156 processor_set_t pset
;
160 processor_lock(processor
);
161 if (processor
->state
== PROCESSOR_OFF_LINE
) {
163 * Success if already shutdown.
165 processor_unlock(processor
);
168 return (KERN_SUCCESS
);
171 if (processor
->state
== PROCESSOR_START
) {
173 * Failure if currently being started.
175 processor_unlock(processor
);
178 return (KERN_FAILURE
);
182 * Must lock the scheduling lock
183 * to get at the processor state.
185 pset
= processor
->processor_set
;
186 if (pset
!= PROCESSOR_SET_NULL
) {
187 simple_lock(&pset
->sched_lock
);
190 * If the processor is dispatching, let it finish.
192 while (processor
->state
== PROCESSOR_DISPATCHING
) {
193 simple_unlock(&pset
->sched_lock
);
195 simple_lock(&pset
->sched_lock
);
199 * Success if already being shutdown.
201 if (processor
->state
== PROCESSOR_SHUTDOWN
) {
202 simple_unlock(&pset
->sched_lock
);
203 processor_unlock(processor
);
206 return (KERN_SUCCESS
);
211 * Success, already being shutdown.
213 processor_unlock(processor
);
216 return (KERN_SUCCESS
);
219 if (processor
->state
== PROCESSOR_IDLE
) {
220 remqueue(&pset
->idle_queue
, (queue_entry_t
)processor
);
224 if (processor
->state
== PROCESSOR_RUNNING
)
225 remqueue(&pset
->active_queue
, (queue_entry_t
)processor
);
227 panic("processor_shutdown");
229 processor
->state
= PROCESSOR_SHUTDOWN
;
231 simple_unlock(&pset
->sched_lock
);
233 processor_unlock(processor
);
235 processor_doshutdown(processor
);
238 cpu_exit_wait(PROCESSOR_DATA(processor
, slot_num
));
240 return (KERN_SUCCESS
);
244 * Called at splsched.
247 processor_doshutdown(
248 processor_t processor
)
250 thread_t old_thread
, self
= current_thread();
251 processor_set_t pset
;
256 * Get onto the processor to shutdown
258 prev
= thread_bind(self
, processor
);
259 thread_block(THREAD_CONTINUE_NULL
);
261 processor_lock(processor
);
262 pset
= processor
->processor_set
;
263 simple_lock(&pset
->sched_lock
);
265 if ((pcount
= pset
->processor_count
) == 1) {
266 simple_unlock(&pset
->sched_lock
);
267 processor_unlock(processor
);
269 processor_lock(processor
);
270 simple_lock(&pset
->sched_lock
);
273 assert(processor
->state
== PROCESSOR_SHUTDOWN
);
275 pset_remove_processor(pset
, processor
);
276 simple_unlock(&pset
->sched_lock
);
277 processor_unlock(processor
);
281 * Continue processor shutdown in shutdown context.
283 thread_bind(self
, prev
);
284 old_thread
= machine_processor_shutdown(self
, processor_offline
, processor
);
286 thread_begin(self
, self
->last_processor
);
288 thread_dispatch(old_thread
);
291 * If we just shutdown another processor, move the
292 * timer call outs to the current processor.
294 if (processor
!= current_processor()) {
295 processor_lock(processor
);
296 if ( processor
->state
== PROCESSOR_OFF_LINE
||
297 processor
->state
== PROCESSOR_SHUTDOWN
)
298 timer_call_shutdown(processor
);
299 processor_unlock(processor
);
304 * Complete the shutdown and place the processor offline.
306 * Called at splsched in the shutdown context.
310 processor_t processor
)
312 thread_t thread
, old_thread
= processor
->active_thread
;
314 thread
= processor
->idle_thread
;
315 processor
->active_thread
= thread
;
316 processor
->current_pri
= IDLEPRI
;
318 processor
->last_dispatch
= mach_absolute_time();
319 timer_switch((uint32_t)processor
->last_dispatch
,
320 &PROCESSOR_DATA(processor
, offline_timer
));
322 thread_done(old_thread
, thread
, processor
);
324 machine_set_current_thread(thread
);
326 thread_begin(thread
, processor
);
328 thread_dispatch(old_thread
);
330 PMAP_DEACTIVATE_KERNEL(PROCESSOR_DATA(processor
, slot_num
));
332 processor_lock(processor
);
333 processor
->state
= PROCESSOR_OFF_LINE
;
334 hw_atomic_sub(&machine_info
.avail_cpus
, 1);
336 processor_unlock(processor
);
339 panic("zombie processor");
345 host_priv_t host_priv
,
346 kernel_boot_info_t boot_info
)
348 const char *src
= "";
349 if (host_priv
== HOST_PRIV_NULL
)
350 return (KERN_INVALID_HOST
);
352 assert(host_priv
== &realhost
);
355 * Copy first operator string terminated by '\0' followed by
356 * standardized strings generated from boot string.
358 src
= machine_boot_info(boot_info
, KERNEL_BOOT_INFO_MAX
);
359 if (src
!= boot_info
)
360 (void) strncpy(boot_info
, src
, KERNEL_BOOT_INFO_MAX
);
362 return (KERN_SUCCESS
);