1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#include <string.h>
61
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>
70
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>
84
85#include <IOKit/IOHibernatePrivate.h>
86
87
88
89
90
91struct machine_info machine_info;
92
93
94void processor_doshutdown(
95 processor_t processor);
96
97
98
99
100
101
102
103void
104processor_up(
105 processor_t processor)
106{
107 processor_set_t pset = &default_pset;
108 spl_t s;
109
110 s = splsched();
111 processor_lock(processor);
112 init_ast_check(processor);
113 simple_lock(&pset->sched_lock);
114 pset_add_processor(pset, processor);
115 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
116 processor->state = PROCESSOR_RUNNING;
117 simple_unlock(&pset->sched_lock);
118 hw_atomic_add(&machine_info.avail_cpus, 1);
119 ml_cpu_up();
120 processor_unlock(processor);
121 splx(s);
122}
123
124kern_return_t
125host_reboot(
126 host_priv_t host_priv,
127 int options)
128{
129 if (host_priv == HOST_PRIV_NULL)
130 return (KERN_INVALID_HOST);
131
132 assert(host_priv == &realhost);
133
134 if (options & HOST_REBOOT_DEBUGGER) {
135 Debugger("Debugger");
136 return (KERN_SUCCESS);
137 }
138
139 halt_all_cpus(!(options & HOST_REBOOT_HALT));
140
141 return (KERN_SUCCESS);
142}
143
144kern_return_t
145processor_assign(
146 __unused processor_t processor,
147 __unused processor_set_t new_pset,
148 __unused boolean_t wait)
149{
150 return (KERN_FAILURE);
151}
152
153kern_return_t
154processor_shutdown(
155 processor_t processor)
156{
157 processor_set_t pset;
158 spl_t s;
159
160 s = splsched();
161 processor_lock(processor);
162 if (processor->state == PROCESSOR_OFF_LINE) {
163
164
165
166 processor_unlock(processor);
167 splx(s);
168
169 return (KERN_SUCCESS);
170 }
171
172 if (processor->state == PROCESSOR_START) {
173
174
175
176 processor_unlock(processor);
177 splx(s);
178
179 return (KERN_FAILURE);
180 }
181
182
183
184
185
186 pset = processor->processor_set;
187 if (pset != PROCESSOR_SET_NULL) {
188 simple_lock(&pset->sched_lock);
189
190
191
192
193 while (processor->state == PROCESSOR_DISPATCHING) {
194 simple_unlock(&pset->sched_lock);
195 delay(1);
196 simple_lock(&pset->sched_lock);
197 }
198
199
200
201
202 if (processor->state == PROCESSOR_SHUTDOWN) {
203 simple_unlock(&pset->sched_lock);
204 processor_unlock(processor);
205 splx(s);
206
207 return (KERN_SUCCESS);
208 }
209 }
210 else {
211
212
213
214 processor_unlock(processor);
215 splx(s);
216
217 return (KERN_SUCCESS);
218 }
219
220 if (processor->state == PROCESSOR_IDLE) {
221 remqueue(&pset->idle_queue, (queue_entry_t)processor);
222 pset->idle_count--;
223 }
224 else
225 if (processor->state == PROCESSOR_RUNNING)
226 remqueue(&pset->active_queue, (queue_entry_t)processor);
227 else
228 panic("processor_shutdown");
229
230 processor->state = PROCESSOR_SHUTDOWN;
231
232 simple_unlock(&pset->sched_lock);
233
234 processor_unlock(processor);
235
236 processor_doshutdown(processor);
237 splx(s);
238
239 cpu_exit_wait(PROCESSOR_DATA(processor, slot_num));
240
241 return (KERN_SUCCESS);
242}
243
244
245
246
247void
248processor_doshutdown(
249 processor_t processor)
250{
251 thread_t old_thread, self = current_thread();
252 processor_set_t pset;
253 processor_t prev;
254 int pcount;
255
256
257
258
259 prev = thread_bind(self, processor);
260 thread_block(THREAD_CONTINUE_NULL);
261
262 processor_lock(processor);
263 pset = processor->processor_set;
264 simple_lock(&pset->sched_lock);
265
266 if ((pcount = pset->processor_count) == 1) {
267 simple_unlock(&pset->sched_lock);
268 processor_unlock(processor);
269
270 hibernate_vm_lock();
271
272 processor_lock(processor);
273 simple_lock(&pset->sched_lock);
274 }
275
276 assert(processor->state == PROCESSOR_SHUTDOWN);
277
278 pset_remove_processor(pset, processor);
279 simple_unlock(&pset->sched_lock);
280 processor_unlock(processor);
281
282 if (pcount == 1)
283 hibernate_vm_unlock();
284
285
286
287
288 thread_bind(self, prev);
289 old_thread = machine_processor_shutdown(self, processor_offline, processor);
290
291 thread_begin(self, self->last_processor);
292
293 thread_dispatch(old_thread);
294
295
296
297
298
299 if (processor != current_processor()) {
300 processor_lock(processor);
301 if ( processor->state == PROCESSOR_OFF_LINE ||
302 processor->state == PROCESSOR_SHUTDOWN )
303 timer_call_shutdown(processor);
304 processor_unlock(processor);
305 }
306}
307
308
309
310
311
312
313void
314processor_offline(
315 processor_t processor)
316{
317 thread_t thread, old_thread = processor->active_thread;
318
319 thread = processor->idle_thread;
320 processor->active_thread = thread;
321 processor->current_pri = IDLEPRI;
322
323 processor->last_dispatch = mach_absolute_time();
324 timer_switch((uint32_t)processor->last_dispatch,
325 &PROCESSOR_DATA(processor, offline_timer));
326
327 thread_done(old_thread, thread, processor);
328
329 machine_set_current_thread(thread);
330
331 thread_begin(thread, processor);
332
333 thread_dispatch(old_thread);
334
335 PMAP_DEACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num));
336
337 processor_lock(processor);
338 processor->state = PROCESSOR_OFF_LINE;
339 hw_atomic_sub(&machine_info.avail_cpus, 1);
340 ml_cpu_down();
341 processor_unlock(processor);
342
343 cpu_sleep();
344 panic("zombie processor");
345
346}
347
348kern_return_t
349host_get_boot_info(
350 host_priv_t host_priv,
351 kernel_boot_info_t boot_info)
352{
353 const char *src = "";
354 if (host_priv == HOST_PRIV_NULL)
355 return (KERN_INVALID_HOST);
356
357 assert(host_priv == &realhost);
358
359
360
361
362
363 src = machine_boot_info(boot_info, KERNEL_BOOT_INFO_MAX);
364 if (src != boot_info)
365 (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
366
367 return (KERN_SUCCESS);
368}
369