]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/mp.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / osfmk / i386 / mp.c
CommitLineData
55e303ae 1/*
39236c6e 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
55e303ae 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
55e303ae 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
55e303ae
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
55e303ae 32#include <mach_rt.h>
55e303ae
A
33#include <mach_kdp.h>
34#include <mach_ldebug.h>
91447636
A
35#include <gprof.h>
36
37#include <mach/mach_types.h>
38#include <mach/kern_return.h>
39
40#include <kern/kern_types.h>
41#include <kern/startup.h>
c910b4d9 42#include <kern/timer_queue.h>
91447636
A
43#include <kern/processor.h>
44#include <kern/cpu_number.h>
45#include <kern/cpu_data.h>
46#include <kern/assert.h>
47#include <kern/machine.h>
0c530ab8 48#include <kern/pms.h>
593a1d5f 49#include <kern/misc_protos.h>
39236c6e 50#include <kern/timer_call.h>
6d2010ae
A
51#include <kern/kalloc.h>
52#include <kern/queue.h>
91447636
A
53
54#include <vm/vm_map.h>
55#include <vm/vm_kern.h>
56
57#include <profiling/profile-mk.h>
55e303ae 58
b0d623f7
A
59#include <i386/proc_reg.h>
60#include <i386/cpu_threads.h>
61#include <i386/mp_desc.h>
62#include <i386/misc_protos.h>
63#include <i386/trap.h>
64#include <i386/postcode.h>
65#include <i386/machine_routines.h>
55e303ae
A
66#include <i386/mp.h>
67#include <i386/mp_events.h>
593a1d5f 68#include <i386/lapic.h>
55e303ae 69#include <i386/cpuid.h>
b0d623f7 70#include <i386/fpu.h>
55e303ae 71#include <i386/machine_cpu.h>
0c530ab8 72#include <i386/pmCPU.h>
b0d623f7 73#if CONFIG_MCA
2d21ac55 74#include <i386/machine_check.h>
b0d623f7
A
75#endif
76#include <i386/acpi.h>
0c530ab8
A
77
78#include <chud/chud_xnu.h>
79#include <chud/chud_xnu_private.h>
80
81#include <sys/kdebug.h>
55e303ae 82
39236c6e
A
83#include <console/serial_protos.h>
84
55e303ae
A
85#if MP_DEBUG
86#define PAUSE delay(1000000)
87#define DBG(x...) kprintf(x)
88#else
89#define DBG(x...)
90#define PAUSE
91#endif /* MP_DEBUG */
92
6d2010ae
A
93/* Debugging/test trace events: */
94#define TRACE_MP_TLB_FLUSH MACHDBG_CODE(DBG_MACH_MP, 0)
95#define TRACE_MP_CPUS_CALL MACHDBG_CODE(DBG_MACH_MP, 1)
96#define TRACE_MP_CPUS_CALL_LOCAL MACHDBG_CODE(DBG_MACH_MP, 2)
97#define TRACE_MP_CPUS_CALL_ACTION MACHDBG_CODE(DBG_MACH_MP, 3)
98#define TRACE_MP_CPUS_CALL_NOBUF MACHDBG_CODE(DBG_MACH_MP, 4)
bd504ef0
A
99#define TRACE_MP_CPU_FAST_START MACHDBG_CODE(DBG_MACH_MP, 5)
100#define TRACE_MP_CPU_START MACHDBG_CODE(DBG_MACH_MP, 6)
101#define TRACE_MP_CPU_DEACTIVATE MACHDBG_CODE(DBG_MACH_MP, 7)
55e303ae 102
7e4a7d39
A
103#define ABS(v) (((v) > 0)?(v):-(v))
104
55e303ae 105void slave_boot_init(void);
6d2010ae 106void i386_cpu_IPI(int cpu);
55e303ae 107
39236c6e 108#if MACH_KDP
b0d623f7 109static void mp_kdp_wait(boolean_t flush, boolean_t isNMI);
39236c6e 110#endif /* MACH_KDP */
55e303ae 111static void mp_rendezvous_action(void);
2d21ac55 112static void mp_broadcast_action(void);
55e303ae 113
39236c6e 114#if MACH_KDP
0c530ab8 115static boolean_t cpu_signal_pending(int cpu, mp_event_t event);
39236c6e 116#endif /* MACH_KDP */
593a1d5f 117static int NMIInterruptHandler(x86_saved_state_t *regs);
0c530ab8 118
b0d623f7 119boolean_t smp_initialized = FALSE;
7e4a7d39 120uint32_t TSC_sync_margin = 0xFFF;
935ed37a
A
121volatile boolean_t force_immediate_debugger_NMI = FALSE;
122volatile boolean_t pmap_tlb_flush_timeout = FALSE;
55e303ae 123decl_simple_lock_data(,mp_kdp_lock);
91447636 124
b0d623f7
A
125decl_lck_mtx_data(static, mp_cpu_boot_lock);
126lck_mtx_ext_t mp_cpu_boot_lock_ext;
55e303ae
A
127
128/* Variables needed for MP rendezvous. */
0c530ab8 129decl_simple_lock_data(,mp_rv_lock);
b0d623f7
A
130static void (*mp_rv_setup_func)(void *arg);
131static void (*mp_rv_action_func)(void *arg);
132static void (*mp_rv_teardown_func)(void *arg);
133static void *mp_rv_func_arg;
134static volatile int mp_rv_ncpus;
0c530ab8
A
135 /* Cache-aligned barriers: */
136static volatile long mp_rv_entry __attribute__((aligned(64)));
137static volatile long mp_rv_exit __attribute__((aligned(64)));
138static volatile long mp_rv_complete __attribute__((aligned(64)));
55e303ae 139
b0d623f7
A
140volatile uint64_t debugger_entry_time;
141volatile uint64_t debugger_exit_time;
142#if MACH_KDP
7ddcb079 143#include <kdp/kdp.h>
d41d1dae 144extern int kdp_snapshot;
b0d623f7
A
145static struct _kdp_xcpu_call_func {
146 kdp_x86_xcpu_func_t func;
147 void *arg0, *arg1;
148 volatile long ret;
149 volatile uint16_t cpu;
150} kdp_xcpu_call_func = {
151 .cpu = KDP_XCPU_NONE
152};
153
154#endif
155
2d21ac55
A
156/* Variables needed for MP broadcast. */
157static void (*mp_bc_action_func)(void *arg);
158static void *mp_bc_func_arg;
593a1d5f 159static int mp_bc_ncpus;
2d21ac55 160static volatile long mp_bc_count;
b0d623f7
A
161decl_lck_mtx_data(static, mp_bc_lock);
162lck_mtx_ext_t mp_bc_lock_ext;
593a1d5f 163static volatile int debugger_cpu = -1;
39236c6e
A
164volatile long NMIPI_acks = 0;
165volatile long NMI_count = 0;
166
167extern void NMI_cpus(void);
2d21ac55 168
6d2010ae
A
169static void mp_cpus_call_init(void);
170static void mp_cpus_call_cpu_init(void);
2d21ac55 171static void mp_cpus_call_action(void);
c910b4d9 172static void mp_call_PM(void);
2d21ac55 173
b0d623f7
A
174char mp_slave_stack[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); // Temp stack for slave init
175
6d2010ae
A
176/* PAL-related routines */
177boolean_t i386_smp_init(int nmi_vector, i386_intr_func_t nmi_handler,
178 int ipi_vector, i386_intr_func_t ipi_handler);
179void i386_start_cpu(int lapic_id, int cpu_num);
180void i386_send_NMI(int cpu);
b0d623f7 181
91447636
A
182#if GPROF
183/*
184 * Initialize dummy structs for profiling. These aren't used but
185 * allows hertz_tick() to be built with GPROF defined.
186 */
187struct profile_vars _profile_vars;
188struct profile_vars *_profile_vars_cpus[MAX_CPUS] = { &_profile_vars };
189#define GPROF_INIT() \
190{ \
191 int i; \
192 \
193 /* Hack to initialize pointers to unused profiling structs */ \
194 for (i = 1; i < MAX_CPUS; i++) \
195 _profile_vars_cpus[i] = &_profile_vars; \
196}
197#else
198#define GPROF_INIT()
199#endif /* GPROF */
200
b0d623f7
A
201static lck_grp_t smp_lck_grp;
202static lck_grp_attr_t smp_lck_grp_attr;
203
6d2010ae
A
204#define NUM_CPU_WARM_CALLS 20
205struct timer_call cpu_warm_call_arr[NUM_CPU_WARM_CALLS];
206queue_head_t cpu_warm_call_list;
207decl_simple_lock_data(static, cpu_warm_lock);
208
209typedef struct cpu_warm_data {
210 timer_call_t cwd_call;
211 uint64_t cwd_deadline;
212 int cwd_result;
213} *cpu_warm_data_t;
214
215static void cpu_prewarm_init(void);
216static void cpu_warm_timer_call_func(call_entry_param_t p0, call_entry_param_t p1);
217static void _cpu_warm_setup(void *arg);
218static timer_call_t grab_warm_timer_call(void);
219static void free_warm_timer_call(timer_call_t call);
b0d623f7 220
55e303ae
A
221void
222smp_init(void)
55e303ae 223{
91447636
A
224 simple_lock_init(&mp_kdp_lock, 0);
225 simple_lock_init(&mp_rv_lock, 0);
b0d623f7
A
226 lck_grp_attr_setdefault(&smp_lck_grp_attr);
227 lck_grp_init(&smp_lck_grp, "i386_smp", &smp_lck_grp_attr);
228 lck_mtx_init_ext(&mp_cpu_boot_lock, &mp_cpu_boot_lock_ext, &smp_lck_grp, LCK_ATTR_NULL);
229 lck_mtx_init_ext(&mp_bc_lock, &mp_bc_lock_ext, &smp_lck_grp, LCK_ATTR_NULL);
91447636 230 console_init();
55e303ae 231
6d2010ae
A
232 if(!i386_smp_init(LAPIC_NMI_INTERRUPT, NMIInterruptHandler,
233 LAPIC_VECTOR(INTERPROCESSOR), cpu_signal_handler))
55e303ae
A
234 return;
235
91447636
A
236 cpu_thread_init();
237
91447636
A
238 GPROF_INIT();
239 DBGLOG_CPU_INIT(master_cpu);
240
6d2010ae
A
241 mp_cpus_call_init();
242 mp_cpus_call_cpu_init();
55e303ae 243
7e4a7d39 244 if (PE_parse_boot_argn("TSC_sync_margin",
316670eb 245 &TSC_sync_margin, sizeof(TSC_sync_margin))) {
7e4a7d39 246 kprintf("TSC sync Margin 0x%x\n", TSC_sync_margin);
316670eb
A
247 } else if (cpuid_vmm_present()) {
248 kprintf("TSC sync margin disabled\n");
249 TSC_sync_margin = 0;
250 }
55e303ae
A
251 smp_initialized = TRUE;
252
6d2010ae
A
253 cpu_prewarm_init();
254
55e303ae
A
255 return;
256}
257
7e4a7d39
A
258typedef struct {
259 int target_cpu;
260 int target_lapic;
261 int starter_cpu;
262} processor_start_info_t;
263static processor_start_info_t start_info __attribute__((aligned(64)));
264
265/*
266 * Cache-alignment is to avoid cross-cpu false-sharing interference.
267 */
268static volatile long tsc_entry_barrier __attribute__((aligned(64)));
269static volatile long tsc_exit_barrier __attribute__((aligned(64)));
270static volatile uint64_t tsc_target __attribute__((aligned(64)));
271
0c530ab8 272/*
593a1d5f 273 * Poll a CPU to see when it has marked itself as running.
0c530ab8 274 */
593a1d5f
A
275static void
276mp_wait_for_cpu_up(int slot_num, unsigned int iters, unsigned int usecdelay)
91447636 277{
7e4a7d39 278 while (iters-- > 0) {
593a1d5f 279 if (cpu_datap(slot_num)->cpu_running)
7e4a7d39 280 break;
593a1d5f 281 delay(usecdelay);
91447636 282 }
55e303ae
A
283}
284
b0d623f7
A
285/*
286 * Quickly bring a CPU back online which has been halted.
287 */
288kern_return_t
289intel_startCPU_fast(int slot_num)
290{
7e4a7d39 291 kern_return_t rc;
b0d623f7
A
292
293 /*
294 * Try to perform a fast restart
295 */
296 rc = pmCPUExitHalt(slot_num);
297 if (rc != KERN_SUCCESS)
298 /*
299 * The CPU was not eligible for a fast restart.
300 */
301 return(rc);
302
bd504ef0
A
303 KERNEL_DEBUG_CONSTANT(
304 TRACE_MP_CPU_FAST_START | DBG_FUNC_START,
305 slot_num, 0, 0, 0, 0);
306
b0d623f7
A
307 /*
308 * Wait until the CPU is back online.
309 */
310 mp_disable_preemption();
311
312 /*
313 * We use short pauses (1us) for low latency. 30,000 iterations is
314 * longer than a full restart would require so it should be more
315 * than long enough.
316 */
6d2010ae 317
b0d623f7
A
318 mp_wait_for_cpu_up(slot_num, 30000, 1);
319 mp_enable_preemption();
320
bd504ef0
A
321 KERNEL_DEBUG_CONSTANT(
322 TRACE_MP_CPU_FAST_START | DBG_FUNC_END,
323 slot_num, cpu_datap(slot_num)->cpu_running, 0, 0, 0);
324
b0d623f7
A
325 /*
326 * Check to make sure that the CPU is really running. If not,
327 * go through the slow path.
328 */
329 if (cpu_datap(slot_num)->cpu_running)
330 return(KERN_SUCCESS);
7e4a7d39 331 else
b0d623f7
A
332 return(KERN_FAILURE);
333}
334
7e4a7d39
A
335static void
336started_cpu(void)
337{
338 /* Here on the started cpu with cpu_running set TRUE */
c910b4d9 339
7e4a7d39
A
340 if (TSC_sync_margin &&
341 start_info.target_cpu == cpu_number()) {
342 /*
343 * I've just started-up, synchronize again with the starter cpu
344 * and then snap my TSC.
345 */
346 tsc_target = 0;
347 atomic_decl(&tsc_entry_barrier, 1);
348 while (tsc_entry_barrier != 0)
349 ; /* spin for starter and target at barrier */
350 tsc_target = rdtsc64();
351 atomic_decl(&tsc_exit_barrier, 1);
352 }
353}
c910b4d9
A
354
355static void
356start_cpu(void *arg)
357{
358 int i = 1000;
359 processor_start_info_t *psip = (processor_start_info_t *) arg;
360
361 /* Ignore this if the current processor is not the starter */
362 if (cpu_number() != psip->starter_cpu)
363 return;
364
bd504ef0
A
365 DBG("start_cpu(%p) about to start cpu %d, lapic %d\n",
366 arg, psip->target_cpu, psip->target_lapic);
367
368 KERNEL_DEBUG_CONSTANT(
369 TRACE_MP_CPU_START | DBG_FUNC_START,
370 psip->target_cpu,
371 psip->target_lapic, 0, 0, 0);
372
6d2010ae 373 i386_start_cpu(psip->target_lapic, psip->target_cpu);
c910b4d9
A
374
375#ifdef POSTCODE_DELAY
376 /* Wait much longer if postcodes are displayed for a delay period. */
377 i *= 10000;
378#endif
bd504ef0
A
379 DBG("start_cpu(%p) about to wait for cpu %d\n",
380 arg, psip->target_cpu);
381
c910b4d9 382 mp_wait_for_cpu_up(psip->target_cpu, i*100, 100);
bd504ef0
A
383
384 KERNEL_DEBUG_CONSTANT(
385 TRACE_MP_CPU_START | DBG_FUNC_END,
386 psip->target_cpu,
387 cpu_datap(psip->target_cpu)->cpu_running, 0, 0, 0);
388
7e4a7d39
A
389 if (TSC_sync_margin &&
390 cpu_datap(psip->target_cpu)->cpu_running) {
391 /*
392 * Compare the TSC from the started processor with ours.
393 * Report and log/panic if it diverges by more than
394 * TSC_sync_margin (TSC_SYNC_MARGIN) ticks. This margin
395 * can be overriden by boot-arg (with 0 meaning no checking).
396 */
397 uint64_t tsc_starter;
398 int64_t tsc_delta;
399 atomic_decl(&tsc_entry_barrier, 1);
400 while (tsc_entry_barrier != 0)
401 ; /* spin for both processors at barrier */
402 tsc_starter = rdtsc64();
403 atomic_decl(&tsc_exit_barrier, 1);
404 while (tsc_exit_barrier != 0)
405 ; /* spin for target to store its TSC */
406 tsc_delta = tsc_target - tsc_starter;
407 kprintf("TSC sync for cpu %d: 0x%016llx delta 0x%llx (%lld)\n",
408 psip->target_cpu, tsc_target, tsc_delta, tsc_delta);
409 if (ABS(tsc_delta) > (int64_t) TSC_sync_margin) {
410#if DEBUG
411 panic(
412#else
413 printf(
414#endif
415 "Unsynchronized TSC for cpu %d: "
416 "0x%016llx, delta 0x%llx\n",
417 psip->target_cpu, tsc_target, tsc_delta);
418 }
419 }
c910b4d9
A
420}
421
55e303ae
A
422kern_return_t
423intel_startCPU(
424 int slot_num)
425{
c910b4d9
A
426 int lapic = cpu_to_lapic[slot_num];
427 boolean_t istate;
55e303ae 428
91447636
A
429 assert(lapic != -1);
430
431 DBGLOG_CPU_INIT(slot_num);
55e303ae 432
91447636 433 DBG("intel_startCPU(%d) lapic_id=%d\n", slot_num, lapic);
6d2010ae 434 DBG("IdlePTD(%p): 0x%x\n", &IdlePTD, (int) (uintptr_t)IdlePTD);
55e303ae 435
0c530ab8
A
436 /*
437 * Initialize (or re-initialize) the descriptor tables for this cpu.
438 * Propagate processor mode to slave.
439 */
39236c6e 440 cpu_desc_init64(cpu_datap(slot_num));
91447636 441
c910b4d9 442 /* Serialize use of the slave boot stack, etc. */
b0d623f7 443 lck_mtx_lock(&mp_cpu_boot_lock);
55e303ae 444
c910b4d9 445 istate = ml_set_interrupts_enabled(FALSE);
91447636 446 if (slot_num == get_cpu_number()) {
c910b4d9 447 ml_set_interrupts_enabled(istate);
b0d623f7 448 lck_mtx_unlock(&mp_cpu_boot_lock);
91447636
A
449 return KERN_SUCCESS;
450 }
55e303ae 451
b0d623f7
A
452 start_info.starter_cpu = cpu_number();
453 start_info.target_cpu = slot_num;
c910b4d9 454 start_info.target_lapic = lapic;
7e4a7d39
A
455 tsc_entry_barrier = 2;
456 tsc_exit_barrier = 2;
55e303ae 457
c910b4d9 458 /*
b0d623f7 459 * Perform the processor startup sequence with all running
c910b4d9
A
460 * processors rendezvous'ed. This is required during periods when
461 * the cache-disable bit is set for MTRR/PAT initialization.
462 */
b0d623f7 463 mp_rendezvous_no_intrs(start_cpu, (void *) &start_info);
55e303ae 464
7e4a7d39
A
465 start_info.target_cpu = 0;
466
c910b4d9 467 ml_set_interrupts_enabled(istate);
b0d623f7 468 lck_mtx_unlock(&mp_cpu_boot_lock);
55e303ae 469
91447636 470 if (!cpu_datap(slot_num)->cpu_running) {
0c530ab8 471 kprintf("Failed to start CPU %02d\n", slot_num);
91447636
A
472 printf("Failed to start CPU %02d, rebooting...\n", slot_num);
473 delay(1000000);
b0d623f7 474 halt_cpu();
55e303ae
A
475 return KERN_SUCCESS;
476 } else {
2d21ac55 477 kprintf("Started cpu %d (lapic id %08x)\n", slot_num, lapic);
55e303ae
A
478 return KERN_SUCCESS;
479 }
480}
481
55e303ae 482#if MP_DEBUG
91447636
A
483cpu_signal_event_log_t *cpu_signal[MAX_CPUS];
484cpu_signal_event_log_t *cpu_handle[MAX_CPUS];
55e303ae
A
485
486MP_EVENT_NAME_DECL();
487
55e303ae
A
488#endif /* MP_DEBUG */
489
593a1d5f 490int
0c530ab8 491cpu_signal_handler(x86_saved_state_t *regs)
55e303ae 492{
39236c6e
A
493#if !MACH_KDP
494#pragma unused (regs)
495#endif /* !MACH_KDP */
91447636 496 int my_cpu;
55e303ae 497 volatile int *my_word;
55e303ae 498
6d2010ae 499 SCHED_STATS_IPI(current_processor());
55e303ae
A
500
501 my_cpu = cpu_number();
060df5ea
A
502 my_word = &cpu_data_ptr[my_cpu]->cpu_signals;
503 /* Store the initial set of signals for diagnostics. New
504 * signals could arrive while these are being processed
505 * so it's no more than a hint.
506 */
6d2010ae 507
060df5ea 508 cpu_data_ptr[my_cpu]->cpu_prior_signals = *my_word;
55e303ae
A
509
510 do {
55e303ae 511#if MACH_KDP
39236c6e 512 if (i_bit(MP_KDP, my_word) && regs != NULL) {
55e303ae
A
513 DBGLOG(cpu_handle,my_cpu,MP_KDP);
514 i_bit_clear(MP_KDP, my_word);
0c530ab8
A
515/* Ensure that the i386_kernel_state at the base of the
516 * current thread's stack (if any) is synchronized with the
517 * context at the moment of the interrupt, to facilitate
518 * access through the debugger.
0c530ab8 519 */
b0d623f7 520 sync_iss_to_iks(regs);
d41d1dae
A
521 if (pmsafe_debug && !kdp_snapshot)
522 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
b0d623f7 523 mp_kdp_wait(TRUE, FALSE);
d41d1dae
A
524 if (pmsafe_debug && !kdp_snapshot)
525 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL);
55e303ae
A
526 } else
527#endif /* MACH_KDP */
91447636 528 if (i_bit(MP_TLB_FLUSH, my_word)) {
55e303ae
A
529 DBGLOG(cpu_handle,my_cpu,MP_TLB_FLUSH);
530 i_bit_clear(MP_TLB_FLUSH, my_word);
531 pmap_update_interrupt();
532 } else if (i_bit(MP_AST, my_word)) {
533 DBGLOG(cpu_handle,my_cpu,MP_AST);
534 i_bit_clear(MP_AST, my_word);
535 ast_check(cpu_to_processor(my_cpu));
55e303ae
A
536 } else if (i_bit(MP_RENDEZVOUS, my_word)) {
537 DBGLOG(cpu_handle,my_cpu,MP_RENDEZVOUS);
538 i_bit_clear(MP_RENDEZVOUS, my_word);
539 mp_rendezvous_action();
2d21ac55
A
540 } else if (i_bit(MP_BROADCAST, my_word)) {
541 DBGLOG(cpu_handle,my_cpu,MP_BROADCAST);
542 i_bit_clear(MP_BROADCAST, my_word);
543 mp_broadcast_action();
0c530ab8
A
544 } else if (i_bit(MP_CHUD, my_word)) {
545 DBGLOG(cpu_handle,my_cpu,MP_CHUD);
546 i_bit_clear(MP_CHUD, my_word);
547 chudxnu_cpu_signal_handler();
2d21ac55
A
548 } else if (i_bit(MP_CALL, my_word)) {
549 DBGLOG(cpu_handle,my_cpu,MP_CALL);
550 i_bit_clear(MP_CALL, my_word);
551 mp_cpus_call_action();
c910b4d9
A
552 } else if (i_bit(MP_CALL_PM, my_word)) {
553 DBGLOG(cpu_handle,my_cpu,MP_CALL_PM);
554 i_bit_clear(MP_CALL_PM, my_word);
555 mp_call_PM();
55e303ae
A
556 }
557 } while (*my_word);
558
593a1d5f 559 return 0;
55e303ae
A
560}
561
593a1d5f 562static int
2d21ac55 563NMIInterruptHandler(x86_saved_state_t *regs)
0c530ab8 564{
935ed37a 565 void *stackptr;
060df5ea 566
6d2010ae
A
567 if (panic_active() && !panicDebugging) {
568 if (pmsafe_debug)
569 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
570 for(;;)
571 cpu_pause();
572 }
573
060df5ea 574 atomic_incl(&NMIPI_acks, 1);
39236c6e 575 atomic_incl(&NMI_count, 1);
0c530ab8 576 sync_iss_to_iks_unconditionally(regs);
b0d623f7 577 __asm__ volatile("movq %%rbp, %0" : "=m" (stackptr));
935ed37a 578
593a1d5f
A
579 if (cpu_number() == debugger_cpu)
580 goto NMExit;
581
060df5ea 582 if (spinlock_timed_out) {
7ddcb079 583 char pstr[192];
060df5ea
A
584 snprintf(&pstr[0], sizeof(pstr), "Panic(CPU %d): NMIPI for spinlock acquisition timeout, spinlock: %p, spinlock owner: %p, current_thread: %p, spinlock_owner_cpu: 0x%x\n", cpu_number(), spinlock_timed_out, (void *) spinlock_timed_out->interlock.lock_data, current_thread(), spinlock_owner_cpu);
585 panic_i386_backtrace(stackptr, 64, &pstr[0], TRUE, regs);
060df5ea 586 } else if (pmap_tlb_flush_timeout == TRUE) {
593a1d5f 587 char pstr[128];
7ddcb079 588 snprintf(&pstr[0], sizeof(pstr), "Panic(CPU %d): Unresponsive processor (this CPU did not acknowledge interrupts) TLB state:0x%x\n", cpu_number(), current_cpu_datap()->cpu_tlb_invalid);
6d2010ae 589 panic_i386_backtrace(stackptr, 48, &pstr[0], TRUE, regs);
935ed37a 590 }
b0d623f7
A
591
592#if MACH_KDP
d41d1dae
A
593 if (pmsafe_debug && !kdp_snapshot)
594 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
060df5ea 595 current_cpu_datap()->cpu_NMI_acknowledged = TRUE;
15129b1c 596 i_bit_clear(MP_KDP, &current_cpu_datap()->cpu_signals);
060df5ea 597 mp_kdp_wait(FALSE, pmap_tlb_flush_timeout || spinlock_timed_out || panic_active());
d41d1dae
A
598 if (pmsafe_debug && !kdp_snapshot)
599 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL);
b0d623f7 600#endif
593a1d5f 601NMExit:
0c530ab8
A
602 return 1;
603}
604
2d21ac55
A
605
606/*
607 * cpu_interrupt is really just to be used by the scheduler to
608 * get a CPU's attention it may not always issue an IPI. If an
609 * IPI is always needed then use i386_cpu_IPI.
610 */
611void
612cpu_interrupt(int cpu)
613{
6d2010ae
A
614 boolean_t did_IPI = FALSE;
615
2d21ac55
A
616 if (smp_initialized
617 && pmCPUExitIdle(cpu_datap(cpu))) {
618 i386_cpu_IPI(cpu);
6d2010ae 619 did_IPI = TRUE;
2d21ac55 620 }
6d2010ae
A
621
622 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_REMOTE_AST), cpu, did_IPI, 0, 0, 0);
55e303ae
A
623}
624
0c530ab8
A
625/*
626 * Send a true NMI via the local APIC to the specified CPU.
627 */
935ed37a 628void
0c530ab8
A
629cpu_NMI_interrupt(int cpu)
630{
0c530ab8 631 if (smp_initialized) {
6d2010ae 632 i386_send_NMI(cpu);
0c530ab8 633 }
0c530ab8
A
634}
635
39236c6e
A
636void
637NMI_cpus(void)
638{
639 unsigned int cpu;
640 boolean_t intrs_enabled;
641 uint64_t tsc_timeout;
642
643 intrs_enabled = ml_set_interrupts_enabled(FALSE);
644
645 for (cpu = 0; cpu < real_ncpus; cpu++) {
646 if (!cpu_datap(cpu)->cpu_running)
647 continue;
648 cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE;
649 cpu_NMI_interrupt(cpu);
650 tsc_timeout = !machine_timeout_suspended() ?
651 rdtsc64() + (1000 * 1000 * 1000 * 10ULL) :
652 ~0ULL;
653 while (!cpu_datap(cpu)->cpu_NMI_acknowledged) {
654 handle_pending_TLB_flushes();
655 cpu_pause();
656 if (rdtsc64() > tsc_timeout)
657 panic("NMI_cpus() timeout cpu %d", cpu);
658 }
659 cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE;
660 }
661
662 ml_set_interrupts_enabled(intrs_enabled);
663}
664
b0d623f7 665static void (* volatile mp_PM_func)(void) = NULL;
c910b4d9
A
666
667static void
668mp_call_PM(void)
669{
670 assert(!ml_get_interrupts_enabled());
671
672 if (mp_PM_func != NULL)
673 mp_PM_func();
674}
675
676void
677cpu_PM_interrupt(int cpu)
678{
679 assert(!ml_get_interrupts_enabled());
680
681 if (mp_PM_func != NULL) {
682 if (cpu == cpu_number())
683 mp_PM_func();
684 else
685 i386_signal_cpu(cpu, MP_CALL_PM, ASYNC);
686 }
687}
688
689void
690PM_interrupt_register(void (*fn)(void))
691{
692 mp_PM_func = fn;
693}
694
55e303ae
A
695void
696i386_signal_cpu(int cpu, mp_event_t event, mp_sync_t mode)
697{
91447636
A
698 volatile int *signals = &cpu_datap(cpu)->cpu_signals;
699 uint64_t tsc_timeout;
6601e61a 700
0c530ab8 701
91447636 702 if (!cpu_datap(cpu)->cpu_running)
55e303ae
A
703 return;
704
0c530ab8 705 if (event == MP_TLB_FLUSH)
6d2010ae 706 KERNEL_DEBUG(TRACE_MP_TLB_FLUSH | DBG_FUNC_START, cpu, 0, 0, 0, 0);
6601e61a 707
0c530ab8
A
708 DBGLOG(cpu_signal, cpu, event);
709
55e303ae 710 i_bit_set(event, signals);
2d21ac55 711 i386_cpu_IPI(cpu);
55e303ae
A
712 if (mode == SYNC) {
713 again:
39236c6e
A
714 tsc_timeout = !machine_timeout_suspended() ?
715 rdtsc64() + (1000*1000*1000) :
716 ~0ULL;
91447636 717 while (i_bit(event, signals) && rdtsc64() < tsc_timeout) {
55e303ae
A
718 cpu_pause();
719 }
720 if (i_bit(event, signals)) {
721 DBG("i386_signal_cpu(%d, 0x%x, SYNC) timed out\n",
722 cpu, event);
723 goto again;
724 }
725 }
0c530ab8 726 if (event == MP_TLB_FLUSH)
6d2010ae 727 KERNEL_DEBUG(TRACE_MP_TLB_FLUSH | DBG_FUNC_END, cpu, 0, 0, 0, 0);
55e303ae
A
728}
729
2d21ac55
A
730/*
731 * Send event to all running cpus.
732 * Called with the topology locked.
733 */
55e303ae
A
734void
735i386_signal_cpus(mp_event_t event, mp_sync_t mode)
736{
91447636
A
737 unsigned int cpu;
738 unsigned int my_cpu = cpu_number();
55e303ae 739
b0d623f7 740 assert(hw_lock_held((hw_lock_t)&x86_topo_lock));
2d21ac55 741
91447636
A
742 for (cpu = 0; cpu < real_ncpus; cpu++) {
743 if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running)
55e303ae
A
744 continue;
745 i386_signal_cpu(cpu, event, mode);
746 }
747}
748
2d21ac55
A
749/*
750 * Return the number of running cpus.
751 * Called with the topology locked.
752 */
55e303ae
A
753int
754i386_active_cpus(void)
755{
91447636
A
756 unsigned int cpu;
757 unsigned int ncpus = 0;
55e303ae 758
b0d623f7 759 assert(hw_lock_held((hw_lock_t)&x86_topo_lock));
2d21ac55 760
91447636
A
761 for (cpu = 0; cpu < real_ncpus; cpu++) {
762 if (cpu_datap(cpu)->cpu_running)
55e303ae
A
763 ncpus++;
764 }
765 return(ncpus);
766}
767
39236c6e
A
768/*
769 * Helper function called when busy-waiting: panic if too long
770 * a TSC-based time has elapsed since the start of the spin.
771 */
772static void
773mp_spin_timeout_check(uint64_t tsc_start, const char *msg)
774{
775 uint64_t tsc_timeout;
776
777 cpu_pause();
778 if (machine_timeout_suspended())
779 return;
780
781 /*
782 * The timeout is 4 * the spinlock timeout period
783 * unless we have serial console printing (kprintf) enabled
784 * in which case we allow an even greater margin.
785 */
786 tsc_timeout = disable_serial_output ? (uint64_t) LockTimeOutTSC << 2
787 : (uint64_t) LockTimeOutTSC << 4;
788 if (rdtsc64() > tsc_start + tsc_timeout)
789 panic("%s: spin timeout", msg);
790}
791
55e303ae
A
792/*
793 * All-CPU rendezvous:
794 * - CPUs are signalled,
795 * - all execute the setup function (if specified),
796 * - rendezvous (i.e. all cpus reach a barrier),
797 * - all execute the action function (if specified),
798 * - rendezvous again,
799 * - execute the teardown function (if specified), and then
800 * - resume.
801 *
802 * Note that the supplied external functions _must_ be reentrant and aware
803 * that they are running in parallel and in an unknown lock context.
804 */
805
806static void
807mp_rendezvous_action(void)
808{
39236c6e
A
809 boolean_t intrs_enabled;
810 uint64_t tsc_spin_start;
55e303ae
A
811
812 /* setup function */
813 if (mp_rv_setup_func != NULL)
814 mp_rv_setup_func(mp_rv_func_arg);
2d21ac55
A
815
816 intrs_enabled = ml_get_interrupts_enabled();
817
55e303ae 818 /* spin on entry rendezvous */
0c530ab8 819 atomic_incl(&mp_rv_entry, 1);
39236c6e 820 tsc_spin_start = rdtsc64();
0c530ab8 821 while (mp_rv_entry < mp_rv_ncpus) {
2d21ac55
A
822 /* poll for pesky tlb flushes if interrupts disabled */
823 if (!intrs_enabled)
824 handle_pending_TLB_flushes();
39236c6e
A
825 mp_spin_timeout_check(tsc_spin_start,
826 "mp_rendezvous_action() entry");
0c530ab8 827 }
6d2010ae 828
55e303ae
A
829 /* action function */
830 if (mp_rv_action_func != NULL)
831 mp_rv_action_func(mp_rv_func_arg);
6d2010ae 832
55e303ae 833 /* spin on exit rendezvous */
0c530ab8 834 atomic_incl(&mp_rv_exit, 1);
39236c6e 835 tsc_spin_start = rdtsc64();
2d21ac55
A
836 while (mp_rv_exit < mp_rv_ncpus) {
837 if (!intrs_enabled)
838 handle_pending_TLB_flushes();
39236c6e
A
839 mp_spin_timeout_check(tsc_spin_start,
840 "mp_rendezvous_action() exit");
2d21ac55 841 }
6d2010ae 842
55e303ae
A
843 /* teardown function */
844 if (mp_rv_teardown_func != NULL)
845 mp_rv_teardown_func(mp_rv_func_arg);
0c530ab8
A
846
847 /* Bump completion count */
848 atomic_incl(&mp_rv_complete, 1);
55e303ae
A
849}
850
851void
852mp_rendezvous(void (*setup_func)(void *),
853 void (*action_func)(void *),
854 void (*teardown_func)(void *),
855 void *arg)
856{
39236c6e 857 uint64_t tsc_spin_start;
55e303ae
A
858
859 if (!smp_initialized) {
860 if (setup_func != NULL)
861 setup_func(arg);
862 if (action_func != NULL)
863 action_func(arg);
864 if (teardown_func != NULL)
865 teardown_func(arg);
866 return;
867 }
868
869 /* obtain rendezvous lock */
870 simple_lock(&mp_rv_lock);
871
872 /* set static function pointers */
873 mp_rv_setup_func = setup_func;
874 mp_rv_action_func = action_func;
875 mp_rv_teardown_func = teardown_func;
876 mp_rv_func_arg = arg;
877
0c530ab8
A
878 mp_rv_entry = 0;
879 mp_rv_exit = 0;
880 mp_rv_complete = 0;
55e303ae
A
881
882 /*
883 * signal other processors, which will call mp_rendezvous_action()
2d21ac55 884 * with interrupts disabled
55e303ae 885 */
2d21ac55 886 simple_lock(&x86_topo_lock);
0c530ab8 887 mp_rv_ncpus = i386_active_cpus();
55e303ae 888 i386_signal_cpus(MP_RENDEZVOUS, ASYNC);
2d21ac55 889 simple_unlock(&x86_topo_lock);
55e303ae
A
890
891 /* call executor function on this cpu */
892 mp_rendezvous_action();
893
0c530ab8
A
894 /*
895 * Spin for everyone to complete.
896 * This is necessary to ensure that all processors have proceeded
897 * from the exit barrier before we release the rendezvous structure.
898 */
39236c6e 899 tsc_spin_start = rdtsc64();
0c530ab8 900 while (mp_rv_complete < mp_rv_ncpus) {
39236c6e 901 mp_spin_timeout_check(tsc_spin_start, "mp_rendezvous()");
0c530ab8
A
902 }
903
2d21ac55
A
904 /* Tidy up */
905 mp_rv_setup_func = NULL;
906 mp_rv_action_func = NULL;
907 mp_rv_teardown_func = NULL;
908 mp_rv_func_arg = NULL;
909
55e303ae
A
910 /* release lock */
911 simple_unlock(&mp_rv_lock);
912}
913
0c530ab8
A
914void
915mp_rendezvous_break_lock(void)
916{
917 simple_lock_init(&mp_rv_lock, 0);
918}
919
920static void
921setup_disable_intrs(__unused void * param_not_used)
922{
923 /* disable interrupts before the first barrier */
924 boolean_t intr = ml_set_interrupts_enabled(FALSE);
925
926 current_cpu_datap()->cpu_iflag = intr;
927 DBG("CPU%d: %s\n", get_cpu_number(), __FUNCTION__);
928}
929
930static void
931teardown_restore_intrs(__unused void * param_not_used)
932{
933 /* restore interrupt flag following MTRR changes */
934 ml_set_interrupts_enabled(current_cpu_datap()->cpu_iflag);
935 DBG("CPU%d: %s\n", get_cpu_number(), __FUNCTION__);
936}
937
938/*
939 * A wrapper to mp_rendezvous() to call action_func() with interrupts disabled.
940 * This is exported for use by kexts.
941 */
942void
943mp_rendezvous_no_intrs(
944 void (*action_func)(void *),
945 void *arg)
946{
947 mp_rendezvous(setup_disable_intrs,
948 action_func,
949 teardown_restore_intrs,
950 arg);
951}
952
6d2010ae
A
953
954typedef struct {
955 queue_chain_t link; /* queue linkage */
956 void (*func)(void *,void *); /* routine to call */
957 void *arg0; /* routine's 1st arg */
958 void *arg1; /* routine's 2nd arg */
959 volatile long *countp; /* completion counter */
960} mp_call_t;
316670eb
A
961
962
963typedef struct {
964 queue_head_t queue;
965 decl_simple_lock_data(, lock);
966} mp_call_queue_t;
6d2010ae 967#define MP_CPUS_CALL_BUFS_PER_CPU MAX_CPUS
316670eb
A
968static mp_call_queue_t mp_cpus_call_freelist;
969static mp_call_queue_t mp_cpus_call_head[MAX_CPUS];
6d2010ae
A
970
971static inline boolean_t
316670eb 972mp_call_head_lock(mp_call_queue_t *cqp)
6d2010ae
A
973{
974 boolean_t intrs_enabled;
975
976 intrs_enabled = ml_set_interrupts_enabled(FALSE);
316670eb 977 simple_lock(&cqp->lock);
6d2010ae
A
978
979 return intrs_enabled;
980}
981
982static inline boolean_t
316670eb 983mp_call_head_is_locked(mp_call_queue_t *cqp)
6d2010ae
A
984{
985 return !ml_get_interrupts_enabled() &&
316670eb 986 hw_lock_held((hw_lock_t)&cqp->lock);
6d2010ae
A
987}
988
989static inline void
316670eb 990mp_call_head_unlock(mp_call_queue_t *cqp, boolean_t intrs_enabled)
6d2010ae 991{
316670eb 992 simple_unlock(&cqp->lock);
6d2010ae
A
993 ml_set_interrupts_enabled(intrs_enabled);
994}
995
996static inline mp_call_t *
997mp_call_alloc(void)
998{
316670eb
A
999 mp_call_t *callp = NULL;
1000 boolean_t intrs_enabled;
1001 mp_call_queue_t *cqp = &mp_cpus_call_freelist;
1002
1003 intrs_enabled = mp_call_head_lock(cqp);
1004 if (!queue_empty(&cqp->queue))
1005 queue_remove_first(&cqp->queue, callp, typeof(callp), link);
1006 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae 1007
6d2010ae
A
1008 return callp;
1009}
1010
1011static inline void
1012mp_call_free(mp_call_t *callp)
0c530ab8 1013{
316670eb
A
1014 boolean_t intrs_enabled;
1015 mp_call_queue_t *cqp = &mp_cpus_call_freelist;
1016
1017 intrs_enabled = mp_call_head_lock(cqp);
1018 queue_enter_first(&cqp->queue, callp, typeof(callp), link);
1019 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1020}
1021
1022static inline mp_call_t *
316670eb 1023mp_call_dequeue_locked(mp_call_queue_t *cqp)
6d2010ae 1024{
316670eb 1025 mp_call_t *callp = NULL;
0c530ab8 1026
316670eb
A
1027 assert(mp_call_head_is_locked(cqp));
1028 if (!queue_empty(&cqp->queue))
1029 queue_remove_first(&cqp->queue, callp, typeof(callp), link);
6d2010ae
A
1030 return callp;
1031}
1032
316670eb
A
1033static inline void
1034mp_call_enqueue_locked(
1035 mp_call_queue_t *cqp,
1036 mp_call_t *callp)
1037{
1038 queue_enter(&cqp->queue, callp, typeof(callp), link);
1039}
1040
6d2010ae
A
1041/* Called on the boot processor to initialize global structures */
1042static void
1043mp_cpus_call_init(void)
1044{
316670eb
A
1045 mp_call_queue_t *cqp = &mp_cpus_call_freelist;
1046
6d2010ae 1047 DBG("mp_cpus_call_init()\n");
316670eb
A
1048 simple_lock_init(&cqp->lock, 0);
1049 queue_init(&cqp->queue);
6d2010ae
A
1050}
1051
1052/*
1053 * Called by each processor to add call buffers to the free list
1054 * and to initialize the per-cpu call queue.
1055 * Also called but ignored on slave processors on re-start/wake.
1056 */
1057static void
1058mp_cpus_call_cpu_init(void)
1059{
6d2010ae 1060 int i;
316670eb 1061 mp_call_queue_t *cqp = &mp_cpus_call_head[cpu_number()];
6d2010ae
A
1062 mp_call_t *callp;
1063
316670eb 1064 if (cqp->queue.next != NULL)
6d2010ae
A
1065 return; /* restart/wake case: called already */
1066
316670eb
A
1067 simple_lock_init(&cqp->lock, 0);
1068 queue_init(&cqp->queue);
6d2010ae
A
1069 for (i = 0; i < MP_CPUS_CALL_BUFS_PER_CPU; i++) {
1070 callp = (mp_call_t *) kalloc(sizeof(mp_call_t));
6d2010ae 1071 mp_call_free(callp);
0c530ab8 1072 }
6d2010ae
A
1073
1074 DBG("mp_cpus_call_init() done on cpu %d\n", cpu_number());
0c530ab8
A
1075}
1076
2d21ac55
A
1077/*
1078 * This is called from cpu_signal_handler() to process an MP_CALL signal.
6d2010ae 1079 * And also from i386_deactivate_cpu() when a cpu is being taken offline.
2d21ac55
A
1080 */
1081static void
1082mp_cpus_call_action(void)
1083{
316670eb 1084 mp_call_queue_t *cqp;
6d2010ae
A
1085 boolean_t intrs_enabled;
1086 mp_call_t *callp;
1087 mp_call_t call;
1088
1089 assert(!ml_get_interrupts_enabled());
316670eb
A
1090 cqp = &mp_cpus_call_head[cpu_number()];
1091 intrs_enabled = mp_call_head_lock(cqp);
1092 while ((callp = mp_call_dequeue_locked(cqp)) != NULL) {
6d2010ae
A
1093 /* Copy call request to the stack to free buffer */
1094 call = *callp;
1095 mp_call_free(callp);
1096 if (call.func != NULL) {
316670eb 1097 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1098 KERNEL_DEBUG_CONSTANT(
1099 TRACE_MP_CPUS_CALL_ACTION,
1100 call.func, call.arg0, call.arg1, call.countp, 0);
1101 call.func(call.arg0, call.arg1);
316670eb 1102 (void) mp_call_head_lock(cqp);
6d2010ae
A
1103 }
1104 if (call.countp != NULL)
1105 atomic_incl(call.countp, 1);
1106 }
316670eb 1107 mp_call_head_unlock(cqp, intrs_enabled);
2d21ac55
A
1108}
1109
1110/*
1111 * mp_cpus_call() runs a given function on cpus specified in a given cpu mask.
6d2010ae
A
1112 * Possible modes are:
1113 * SYNC: function is called serially on target cpus in logical cpu order
1114 * waiting for each call to be acknowledged before proceeding
1115 * ASYNC: function call is queued to the specified cpus
1116 * waiting for all calls to complete in parallel before returning
1117 * NOSYNC: function calls are queued
1118 * but we return before confirmation of calls completing.
2d21ac55
A
1119 * The action function may be NULL.
1120 * The cpu mask may include the local cpu. Offline cpus are ignored.
6d2010ae 1121 * The return value is the number of cpus on which the call was made or queued.
2d21ac55
A
1122 */
1123cpu_t
1124mp_cpus_call(
1125 cpumask_t cpus,
1126 mp_sync_t mode,
1127 void (*action_func)(void *),
1128 void *arg)
6d2010ae
A
1129{
1130 return mp_cpus_call1(
1131 cpus,
1132 mode,
1133 (void (*)(void *,void *))action_func,
1134 arg,
1135 NULL,
1136 NULL,
1137 NULL);
1138}
1139
1140static void
316670eb
A
1141mp_cpus_call_wait(boolean_t intrs_enabled,
1142 long mp_cpus_signals,
1143 volatile long *mp_cpus_calls)
6d2010ae 1144{
316670eb 1145 mp_call_queue_t *cqp;
39236c6e 1146 uint64_t tsc_spin_start;
6d2010ae 1147
316670eb 1148 cqp = &mp_cpus_call_head[cpu_number()];
6d2010ae 1149
39236c6e 1150 tsc_spin_start = rdtsc64();
6d2010ae
A
1151 while (*mp_cpus_calls < mp_cpus_signals) {
1152 if (!intrs_enabled) {
316670eb
A
1153 /* Sniffing w/o locking */
1154 if (!queue_empty(&cqp->queue))
6d2010ae 1155 mp_cpus_call_action();
6d2010ae
A
1156 handle_pending_TLB_flushes();
1157 }
39236c6e 1158 mp_spin_timeout_check(tsc_spin_start, "mp_cpus_call_wait()");
6d2010ae
A
1159 }
1160}
1161
1162cpu_t
1163mp_cpus_call1(
1164 cpumask_t cpus,
1165 mp_sync_t mode,
1166 void (*action_func)(void *, void *),
1167 void *arg0,
1168 void *arg1,
1169 cpumask_t *cpus_calledp,
1170 cpumask_t *cpus_notcalledp)
2d21ac55
A
1171{
1172 cpu_t cpu;
6d2010ae 1173 boolean_t intrs_enabled = FALSE;
2d21ac55 1174 boolean_t call_self = FALSE;
6d2010ae
A
1175 cpumask_t cpus_called = 0;
1176 cpumask_t cpus_notcalled = 0;
1177 long mp_cpus_signals = 0;
1178 volatile long mp_cpus_calls = 0;
39236c6e 1179 uint64_t tsc_spin_start;
6d2010ae
A
1180
1181 KERNEL_DEBUG_CONSTANT(
1182 TRACE_MP_CPUS_CALL | DBG_FUNC_START,
316670eb 1183 cpus, mode, VM_KERNEL_UNSLIDE(action_func), arg0, arg1);
2d21ac55
A
1184
1185 if (!smp_initialized) {
1186 if ((cpus & CPUMASK_SELF) == 0)
6d2010ae 1187 goto out;
2d21ac55 1188 if (action_func != NULL) {
6d2010ae
A
1189 intrs_enabled = ml_set_interrupts_enabled(FALSE);
1190 action_func(arg0, arg1);
2d21ac55
A
1191 ml_set_interrupts_enabled(intrs_enabled);
1192 }
6d2010ae
A
1193 call_self = TRUE;
1194 goto out;
2d21ac55 1195 }
2d21ac55 1196
6d2010ae
A
1197 /*
1198 * Queue the call for each non-local requested cpu.
1199 * The topo lock is not taken. Instead we sniff the cpu_running state
1200 * and then re-check it after taking the call lock. A cpu being taken
1201 * offline runs the action function after clearing the cpu_running.
1202 */
39236c6e
A
1203 mp_disable_preemption(); /* interrupts may be enabled */
1204 tsc_spin_start = rdtsc64();
2d21ac55
A
1205 for (cpu = 0; cpu < (cpu_t) real_ncpus; cpu++) {
1206 if (((cpu_to_cpumask(cpu) & cpus) == 0) ||
1207 !cpu_datap(cpu)->cpu_running)
1208 continue;
1209 if (cpu == (cpu_t) cpu_number()) {
1210 /*
1211 * We don't IPI ourself and if calling asynchronously,
1212 * we defer our call until we have signalled all others.
1213 */
1214 call_self = TRUE;
6d2010ae 1215 cpus_called |= cpu_to_cpumask(cpu);
2d21ac55 1216 if (mode == SYNC && action_func != NULL) {
6d2010ae
A
1217 KERNEL_DEBUG_CONSTANT(
1218 TRACE_MP_CPUS_CALL_LOCAL,
316670eb
A
1219 VM_KERNEL_UNSLIDE(action_func),
1220 arg0, arg1, 0, 0);
6d2010ae 1221 action_func(arg0, arg1);
2d21ac55
A
1222 }
1223 } else {
1224 /*
6d2010ae
A
1225 * Here to queue a call to cpu and IPI.
1226 * Spinning for request buffer unless NOSYNC.
2d21ac55 1227 */
316670eb
A
1228 mp_call_t *callp = NULL;
1229 mp_call_queue_t *cqp = &mp_cpus_call_head[cpu];
1230
6d2010ae 1231 queue_call:
316670eb
A
1232 if (callp == NULL)
1233 callp = mp_call_alloc();
1234 intrs_enabled = mp_call_head_lock(cqp);
6d2010ae 1235 if (!cpu_datap(cpu)->cpu_running) {
316670eb 1236 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1237 continue;
1238 }
1239 if (mode == NOSYNC) {
316670eb 1240 if (callp == NULL) {
6d2010ae 1241 cpus_notcalled |= cpu_to_cpumask(cpu);
316670eb 1242 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1243 KERNEL_DEBUG_CONSTANT(
1244 TRACE_MP_CPUS_CALL_NOBUF,
1245 cpu, 0, 0, 0, 0);
1246 continue;
1247 }
316670eb 1248 callp->countp = NULL;
6d2010ae 1249 } else {
316670eb
A
1250 if (callp == NULL) {
1251 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1252 KERNEL_DEBUG_CONSTANT(
1253 TRACE_MP_CPUS_CALL_NOBUF,
1254 cpu, 0, 0, 0, 0);
1255 if (!intrs_enabled) {
316670eb
A
1256 /* Sniffing w/o locking */
1257 if (!queue_empty(&cqp->queue))
1258 mp_cpus_call_action();
2d21ac55 1259 handle_pending_TLB_flushes();
6d2010ae 1260 }
39236c6e
A
1261 mp_spin_timeout_check(
1262 tsc_spin_start,
1263 "mp_cpus_call1()");
6d2010ae 1264 goto queue_call;
2d21ac55 1265 }
316670eb 1266 callp->countp = &mp_cpus_calls;
6d2010ae 1267 }
316670eb
A
1268 callp->func = action_func;
1269 callp->arg0 = arg0;
1270 callp->arg1 = arg1;
1271 mp_call_enqueue_locked(cqp, callp);
6d2010ae
A
1272 mp_cpus_signals++;
1273 cpus_called |= cpu_to_cpumask(cpu);
1274 i386_signal_cpu(cpu, MP_CALL, ASYNC);
316670eb 1275 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1276 if (mode == SYNC) {
1277 mp_cpus_call_wait(intrs_enabled, mp_cpus_signals, &mp_cpus_calls);
2d21ac55
A
1278 }
1279 }
1280 }
2d21ac55 1281
6d2010ae
A
1282 /* Call locally if mode not SYNC */
1283 if (mode != SYNC && call_self ) {
1284 KERNEL_DEBUG_CONSTANT(
1285 TRACE_MP_CPUS_CALL_LOCAL,
316670eb 1286 VM_KERNEL_UNSLIDE(action_func), arg0, arg1, 0, 0);
6d2010ae
A
1287 if (action_func != NULL) {
1288 ml_set_interrupts_enabled(FALSE);
1289 action_func(arg0, arg1);
2d21ac55
A
1290 ml_set_interrupts_enabled(intrs_enabled);
1291 }
2d21ac55 1292 }
2d21ac55 1293
39236c6e
A
1294 /* Safe to allow pre-emption now */
1295 mp_enable_preemption();
1296
6d2010ae
A
1297 /* For ASYNC, now wait for all signaled cpus to complete their calls */
1298 if (mode == ASYNC) {
1299 mp_cpus_call_wait(intrs_enabled, mp_cpus_signals, &mp_cpus_calls);
1300 }
1301
1302out:
1303 cpu = (cpu_t) mp_cpus_signals + (call_self ? 1 : 0);
1304
1305 if (cpus_calledp)
1306 *cpus_calledp = cpus_called;
1307 if (cpus_notcalledp)
1308 *cpus_notcalledp = cpus_notcalled;
1309
1310 KERNEL_DEBUG_CONSTANT(
1311 TRACE_MP_CPUS_CALL | DBG_FUNC_END,
1312 cpu, cpus_called, cpus_notcalled, 0, 0);
2d21ac55
A
1313
1314 return cpu;
1315}
1316
6d2010ae 1317
2d21ac55
A
1318static void
1319mp_broadcast_action(void)
1320{
1321 /* call action function */
1322 if (mp_bc_action_func != NULL)
1323 mp_bc_action_func(mp_bc_func_arg);
1324
1325 /* if we're the last one through, wake up the instigator */
b0d623f7
A
1326 if (atomic_decl_and_test(&mp_bc_count, 1))
1327 thread_wakeup(((event_t)(uintptr_t) &mp_bc_count));
2d21ac55
A
1328}
1329
1330/*
1331 * mp_broadcast() runs a given function on all active cpus.
1332 * The caller blocks until the functions has run on all cpus.
1333 * The caller will also block if there is another pending braodcast.
1334 */
1335void
1336mp_broadcast(
1337 void (*action_func)(void *),
1338 void *arg)
1339{
1340 if (!smp_initialized) {
1341 if (action_func != NULL)
1342 action_func(arg);
1343 return;
1344 }
1345
1346 /* obtain broadcast lock */
b0d623f7 1347 lck_mtx_lock(&mp_bc_lock);
2d21ac55
A
1348
1349 /* set static function pointers */
1350 mp_bc_action_func = action_func;
1351 mp_bc_func_arg = arg;
1352
b0d623f7 1353 assert_wait((event_t)(uintptr_t)&mp_bc_count, THREAD_UNINT);
2d21ac55
A
1354
1355 /*
1356 * signal other processors, which will call mp_broadcast_action()
1357 */
1358 simple_lock(&x86_topo_lock);
1359 mp_bc_ncpus = i386_active_cpus(); /* total including this cpu */
1360 mp_bc_count = mp_bc_ncpus;
1361 i386_signal_cpus(MP_BROADCAST, ASYNC);
1362
1363 /* call executor function on this cpu */
1364 mp_broadcast_action();
1365 simple_unlock(&x86_topo_lock);
1366
1367 /* block for all cpus to have run action_func */
1368 if (mp_bc_ncpus > 1)
1369 thread_block(THREAD_CONTINUE_NULL);
1370 else
1371 clear_wait(current_thread(), THREAD_AWAKENED);
1372
1373 /* release lock */
b0d623f7 1374 lck_mtx_unlock(&mp_bc_lock);
2d21ac55
A
1375}
1376
1377void
1378i386_activate_cpu(void)
1379{
1380 cpu_data_t *cdp = current_cpu_datap();
1381
1382 assert(!ml_get_interrupts_enabled());
1383
1384 if (!smp_initialized) {
1385 cdp->cpu_running = TRUE;
1386 return;
1387 }
1388
1389 simple_lock(&x86_topo_lock);
1390 cdp->cpu_running = TRUE;
7e4a7d39 1391 started_cpu();
2d21ac55 1392 simple_unlock(&x86_topo_lock);
7ddcb079 1393 flush_tlb_raw();
2d21ac55
A
1394}
1395
1396void
1397i386_deactivate_cpu(void)
1398{
1399 cpu_data_t *cdp = current_cpu_datap();
1400
1401 assert(!ml_get_interrupts_enabled());
bd504ef0
A
1402
1403 KERNEL_DEBUG_CONSTANT(
1404 TRACE_MP_CPU_DEACTIVATE | DBG_FUNC_START,
1405 0, 0, 0, 0, 0);
2d21ac55
A
1406
1407 simple_lock(&x86_topo_lock);
1408 cdp->cpu_running = FALSE;
1409 simple_unlock(&x86_topo_lock);
1410
bd504ef0
A
1411 /*
1412 * Move all of this cpu's timers to the master/boot cpu,
1413 * and poke it in case there's a sooner deadline for it to schedule.
1414 */
c910b4d9 1415 timer_queue_shutdown(&cdp->rtclock_timer.queue);
39236c6e 1416 mp_cpus_call(cpu_to_cpumask(master_cpu), ASYNC, timer_queue_expire_local, NULL);
c910b4d9 1417
2d21ac55 1418 /*
bd504ef0
A
1419 * Open an interrupt window
1420 * and ensure any pending IPI or timer is serviced
2d21ac55 1421 */
bd504ef0
A
1422 mp_disable_preemption();
1423 ml_set_interrupts_enabled(TRUE);
1424
1425 while (cdp->cpu_signals && x86_lcpu()->rtcDeadline != EndOfAllTime)
1426 cpu_pause();
1427 /*
1428 * Ensure there's no remaining timer deadline set
1429 * - AICPM may have left one active.
1430 */
1431 setPop(0);
1432
1433 ml_set_interrupts_enabled(FALSE);
1434 mp_enable_preemption();
1435
1436 KERNEL_DEBUG_CONSTANT(
1437 TRACE_MP_CPU_DEACTIVATE | DBG_FUNC_END,
1438 0, 0, 0, 0, 0);
2d21ac55
A
1439}
1440
1441int pmsafe_debug = 1;
1442
55e303ae
A
1443#if MACH_KDP
1444volatile boolean_t mp_kdp_trap = FALSE;
593a1d5f 1445volatile unsigned long mp_kdp_ncpus;
91447636
A
1446boolean_t mp_kdp_state;
1447
55e303ae
A
1448
1449void
1450mp_kdp_enter(void)
1451{
91447636 1452 unsigned int cpu;
6d2010ae 1453 unsigned int ncpus = 0;
593a1d5f 1454 unsigned int my_cpu;
91447636 1455 uint64_t tsc_timeout;
55e303ae
A
1456
1457 DBG("mp_kdp_enter()\n");
1458
39236c6e
A
1459#if DEBUG
1460 if (!smp_initialized)
1461 simple_lock_init(&mp_kdp_lock, 0);
1462#endif
1463
55e303ae
A
1464 /*
1465 * Here to enter the debugger.
1466 * In case of races, only one cpu is allowed to enter kdp after
1467 * stopping others.
1468 */
91447636 1469 mp_kdp_state = ml_set_interrupts_enabled(FALSE);
060df5ea 1470 my_cpu = cpu_number();
7ddcb079
A
1471
1472 if (my_cpu == (unsigned) debugger_cpu) {
1473 kprintf("\n\nRECURSIVE DEBUGGER ENTRY DETECTED\n\n");
1474 kdp_reset();
1475 return;
1476 }
1477
060df5ea 1478 cpu_datap(my_cpu)->debugger_entry_time = mach_absolute_time();
55e303ae 1479 simple_lock(&mp_kdp_lock);
060df5ea 1480
d41d1dae 1481 if (pmsafe_debug && !kdp_snapshot)
2d21ac55
A
1482 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
1483
55e303ae
A
1484 while (mp_kdp_trap) {
1485 simple_unlock(&mp_kdp_lock);
1486 DBG("mp_kdp_enter() race lost\n");
b0d623f7
A
1487#if MACH_KDP
1488 mp_kdp_wait(TRUE, FALSE);
1489#endif
55e303ae
A
1490 simple_lock(&mp_kdp_lock);
1491 }
593a1d5f 1492 debugger_cpu = my_cpu;
060df5ea 1493 ncpus = 1;
55e303ae
A
1494 mp_kdp_ncpus = 1; /* self */
1495 mp_kdp_trap = TRUE;
060df5ea 1496 debugger_entry_time = cpu_datap(my_cpu)->debugger_entry_time;
55e303ae 1497 simple_unlock(&mp_kdp_lock);
55e303ae 1498
0c530ab8
A
1499 /*
1500 * Deliver a nudge to other cpus, counting how many
1501 */
55e303ae 1502 DBG("mp_kdp_enter() signaling other processors\n");
2d21ac55 1503 if (force_immediate_debugger_NMI == FALSE) {
060df5ea 1504 for (cpu = 0; cpu < real_ncpus; cpu++) {
2d21ac55
A
1505 if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running)
1506 continue;
1507 ncpus++;
1508 i386_signal_cpu(cpu, MP_KDP, ASYNC);
1509 }
1510 /*
1511 * Wait other processors to synchronize
1512 */
1513 DBG("mp_kdp_enter() waiting for (%d) processors to suspend\n", ncpus);
0c530ab8 1514
2d21ac55
A
1515 /*
1516 * This timeout is rather arbitrary; we don't want to NMI
1517 * processors that are executing at potentially
1518 * "unsafe-to-interrupt" points such as the trampolines,
1519 * but neither do we want to lose state by waiting too long.
1520 */
316670eb
A
1521 tsc_timeout = rdtsc64() + (ncpus * 1000 * 1000 * 10ULL);
1522
1523 if (virtualized)
1524 tsc_timeout = ~0ULL;
0c530ab8 1525
2d21ac55
A
1526 while (mp_kdp_ncpus != ncpus && rdtsc64() < tsc_timeout) {
1527 /*
1528 * A TLB shootdown request may be pending--this would
1529 * result in the requesting processor waiting in
1530 * PMAP_UPDATE_TLBS() until this processor deals with it.
1531 * Process it, so it can now enter mp_kdp_wait()
1532 */
1533 handle_pending_TLB_flushes();
1534 cpu_pause();
1535 }
1536 /* If we've timed out, and some processor(s) are still unresponsive,
1537 * interrupt them with an NMI via the local APIC.
0c530ab8 1538 */
2d21ac55
A
1539 if (mp_kdp_ncpus != ncpus) {
1540 for (cpu = 0; cpu < real_ncpus; cpu++) {
1541 if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running)
1542 continue;
1543 if (cpu_signal_pending(cpu, MP_KDP))
1544 cpu_NMI_interrupt(cpu);
1545 }
1546 }
55e303ae 1547 }
2d21ac55 1548 else
0c530ab8
A
1549 for (cpu = 0; cpu < real_ncpus; cpu++) {
1550 if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running)
1551 continue;
2d21ac55 1552 cpu_NMI_interrupt(cpu);
0c530ab8 1553 }
0c530ab8 1554
bd504ef0 1555 DBG("mp_kdp_enter() %d processors done %s\n",
6d2010ae 1556 (int)mp_kdp_ncpus, (mp_kdp_ncpus == ncpus) ? "OK" : "timed out");
0c530ab8 1557
91447636 1558 postcode(MP_KDP_ENTER);
55e303ae
A
1559}
1560
0c530ab8
A
1561static boolean_t
1562cpu_signal_pending(int cpu, mp_event_t event)
1563{
1564 volatile int *signals = &cpu_datap(cpu)->cpu_signals;
1565 boolean_t retval = FALSE;
1566
1567 if (i_bit(event, signals))
1568 retval = TRUE;
1569 return retval;
1570}
b0d623f7
A
1571
1572long kdp_x86_xcpu_invoke(const uint16_t lcpu, kdp_x86_xcpu_func_t func,
1573 void *arg0, void *arg1)
1574{
1575 if (lcpu > (real_ncpus - 1))
1576 return -1;
1577
1578 if (func == NULL)
1579 return -1;
1580
1581 kdp_xcpu_call_func.func = func;
1582 kdp_xcpu_call_func.ret = -1;
1583 kdp_xcpu_call_func.arg0 = arg0;
1584 kdp_xcpu_call_func.arg1 = arg1;
1585 kdp_xcpu_call_func.cpu = lcpu;
1586 DBG("Invoking function %p on CPU %d\n", func, (int32_t)lcpu);
1587 while (kdp_xcpu_call_func.cpu != KDP_XCPU_NONE)
1588 cpu_pause();
1589 return kdp_xcpu_call_func.ret;
1590}
1591
1592static void
1593kdp_x86_xcpu_poll(void)
1594{
1595 if ((uint16_t)cpu_number() == kdp_xcpu_call_func.cpu) {
1596 kdp_xcpu_call_func.ret =
1597 kdp_xcpu_call_func.func(kdp_xcpu_call_func.arg0,
1598 kdp_xcpu_call_func.arg1,
1599 cpu_number());
1600 kdp_xcpu_call_func.cpu = KDP_XCPU_NONE;
1601 }
1602}
0c530ab8 1603
55e303ae 1604static void
b0d623f7 1605mp_kdp_wait(boolean_t flush, boolean_t isNMI)
55e303ae 1606{
6601e61a 1607 DBG("mp_kdp_wait()\n");
2d21ac55 1608 /* If an I/O port has been specified as a debugging aid, issue a read */
0c530ab8 1609 panic_io_port_read();
bd504ef0 1610 current_cpu_datap()->debugger_ipi_time = mach_absolute_time();
b0d623f7 1611#if CONFIG_MCA
2d21ac55
A
1612 /* If we've trapped due to a machine-check, save MCA registers */
1613 mca_check_save();
b0d623f7 1614#endif
2d21ac55 1615
2d21ac55 1616 atomic_incl((volatile long *)&mp_kdp_ncpus, 1);
b0d623f7 1617 while (mp_kdp_trap || (isNMI == TRUE)) {
0c530ab8 1618 /*
2d21ac55
A
1619 * A TLB shootdown request may be pending--this would result
1620 * in the requesting processor waiting in PMAP_UPDATE_TLBS()
1621 * until this processor handles it.
0c530ab8
A
1622 * Process it, so it can now enter mp_kdp_wait()
1623 */
2d21ac55
A
1624 if (flush)
1625 handle_pending_TLB_flushes();
b0d623f7
A
1626
1627 kdp_x86_xcpu_poll();
55e303ae
A
1628 cpu_pause();
1629 }
2d21ac55 1630
0c530ab8 1631 atomic_decl((volatile long *)&mp_kdp_ncpus, 1);
55e303ae
A
1632 DBG("mp_kdp_wait() done\n");
1633}
1634
1635void
1636mp_kdp_exit(void)
1637{
1638 DBG("mp_kdp_exit()\n");
593a1d5f 1639 debugger_cpu = -1;
0c530ab8 1640 atomic_decl((volatile long *)&mp_kdp_ncpus, 1);
b0d623f7
A
1641
1642 debugger_exit_time = mach_absolute_time();
1643
55e303ae 1644 mp_kdp_trap = FALSE;
39236c6e 1645 mfence();
55e303ae
A
1646
1647 /* Wait other processors to stop spinning. XXX needs timeout */
1648 DBG("mp_kdp_exit() waiting for processors to resume\n");
0c530ab8
A
1649 while (mp_kdp_ncpus > 0) {
1650 /*
1651 * a TLB shootdown request may be pending... this would result in the requesting
1652 * processor waiting in PMAP_UPDATE_TLBS() until this processor deals with it.
1653 * Process it, so it can now enter mp_kdp_wait()
1654 */
1655 handle_pending_TLB_flushes();
1656
55e303ae
A
1657 cpu_pause();
1658 }
2d21ac55 1659
d41d1dae 1660 if (pmsafe_debug && !kdp_snapshot)
2d21ac55
A
1661 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL);
1662
6d2010ae
A
1663 debugger_exit_time = mach_absolute_time();
1664
55e303ae 1665 DBG("mp_kdp_exit() done\n");
91447636
A
1666 (void) ml_set_interrupts_enabled(mp_kdp_state);
1667 postcode(0);
55e303ae
A
1668}
1669#endif /* MACH_KDP */
1670
b0d623f7
A
1671boolean_t
1672mp_recent_debugger_activity() {
060df5ea
A
1673 uint64_t abstime = mach_absolute_time();
1674 return (((abstime - debugger_entry_time) < LastDebuggerEntryAllowance) ||
1675 ((abstime - debugger_exit_time) < LastDebuggerEntryAllowance));
b0d623f7
A
1676}
1677
55e303ae
A
1678/*ARGSUSED*/
1679void
1680init_ast_check(
91447636 1681 __unused processor_t processor)
55e303ae
A
1682{
1683}
1684
1685void
1686cause_ast_check(
1687 processor_t processor)
1688{
b0d623f7 1689 int cpu = processor->cpu_id;
55e303ae
A
1690
1691 if (cpu != cpu_number()) {
1692 i386_signal_cpu(cpu, MP_AST, ASYNC);
6d2010ae 1693 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_REMOTE_AST), cpu, 1, 0, 0, 0);
55e303ae
A
1694 }
1695}
1696
593a1d5f
A
1697void
1698slave_machine_init(void *param)
91447636
A
1699{
1700 /*
0c530ab8 1701 * Here in process context, but with interrupts disabled.
91447636
A
1702 */
1703 DBG("slave_machine_init() CPU%d\n", get_cpu_number());
1704
593a1d5f
A
1705 if (param == FULL_SLAVE_INIT) {
1706 /*
1707 * Cold start
1708 */
1709 clock_init();
593a1d5f 1710 cpu_machine_init(); /* Interrupts enabled hereafter */
6d2010ae 1711 mp_cpus_call_cpu_init();
bd504ef0
A
1712 } else {
1713 cpu_machine_init(); /* Interrupts enabled hereafter */
593a1d5f 1714 }
55e303ae
A
1715}
1716
b0d623f7 1717#undef cpu_number
55e303ae
A
1718int cpu_number(void)
1719{
1720 return get_cpu_number();
1721}
1722
6d2010ae
A
1723static void
1724cpu_prewarm_init()
1725{
1726 int i;
1727
1728 simple_lock_init(&cpu_warm_lock, 0);
1729 queue_init(&cpu_warm_call_list);
1730 for (i = 0; i < NUM_CPU_WARM_CALLS; i++) {
1731 enqueue_head(&cpu_warm_call_list, (queue_entry_t)&cpu_warm_call_arr[i]);
1732 }
1733}
1734
1735static timer_call_t
1736grab_warm_timer_call()
1737{
1738 spl_t x;
1739 timer_call_t call = NULL;
1740
1741 x = splsched();
1742 simple_lock(&cpu_warm_lock);
1743 if (!queue_empty(&cpu_warm_call_list)) {
1744 call = (timer_call_t) dequeue_head(&cpu_warm_call_list);
1745 }
1746 simple_unlock(&cpu_warm_lock);
1747 splx(x);
1748
1749 return call;
1750}
1751
1752static void
1753free_warm_timer_call(timer_call_t call)
1754{
1755 spl_t x;
1756
1757 x = splsched();
1758 simple_lock(&cpu_warm_lock);
1759 enqueue_head(&cpu_warm_call_list, (queue_entry_t)call);
1760 simple_unlock(&cpu_warm_lock);
1761 splx(x);
1762}
1763
1764/*
1765 * Runs in timer call context (interrupts disabled).
1766 */
1767static void
1768cpu_warm_timer_call_func(
1769 call_entry_param_t p0,
1770 __unused call_entry_param_t p1)
1771{
1772 free_warm_timer_call((timer_call_t)p0);
1773 return;
1774}
1775
1776/*
1777 * Runs with interrupts disabled on the CPU we wish to warm (i.e. CPU 0).
1778 */
1779static void
1780_cpu_warm_setup(
1781 void *arg)
1782{
1783 cpu_warm_data_t cwdp = (cpu_warm_data_t)arg;
1784
39236c6e 1785 timer_call_enter(cwdp->cwd_call, cwdp->cwd_deadline, TIMER_CALL_SYS_CRITICAL | TIMER_CALL_LOCAL);
6d2010ae
A
1786 cwdp->cwd_result = 0;
1787
1788 return;
1789}
1790
1791/*
1792 * Not safe to call with interrupts disabled.
1793 */
1794kern_return_t
1795ml_interrupt_prewarm(
1796 uint64_t deadline)
1797{
1798 struct cpu_warm_data cwd;
1799 timer_call_t call;
1800 cpu_t ct;
1801
1802 if (ml_get_interrupts_enabled() == FALSE) {
1803 panic("%s: Interrupts disabled?\n", __FUNCTION__);
1804 }
1805
1806 /*
1807 * If the platform doesn't need our help, say that we succeeded.
1808 */
1809 if (!ml_get_interrupt_prewake_applicable()) {
1810 return KERN_SUCCESS;
1811 }
1812
1813 /*
1814 * Grab a timer call to use.
1815 */
1816 call = grab_warm_timer_call();
1817 if (call == NULL) {
1818 return KERN_RESOURCE_SHORTAGE;
1819 }
1820
1821 timer_call_setup(call, cpu_warm_timer_call_func, call);
1822 cwd.cwd_call = call;
1823 cwd.cwd_deadline = deadline;
1824 cwd.cwd_result = 0;
1825
1826 /*
1827 * For now, non-local interrupts happen on the master processor.
1828 */
1829 ct = mp_cpus_call(cpu_to_cpumask(master_cpu), SYNC, _cpu_warm_setup, &cwd);
1830 if (ct == 0) {
1831 free_warm_timer_call(call);
1832 return KERN_FAILURE;
1833 } else {
1834 return cwd.cwd_result;
1835 }
1836}