]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/machine.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / osfmk / kern / machine.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
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.
8f6c56a5 11 *
6601e61a
A
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
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
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.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 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 Software.Distribution@CS.CMU.EDU
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 * File: kern/machine.c
54 * Author: Avadis Tevanian, Jr.
55 * Date: 1987
56 *
57 * Support for machine independent machine abstraction.
58 */
59
1c79356b 60#include <string.h>
91447636
A
61
62#include <mach/mach_types.h>
1c79356b
A
63#include <mach/boolean.h>
64#include <mach/kern_return.h>
1c79356b
A
65#include <mach/machine.h>
66#include <mach/host_info.h>
67#include <mach/host_reboot.h>
91447636
A
68#include <mach/host_priv_server.h>
69#include <mach/processor_server.h>
70
71#include <kern/kern_types.h>
1c79356b
A
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>
91447636 78#include <kern/misc_protos.h>
1c79356b
A
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>
1c79356b 84
3a60a9f5 85#include <IOKit/IOHibernatePrivate.h>
0c530ab8 86#include <IOKit/IOPlatformExpert.h>
1c79356b
A
87
88/*
89 * Exported variables:
90 */
91
92struct machine_info machine_info;
1c79356b
A
93
94/* Forwards */
1c79356b
A
95void processor_doshutdown(
96 processor_t processor);
97
98/*
91447636 99 * processor_up:
1c79356b 100 *
91447636
A
101 * Flag processor as up and running, and available
102 * for scheduling.
1c79356b
A
103 */
104void
91447636
A
105processor_up(
106 processor_t processor)
1c79356b 107{
91447636
A
108 processor_set_t pset = &default_pset;
109 spl_t s;
1c79356b
A
110
111 s = splsched();
112 processor_lock(processor);
113 init_ast_check(processor);
9bccf70c 114 simple_lock(&pset->sched_lock);
55e303ae 115 pset_add_processor(pset, processor);
9bccf70c 116 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
1c79356b 117 processor->state = PROCESSOR_RUNNING;
9bccf70c 118 simple_unlock(&pset->sched_lock);
91447636
A
119 hw_atomic_add(&machine_info.avail_cpus, 1);
120 ml_cpu_up();
1c79356b
A
121 processor_unlock(processor);
122 splx(s);
123}
124
125kern_return_t
126host_reboot(
55e303ae 127 host_priv_t host_priv,
1c79356b
A
128 int options)
129{
130 if (host_priv == HOST_PRIV_NULL)
131 return (KERN_INVALID_HOST);
132
133 assert(host_priv == &realhost);
134
135 if (options & HOST_REBOOT_DEBUGGER) {
136 Debugger("Debugger");
55e303ae 137 return (KERN_SUCCESS);
1c79356b
A
138 }
139
0c530ab8
A
140 if (options & HOST_REBOOT_UPSDELAY) {
141 // UPS power cutoff path
142 PEHaltRestart( kPEUPSDelayHaltCPU );
143 } else {
144 halt_all_cpus(!(options & HOST_REBOOT_HALT));
145 }
9bccf70c 146
55e303ae 147 return (KERN_SUCCESS);
1c79356b
A
148}
149
150kern_return_t
151processor_assign(
91447636
A
152 __unused processor_t processor,
153 __unused processor_set_t new_pset,
154 __unused boolean_t wait)
1c79356b 155{
1c79356b
A
156 return (KERN_FAILURE);
157}
158
1c79356b
A
159kern_return_t
160processor_shutdown(
55e303ae 161 processor_t processor)
1c79356b 162{
55e303ae
A
163 processor_set_t pset;
164 spl_t s;
1c79356b
A
165
166 s = splsched();
167 processor_lock(processor);
91447636 168 if (processor->state == PROCESSOR_OFF_LINE) {
1c79356b 169 /*
91447636 170 * Success if already shutdown.
1c79356b
A
171 */
172 processor_unlock(processor);
173 splx(s);
174
175 return (KERN_SUCCESS);
176 }
177
55e303ae
A
178 if (processor->state == PROCESSOR_START) {
179 /*
180 * Failure if currently being started.
181 */
182 processor_unlock(processor);
183 splx(s);
1c79356b 184
55e303ae
A
185 return (KERN_FAILURE);
186 }
1c79356b 187
55e303ae 188 /*
91447636
A
189 * Must lock the scheduling lock
190 * to get at the processor state.
55e303ae
A
191 */
192 pset = processor->processor_set;
91447636 193 if (pset != PROCESSOR_SET_NULL) {
55e303ae 194 simple_lock(&pset->sched_lock);
91447636
A
195
196 /*
197 * If the processor is dispatching, let it finish.
198 */
199 while (processor->state == PROCESSOR_DISPATCHING) {
200 simple_unlock(&pset->sched_lock);
201 delay(1);
202 simple_lock(&pset->sched_lock);
203 }
204
205 /*
206 * Success if already being shutdown.
207 */
208 if (processor->state == PROCESSOR_SHUTDOWN) {
209 simple_unlock(&pset->sched_lock);
210 processor_unlock(processor);
211 splx(s);
212
213 return (KERN_SUCCESS);
214 }
215 }
216 else {
217 /*
218 * Success, already being shutdown.
219 */
220 processor_unlock(processor);
221 splx(s);
222
223 return (KERN_SUCCESS);
55e303ae 224 }
1c79356b 225
55e303ae
A
226 if (processor->state == PROCESSOR_IDLE) {
227 remqueue(&pset->idle_queue, (queue_entry_t)processor);
228 pset->idle_count--;
229 }
230 else
231 if (processor->state == PROCESSOR_RUNNING)
232 remqueue(&pset->active_queue, (queue_entry_t)processor);
233 else
91447636 234 panic("processor_shutdown");
1c79356b 235
55e303ae 236 processor->state = PROCESSOR_SHUTDOWN;
1c79356b 237
55e303ae 238 simple_unlock(&pset->sched_lock);
1c79356b 239
55e303ae 240 processor_unlock(processor);
1c79356b 241
55e303ae 242 processor_doshutdown(processor);
1c79356b 243 splx(s);
1c79356b 244
91447636 245 cpu_exit_wait(PROCESSOR_DATA(processor, slot_num));
5353443c 246
55e303ae 247 return (KERN_SUCCESS);
1c79356b
A
248}
249
250/*
55e303ae 251 * Called at splsched.
1c79356b
A
252 */
253void
55e303ae
A
254processor_doshutdown(
255 processor_t processor)
1c79356b 256{
55e303ae 257 thread_t old_thread, self = current_thread();
1c79356b 258 processor_set_t pset;
55e303ae 259 processor_t prev;
91447636 260 int pcount;
1c79356b
A
261
262 /*
263 * Get onto the processor to shutdown
264 */
55e303ae 265 prev = thread_bind(self, processor);
9bccf70c 266 thread_block(THREAD_CONTINUE_NULL);
1c79356b 267
55e303ae 268 processor_lock(processor);
1c79356b 269 pset = processor->processor_set;
55e303ae 270 simple_lock(&pset->sched_lock);
1c79356b 271
91447636 272 if ((pcount = pset->processor_count) == 1) {
55e303ae
A
273 simple_unlock(&pset->sched_lock);
274 processor_unlock(processor);
1c79356b 275
3a60a9f5
A
276 hibernate_vm_lock();
277
55e303ae
A
278 processor_lock(processor);
279 simple_lock(&pset->sched_lock);
1c79356b
A
280 }
281
55e303ae 282 assert(processor->state == PROCESSOR_SHUTDOWN);
1c79356b
A
283
284 pset_remove_processor(pset, processor);
55e303ae 285 simple_unlock(&pset->sched_lock);
1c79356b 286 processor_unlock(processor);
1c79356b 287
3a60a9f5
A
288 if (pcount == 1)
289 hibernate_vm_unlock();
91447636 290
1c79356b 291 /*
91447636 292 * Continue processor shutdown in shutdown context.
1c79356b 293 */
55e303ae 294 thread_bind(self, prev);
91447636 295 old_thread = machine_processor_shutdown(self, processor_offline, processor);
a3d08fcd 296
91447636 297 thread_begin(self, self->last_processor);
a3d08fcd 298
1c79356b 299 thread_dispatch(old_thread);
91447636
A
300
301 /*
302 * If we just shutdown another processor, move the
303 * timer call outs to the current processor.
304 */
305 if (processor != current_processor()) {
306 processor_lock(processor);
307 if ( processor->state == PROCESSOR_OFF_LINE ||
308 processor->state == PROCESSOR_SHUTDOWN )
309 timer_call_shutdown(processor);
310 processor_unlock(processor);
311 }
1c79356b
A
312}
313
314/*
91447636
A
315 * Complete the shutdown and place the processor offline.
316 *
317 * Called at splsched in the shutdown context.
1c79356b 318 */
1c79356b 319void
55e303ae 320processor_offline(
1c79356b
A
321 processor_t processor)
322{
91447636
A
323 thread_t thread, old_thread = processor->active_thread;
324
325 thread = processor->idle_thread;
326 processor->active_thread = thread;
327 processor->current_pri = IDLEPRI;
328
329 processor->last_dispatch = mach_absolute_time();
330 timer_switch((uint32_t)processor->last_dispatch,
331 &PROCESSOR_DATA(processor, offline_timer));
332
333 thread_done(old_thread, thread, processor);
334
335 machine_set_current_thread(thread);
336
337 thread_begin(thread, processor);
1c79356b 338
55e303ae 339 thread_dispatch(old_thread);
1c79356b 340
91447636
A
341 PMAP_DEACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num));
342
343 processor_lock(processor);
344 processor->state = PROCESSOR_OFF_LINE;
345 hw_atomic_sub(&machine_info.avail_cpus, 1);
346 ml_cpu_down();
347 processor_unlock(processor);
348
1c79356b
A
349 cpu_sleep();
350 panic("zombie processor");
351 /*NOTREACHED*/
352}
353
354kern_return_t
355host_get_boot_info(
356 host_priv_t host_priv,
357 kernel_boot_info_t boot_info)
358{
91447636 359 const char *src = "";
1c79356b
A
360 if (host_priv == HOST_PRIV_NULL)
361 return (KERN_INVALID_HOST);
362
363 assert(host_priv == &realhost);
364
365 /*
366 * Copy first operator string terminated by '\0' followed by
367 * standardized strings generated from boot string.
368 */
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);
372
373 return (KERN_SUCCESS);
374}