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 thread_t machine_wake_thread
;
98 void processor_doshutdown(
99 processor_t processor
);
104 * Flag specified cpu as up and running. Called when a processor comes
111 processor_t processor
= cpu_to_processor(cpu
);
112 processor_set_t pset
= &default_pset
;
113 struct machine_slot
*ms
;
117 processor_lock(processor
);
118 init_ast_check(processor
);
119 ms
= &machine_slot
[cpu
];
121 machine_info
.avail_cpus
++;
122 simple_lock(&pset
->sched_lock
);
123 pset_add_processor(pset
, processor
);
124 enqueue_tail(&pset
->active_queue
, (queue_entry_t
)processor
);
125 processor
->deadline
= UINT64_MAX
;
126 processor
->state
= PROCESSOR_RUNNING
;
127 simple_unlock(&pset
->sched_lock
);
128 processor_unlock(processor
);
135 * Flag specified cpu as down. Called when a processor is about to
142 processor_t processor
;
143 struct machine_slot
*ms
;
146 processor
= cpu_to_processor(cpu
);
149 processor_lock(processor
);
150 ms
= &machine_slot
[cpu
];
152 machine_info
.avail_cpus
--;
154 * processor has already been removed from pset.
156 processor
->state
= PROCESSOR_OFF_LINE
;
157 processor_unlock(processor
);
163 host_priv_t host_priv
,
166 if (host_priv
== HOST_PRIV_NULL
)
167 return (KERN_INVALID_HOST
);
169 assert(host_priv
== &realhost
);
171 if (options
& HOST_REBOOT_DEBUGGER
) {
172 Debugger("Debugger");
173 return (KERN_SUCCESS
);
176 halt_all_cpus(!(options
& HOST_REBOOT_HALT
));
178 return (KERN_SUCCESS
);
183 processor_t processor
,
184 processor_set_t new_pset
,
188 processor
++; new_pset
++; wait
++;
190 return (KERN_FAILURE
);
195 processor_t processor
)
197 processor_set_t pset
;
201 processor_lock(processor
);
202 if ( processor
->state
== PROCESSOR_OFF_LINE
||
203 processor
->state
== PROCESSOR_SHUTDOWN
) {
205 * Success if already shutdown or being shutdown.
207 processor_unlock(processor
);
210 return (KERN_SUCCESS
);
213 if (processor
->state
== PROCESSOR_START
) {
215 * Failure if currently being started.
217 processor_unlock(processor
);
220 return (KERN_FAILURE
);
224 * Processor must be in a processor set. Must lock the scheduling
225 * lock to get at the processor state.
227 pset
= processor
->processor_set
;
228 simple_lock(&pset
->sched_lock
);
231 * If the processor is dispatching, let it finish - it will set its
232 * state to running very soon.
234 while (*(volatile int *)&processor
->state
== PROCESSOR_DISPATCHING
) {
235 simple_unlock(&pset
->sched_lock
);
237 simple_lock(&pset
->sched_lock
);
240 if (processor
->state
== PROCESSOR_IDLE
) {
241 remqueue(&pset
->idle_queue
, (queue_entry_t
)processor
);
245 if (processor
->state
== PROCESSOR_RUNNING
)
246 remqueue(&pset
->active_queue
, (queue_entry_t
)processor
);
248 panic("processor_request_action");
250 processor
->state
= PROCESSOR_SHUTDOWN
;
252 simple_unlock(&pset
->sched_lock
);
254 processor_unlock(processor
);
256 processor_doshutdown(processor
);
259 return (KERN_SUCCESS
);
263 * Called at splsched.
266 processor_doshutdown(
267 processor_t processor
)
269 thread_t old_thread
, self
= current_thread();
270 processor_set_t pset
;
274 * Get onto the processor to shutdown
276 prev
= thread_bind(self
, processor
);
277 thread_block(THREAD_CONTINUE_NULL
);
279 processor_lock(processor
);
280 pset
= processor
->processor_set
;
281 simple_lock(&pset
->sched_lock
);
283 if (pset
->processor_count
== 1) {
285 extern void start_cpu_thread(void);
287 simple_unlock(&pset
->sched_lock
);
288 processor_unlock(processor
);
291 * Create the thread, and point it at the routine.
293 thread
= kernel_thread_create(start_cpu_thread
, MAXPRI_KERNEL
);
296 machine_wake_thread
= thread
;
297 thread
->state
= TH_RUN
;
298 pset_run_incr(thread
->processor_set
);
299 thread_unlock(thread
);
301 processor_lock(processor
);
302 simple_lock(&pset
->sched_lock
);
305 assert(processor
->state
== PROCESSOR_SHUTDOWN
);
307 pset_remove_processor(pset
, processor
);
308 simple_unlock(&pset
->sched_lock
);
309 processor_unlock(processor
);
314 thread_bind(self
, prev
);
315 old_thread
= switch_to_shutdown_context(self
,
316 processor_offline
, processor
);
317 if (processor
!= current_processor())
318 timer_call_shutdown(processor
);
319 thread_dispatch(old_thread
);
323 * Actually do the processor shutdown. This is called at splsched,
324 * running on the processor's shutdown stack.
329 processor_t processor
)
331 register thread_t old_thread
= processor
->active_thread
;
332 register int cpu
= processor
->slot_num
;
334 timer_call_cancel(&processor
->quantum_timer
);
335 timer_switch(&kernel_timer
[cpu
]);
336 processor
->active_thread
= processor
->idle_thread
;
337 machine_thread_set_current(processor
->active_thread
);
338 thread_dispatch(old_thread
);
341 * OK, now exit this cpu.
343 PMAP_DEACTIVATE_KERNEL(cpu
);
346 panic("zombie processor");
352 host_priv_t host_priv
,
353 kernel_boot_info_t boot_info
)
356 extern char *machine_boot_info(
357 kernel_boot_info_t boot_info
,
360 if (host_priv
== HOST_PRIV_NULL
)
361 return (KERN_INVALID_HOST
);
363 assert(host_priv
== &realhost
);
366 * Copy first operator string terminated by '\0' followed by
367 * standardized strings generated from boot string.
369 src
= machine_boot_info(boot_info
, KERNEL_BOOT_INFO_MAX
);
370 if (src
!= boot_info
)
371 (void) strncpy(boot_info
, src
, KERNEL_BOOT_INFO_MAX
);
373 return (KERN_SUCCESS
);