2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
56 * File: kern/machine.c
57 * Author: Avadis Tevanian, Jr.
60 * Support for machine independent machine abstraction.
66 #include <mach/boolean.h>
67 #include <mach/kern_return.h>
68 #include <mach/mach_types.h>
69 #include <mach/machine.h>
70 #include <mach/host_info.h>
71 #include <mach/host_reboot.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/processor.h>
79 #include <kern/queue.h>
80 #include <kern/sched.h>
81 #include <kern/task.h>
82 #include <kern/thread.h>
83 #include <kern/thread_swap.h>
84 #include <kern/misc_protos.h>
86 #include <kern/mk_sp.h>
92 struct machine_info machine_info
;
93 struct machine_slot machine_slot
[NCPUS
];
95 static queue_head_t processor_action_queue
;
96 static boolean_t processor_action_active
;
97 static thread_call_t processor_action_call
;
98 static thread_call_data_t processor_action_call_data
;
99 decl_simple_lock_data(static,processor_action_lock
)
101 thread_t machine_wake_thread
;
104 processor_set_t
processor_request_action(
105 processor_t processor
,
106 processor_set_t new_pset
);
108 void processor_doaction(
109 processor_t processor
);
111 void processor_doshutdown(
112 processor_t processor
);
117 * Flag specified cpu as up and running. Called when a processor comes
124 processor_t processor
= cpu_to_processor(cpu
);
125 processor_set_t pset
= &default_pset
;
126 struct machine_slot
*ms
;
130 * Just twiddle our thumbs; we've got nothing better to do
133 while (!simple_lock_try(&pset
->processors_lock
))
137 processor_lock(processor
);
138 init_ast_check(processor
);
139 ms
= &machine_slot
[cpu
];
141 machine_info
.avail_cpus
++;
142 pset_add_processor(pset
, processor
);
143 simple_lock(&pset
->sched_lock
);
144 enqueue_tail(&pset
->active_queue
, (queue_entry_t
)processor
);
145 processor
->state
= PROCESSOR_RUNNING
;
146 simple_unlock(&pset
->sched_lock
);
147 processor_unlock(processor
);
150 simple_unlock(&pset
->processors_lock
);
156 * Flag specified cpu as down. Called when a processor is about to
163 processor_t processor
;
164 struct machine_slot
*ms
;
167 processor
= cpu_to_processor(cpu
);
170 processor_lock(processor
);
171 ms
= &machine_slot
[cpu
];
173 machine_info
.avail_cpus
--;
175 * processor has already been removed from pset.
177 processor
->processor_set_next
= PROCESSOR_SET_NULL
;
178 processor
->state
= PROCESSOR_OFF_LINE
;
179 processor_unlock(processor
);
185 host_priv_t host_priv
,
188 if (host_priv
== HOST_PRIV_NULL
)
189 return (KERN_INVALID_HOST
);
191 assert(host_priv
== &realhost
);
193 if (options
& HOST_REBOOT_DEBUGGER
) {
194 Debugger("Debugger");
197 halt_all_cpus(!(options
& HOST_REBOOT_HALT
));
199 return (KERN_SUCCESS
);
203 * processor_request_action:
205 * Common internals of processor_assign and processor_shutdown.
206 * If new_pset is null, this is a shutdown, else it's an assign
207 * and caller must donate a reference.
208 * For assign operations, it returns an old pset that must be deallocated
210 * For shutdown operations, it always returns PROCESSOR_SET_NULL.
213 processor_request_action(
214 processor_t processor
,
215 processor_set_t new_pset
)
217 processor_set_t pset
, old_pset
;
220 * Processor must be in a processor set. Must lock its idle lock to
221 * get at processor state.
223 pset
= processor
->processor_set
;
224 simple_lock(&pset
->sched_lock
);
227 * If the processor is dispatching, let it finish - it will set its
228 * state to running very soon.
230 while (*(volatile int *)&processor
->state
== PROCESSOR_DISPATCHING
) {
231 simple_unlock(&pset
->sched_lock
);
233 simple_lock(&pset
->sched_lock
);
236 assert( processor
->state
== PROCESSOR_IDLE
||
237 processor
->state
== PROCESSOR_RUNNING
||
238 processor
->state
== PROCESSOR_ASSIGN
);
241 * Now lock the action queue and do the dirty work.
243 simple_lock(&processor_action_lock
);
245 if (processor
->state
== PROCESSOR_IDLE
) {
246 remqueue(&pset
->idle_queue
, (queue_entry_t
)processor
);
250 if (processor
->state
== PROCESSOR_RUNNING
)
251 remqueue(&pset
->active_queue
, (queue_entry_t
)processor
);
253 if (processor
->state
!= PROCESSOR_ASSIGN
)
254 enqueue_tail(&processor_action_queue
, (queue_entry_t
)processor
);
257 * And ask the action_thread to do the work.
259 if (new_pset
!= PROCESSOR_SET_NULL
) {
260 processor
->state
= PROCESSOR_ASSIGN
;
261 old_pset
= processor
->processor_set_next
;
262 processor
->processor_set_next
= new_pset
;
265 processor
->state
= PROCESSOR_SHUTDOWN
;
266 old_pset
= PROCESSOR_SET_NULL
;
269 simple_unlock(&pset
->sched_lock
);
271 if (processor_action_active
) {
272 simple_unlock(&processor_action_lock
);
277 processor_action_active
= TRUE
;
278 simple_unlock(&processor_action_lock
);
280 processor_unlock(processor
);
282 thread_call_enter(processor_action_call
);
283 processor_lock(processor
);
290 processor_t processor
,
291 processor_set_t new_pset
,
295 processor
++; new_pset
++; wait
++;
297 return (KERN_FAILURE
);
301 * processor_shutdown() queues a processor up for shutdown.
302 * Any assignment in progress is overriden.
306 processor_t processor
)
311 processor_lock(processor
);
312 if ( processor
->state
== PROCESSOR_OFF_LINE
||
313 processor
->state
== PROCESSOR_SHUTDOWN
) {
315 * Already shutdown or being shutdown -- nothing to do.
317 processor_unlock(processor
);
320 return (KERN_SUCCESS
);
323 processor_request_action(processor
, PROCESSOR_SET_NULL
);
325 assert_wait((event_t
)processor
, THREAD_UNINT
);
327 processor_unlock(processor
);
330 thread_block(THREAD_CONTINUE_NULL
);
332 return (KERN_SUCCESS
);
336 * processor_action() shuts down processors or changes their assignment.
340 thread_call_param_t p0
,
341 thread_call_param_t p1
)
343 register processor_t processor
;
347 simple_lock(&processor_action_lock
);
349 while (!queue_empty(&processor_action_queue
)) {
350 processor
= (processor_t
)dequeue_head(&processor_action_queue
);
351 simple_unlock(&processor_action_lock
);
354 processor_doaction(processor
);
357 simple_lock(&processor_action_lock
);
360 processor_action_active
= FALSE
;
361 simple_unlock(&processor_action_lock
);
366 processor_action(void)
368 queue_init(&processor_action_queue
);
369 simple_lock_init(&processor_action_lock
, ETAP_THREAD_ACTION
);
370 processor_action_active
= FALSE
;
372 thread_call_setup(&processor_action_call_data
, _processor_action
, NULL
);
373 processor_action_call
= &processor_action_call_data
;
377 * processor_doaction actually does the shutdown. The trick here
378 * is to schedule ourselves onto a cpu and then save our
379 * context back into the runqs before taking out the cpu.
383 processor_t processor
)
385 thread_t self
= current_thread();
386 processor_set_t pset
;
391 * Get onto the processor to shutdown
393 thread_bind(self
, processor
);
394 thread_block(THREAD_CONTINUE_NULL
);
396 pset
= processor
->processor_set
;
397 simple_lock(&pset
->processors_lock
);
399 if (pset
->processor_count
== 1) {
401 extern void start_cpu_thread(void);
403 simple_unlock(&pset
->processors_lock
);
406 * Create the thread, and point it at the routine.
408 thread
= kernel_thread_with_priority(
409 kernel_task
, MAXPRI_KERNEL
,
410 start_cpu_thread
, TRUE
, FALSE
);
412 disable_preemption();
416 machine_wake_thread
= thread
;
417 thread_go_locked(thread
, THREAD_AWAKENED
);
418 (void)rem_runq(thread
);
419 thread_unlock(thread
);
422 simple_lock(&pset
->processors_lock
);
427 processor_lock(processor
);
430 * Do shutdown, make sure we live when processor dies.
432 if (processor
->state
!= PROCESSOR_SHUTDOWN
) {
433 panic("action_thread -- bad processor state");
436 pset_remove_processor(pset
, processor
);
437 processor_unlock(processor
);
438 simple_unlock(&pset
->processors_lock
);
443 thread_bind(self
, PROCESSOR_NULL
);
444 self
->continuation
= 0;
445 old_thread
= switch_to_shutdown_context(self
,
446 processor_doshutdown
, processor
);
447 if (processor
!= current_processor())
448 timer_call_shutdown(processor
);
449 thread_dispatch(old_thread
);
450 thread_wakeup((event_t
)processor
);
455 * Actually do the processor shutdown. This is called at splsched,
456 * running on the processor's shutdown stack.
460 processor_doshutdown(
461 processor_t processor
)
463 register thread_t old_thread
= current_thread();
464 register int cpu
= processor
->slot_num
;
466 timer_call_cancel(&processor
->quantum_timer
);
467 timer_switch(&kernel_timer
[cpu
]);
468 thread_machine_set_current(processor
->idle_thread
);
469 thread_dispatch(old_thread
);
472 * OK, now exit this cpu.
474 PMAP_DEACTIVATE_KERNEL(cpu
);
477 panic("zombie processor");
483 host_priv_t host_priv
,
484 kernel_boot_info_t boot_info
)
487 extern char *machine_boot_info(
488 kernel_boot_info_t boot_info
,
491 if (host_priv
== HOST_PRIV_NULL
)
492 return (KERN_INVALID_HOST
);
494 assert(host_priv
== &realhost
);
497 * Copy first operator string terminated by '\0' followed by
498 * standardized strings generated from boot string.
500 src
= machine_boot_info(boot_info
, KERNEL_BOOT_INFO_MAX
);
501 if (src
!= boot_info
)
502 (void) strncpy(boot_info
, src
, KERNEL_BOOT_INFO_MAX
);
504 return (KERN_SUCCESS
);