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