]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/mp.c
xnu-4903.270.47.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@
0a7de745 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.
0a7de745 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.
0a7de745 17 *
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
55e303ae
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
55e303ae 32#include <mach_kdp.h>
39037602 33#include <kdp/kdp_internal.h>
55e303ae 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>
0a7de745 47#include <kern/lock_group.h>
91447636 48#include <kern/machine.h>
0c530ab8 49#include <kern/pms.h>
593a1d5f 50#include <kern/misc_protos.h>
39236c6e 51#include <kern/timer_call.h>
6d2010ae
A
52#include <kern/kalloc.h>
53#include <kern/queue.h>
fe8ab488 54#include <prng/random.h>
91447636
A
55
56#include <vm/vm_map.h>
57#include <vm/vm_kern.h>
58
59#include <profiling/profile-mk.h>
55e303ae 60
fe8ab488 61#include <i386/bit_routines.h>
b0d623f7
A
62#include <i386/proc_reg.h>
63#include <i386/cpu_threads.h>
64#include <i386/mp_desc.h>
65#include <i386/misc_protos.h>
66#include <i386/trap.h>
67#include <i386/postcode.h>
68#include <i386/machine_routines.h>
55e303ae
A
69#include <i386/mp.h>
70#include <i386/mp_events.h>
593a1d5f 71#include <i386/lapic.h>
55e303ae 72#include <i386/cpuid.h>
b0d623f7 73#include <i386/fpu.h>
55e303ae 74#include <i386/machine_cpu.h>
0c530ab8 75#include <i386/pmCPU.h>
b0d623f7 76#if CONFIG_MCA
2d21ac55 77#include <i386/machine_check.h>
b0d623f7
A
78#endif
79#include <i386/acpi.h>
0c530ab8 80
0c530ab8 81#include <sys/kdebug.h>
55e303ae 82
39236c6e
A
83#include <console/serial_protos.h>
84
5ba3f43e
A
85#if MONOTONIC
86#include <kern/monotonic.h>
87#endif /* MONOTONIC */
88
0a7de745
A
89#if MP_DEBUG
90#define PAUSE delay(1000000)
91#define DBG(x...) kprintf(x)
55e303ae
A
92#else
93#define DBG(x...)
94#define PAUSE
0a7de745 95#endif /* MP_DEBUG */
55e303ae 96
6d2010ae 97/* Debugging/test trace events: */
0a7de745
A
98#define TRACE_MP_TLB_FLUSH MACHDBG_CODE(DBG_MACH_MP, 0)
99#define TRACE_MP_CPUS_CALL MACHDBG_CODE(DBG_MACH_MP, 1)
100#define TRACE_MP_CPUS_CALL_LOCAL MACHDBG_CODE(DBG_MACH_MP, 2)
101#define TRACE_MP_CPUS_CALL_ACTION MACHDBG_CODE(DBG_MACH_MP, 3)
102#define TRACE_MP_CPUS_CALL_NOBUF MACHDBG_CODE(DBG_MACH_MP, 4)
103#define TRACE_MP_CPU_FAST_START MACHDBG_CODE(DBG_MACH_MP, 5)
104#define TRACE_MP_CPU_START MACHDBG_CODE(DBG_MACH_MP, 6)
105#define TRACE_MP_CPU_DEACTIVATE MACHDBG_CODE(DBG_MACH_MP, 7)
55e303ae 106
0a7de745 107#define ABS(v) (((v) > 0)?(v):-(v))
7e4a7d39 108
0a7de745
A
109void slave_boot_init(void);
110void i386_cpu_IPI(int cpu);
55e303ae 111
39236c6e 112#if MACH_KDP
0a7de745 113static void mp_kdp_wait(boolean_t flush, boolean_t isNMI);
39236c6e 114#endif /* MACH_KDP */
55e303ae 115
39236c6e 116#if MACH_KDP
0a7de745 117static boolean_t cpu_signal_pending(int cpu, mp_event_t event);
39236c6e 118#endif /* MACH_KDP */
0a7de745 119static int NMIInterruptHandler(x86_saved_state_t *regs);
0c530ab8 120
0a7de745
A
121boolean_t smp_initialized = FALSE;
122uint32_t TSC_sync_margin = 0xFFF;
123volatile boolean_t force_immediate_debugger_NMI = FALSE;
124volatile boolean_t pmap_tlb_flush_timeout = FALSE;
5ba3f43e 125#if DEBUG || DEVELOPMENT
0a7de745
A
126boolean_t mp_interrupt_watchdog_enabled = TRUE;
127uint32_t mp_interrupt_watchdog_events = 0;
5ba3f43e 128#endif
91447636 129
0a7de745 130decl_simple_lock_data(, debugger_callback_lock);
39037602
A
131struct debugger_callback *debugger_callback = NULL;
132
b0d623f7 133decl_lck_mtx_data(static, mp_cpu_boot_lock);
0a7de745 134lck_mtx_ext_t mp_cpu_boot_lock_ext;
55e303ae
A
135
136/* Variables needed for MP rendezvous. */
0a7de745
A
137decl_simple_lock_data(, mp_rv_lock);
138static void (*mp_rv_setup_func)(void *arg);
139static void (*mp_rv_action_func)(void *arg);
140static void (*mp_rv_teardown_func)(void *arg);
141static void *mp_rv_func_arg;
142static volatile int mp_rv_ncpus;
143/* Cache-aligned barriers: */
144static volatile long mp_rv_entry __attribute__((aligned(64)));
145static volatile long mp_rv_exit __attribute__((aligned(64)));
146static volatile long mp_rv_complete __attribute__((aligned(64)));
147
148volatile uint64_t debugger_entry_time;
149volatile uint64_t debugger_exit_time;
b0d623f7 150#if MACH_KDP
7ddcb079 151#include <kdp/kdp.h>
d41d1dae 152extern int kdp_snapshot;
b0d623f7
A
153static struct _kdp_xcpu_call_func {
154 kdp_x86_xcpu_func_t func;
155 void *arg0, *arg1;
156 volatile long ret;
157 volatile uint16_t cpu;
158} kdp_xcpu_call_func = {
159 .cpu = KDP_XCPU_NONE
160};
161
162#endif
163
2d21ac55
A
164/* Variables needed for MP broadcast. */
165static void (*mp_bc_action_func)(void *arg);
166static void *mp_bc_func_arg;
0a7de745 167static int mp_bc_ncpus;
2d21ac55 168static volatile long mp_bc_count;
b0d623f7 169decl_lck_mtx_data(static, mp_bc_lock);
0a7de745
A
170lck_mtx_ext_t mp_bc_lock_ext;
171static volatile int debugger_cpu = -1;
172volatile long NMIPI_acks = 0;
173volatile long NMI_count = 0;
174static NMI_reason_t NMI_panic_reason = NONE;
175static int vector_timed_out;
39236c6e 176
0a7de745 177extern void NMI_cpus(void);
2d21ac55 178
0a7de745
A
179static void mp_cpus_call_init(void);
180static void mp_cpus_call_action(void);
181static void mp_call_PM(void);
2d21ac55 182
0a7de745 183char mp_slave_stack[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); // Temp stack for slave init
b0d623f7 184
6d2010ae 185/* PAL-related routines */
0a7de745
A
186boolean_t i386_smp_init(int nmi_vector, i386_intr_func_t nmi_handler,
187 int ipi_vector, i386_intr_func_t ipi_handler);
6d2010ae
A
188void i386_start_cpu(int lapic_id, int cpu_num);
189void i386_send_NMI(int cpu);
5c9f4661 190void NMIPI_enable(boolean_t);
91447636
A
191#if GPROF
192/*
193 * Initialize dummy structs for profiling. These aren't used but
194 * allows hertz_tick() to be built with GPROF defined.
195 */
196struct profile_vars _profile_vars;
197struct profile_vars *_profile_vars_cpus[MAX_CPUS] = { &_profile_vars };
0a7de745
A
198#define GPROF_INIT() \
199{ \
200 int i; \
201 \
202 /* Hack to initialize pointers to unused profiling structs */ \
203 for (i = 1; i < MAX_CPUS; i++) \
204 _profile_vars_cpus[i] = &_profile_vars; \
91447636
A
205}
206#else
207#define GPROF_INIT()
208#endif /* GPROF */
209
0a7de745
A
210static lck_grp_t smp_lck_grp;
211static lck_grp_attr_t smp_lck_grp_attr;
b0d623f7 212
0a7de745
A
213#define NUM_CPU_WARM_CALLS 20
214struct timer_call cpu_warm_call_arr[NUM_CPU_WARM_CALLS];
215queue_head_t cpu_warm_call_list;
6d2010ae
A
216decl_simple_lock_data(static, cpu_warm_lock);
217
218typedef struct cpu_warm_data {
0a7de745
A
219 timer_call_t cwd_call;
220 uint64_t cwd_deadline;
221 int cwd_result;
6d2010ae
A
222} *cpu_warm_data_t;
223
0a7de745
A
224static void cpu_prewarm_init(void);
225static void cpu_warm_timer_call_func(call_entry_param_t p0, call_entry_param_t p1);
226static void _cpu_warm_setup(void *arg);
227static timer_call_t grab_warm_timer_call(void);
228static void free_warm_timer_call(timer_call_t call);
b0d623f7 229
55e303ae
A
230void
231smp_init(void)
55e303ae 232{
91447636 233 simple_lock_init(&mp_rv_lock, 0);
39037602 234 simple_lock_init(&debugger_callback_lock, 0);
b0d623f7
A
235 lck_grp_attr_setdefault(&smp_lck_grp_attr);
236 lck_grp_init(&smp_lck_grp, "i386_smp", &smp_lck_grp_attr);
237 lck_mtx_init_ext(&mp_cpu_boot_lock, &mp_cpu_boot_lock_ext, &smp_lck_grp, LCK_ATTR_NULL);
238 lck_mtx_init_ext(&mp_bc_lock, &mp_bc_lock_ext, &smp_lck_grp, LCK_ATTR_NULL);
91447636 239 console_init();
55e303ae 240
0a7de745
A
241 if (!i386_smp_init(LAPIC_NMI_INTERRUPT, NMIInterruptHandler,
242 LAPIC_VECTOR(INTERPROCESSOR), cpu_signal_handler)) {
55e303ae 243 return;
0a7de745 244 }
55e303ae 245
91447636
A
246 cpu_thread_init();
247
91447636
A
248 GPROF_INIT();
249 DBGLOG_CPU_INIT(master_cpu);
250
6d2010ae 251 mp_cpus_call_init();
fe8ab488 252 mp_cpus_call_cpu_init(master_cpu);
55e303ae 253
5ba3f43e
A
254#if DEBUG || DEVELOPMENT
255 if (PE_parse_boot_argn("interrupt_watchdog",
0a7de745
A
256 &mp_interrupt_watchdog_enabled,
257 sizeof(mp_interrupt_watchdog_enabled))) {
5ba3f43e 258 kprintf("Interrupt watchdog %sabled\n",
0a7de745 259 mp_interrupt_watchdog_enabled ? "en" : "dis");
5ba3f43e
A
260 }
261#endif
262
7e4a7d39 263 if (PE_parse_boot_argn("TSC_sync_margin",
0a7de745 264 &TSC_sync_margin, sizeof(TSC_sync_margin))) {
7e4a7d39 265 kprintf("TSC sync Margin 0x%x\n", TSC_sync_margin);
316670eb
A
266 } else if (cpuid_vmm_present()) {
267 kprintf("TSC sync margin disabled\n");
268 TSC_sync_margin = 0;
269 }
55e303ae
A
270 smp_initialized = TRUE;
271
6d2010ae
A
272 cpu_prewarm_init();
273
55e303ae
A
274 return;
275}
276
7e4a7d39 277typedef struct {
0a7de745
A
278 int target_cpu;
279 int target_lapic;
280 int starter_cpu;
7e4a7d39 281} processor_start_info_t;
0a7de745 282static processor_start_info_t start_info __attribute__((aligned(64)));
7e4a7d39 283
0a7de745 284/*
7e4a7d39
A
285 * Cache-alignment is to avoid cross-cpu false-sharing interference.
286 */
0a7de745
A
287static volatile long tsc_entry_barrier __attribute__((aligned(64)));
288static volatile long tsc_exit_barrier __attribute__((aligned(64)));
289static volatile uint64_t tsc_target __attribute__((aligned(64)));
7e4a7d39 290
0c530ab8 291/*
593a1d5f 292 * Poll a CPU to see when it has marked itself as running.
0c530ab8 293 */
593a1d5f
A
294static void
295mp_wait_for_cpu_up(int slot_num, unsigned int iters, unsigned int usecdelay)
91447636 296{
7e4a7d39 297 while (iters-- > 0) {
0a7de745 298 if (cpu_datap(slot_num)->cpu_running) {
7e4a7d39 299 break;
0a7de745 300 }
593a1d5f 301 delay(usecdelay);
91447636 302 }
55e303ae
A
303}
304
b0d623f7
A
305/*
306 * Quickly bring a CPU back online which has been halted.
307 */
308kern_return_t
309intel_startCPU_fast(int slot_num)
310{
0a7de745 311 kern_return_t rc;
b0d623f7
A
312
313 /*
314 * Try to perform a fast restart
315 */
316 rc = pmCPUExitHalt(slot_num);
0a7de745 317 if (rc != KERN_SUCCESS) {
b0d623f7
A
318 /*
319 * The CPU was not eligible for a fast restart.
320 */
0a7de745
A
321 return rc;
322 }
b0d623f7 323
bd504ef0
A
324 KERNEL_DEBUG_CONSTANT(
325 TRACE_MP_CPU_FAST_START | DBG_FUNC_START,
326 slot_num, 0, 0, 0, 0);
327
b0d623f7
A
328 /*
329 * Wait until the CPU is back online.
330 */
331 mp_disable_preemption();
0a7de745 332
b0d623f7
A
333 /*
334 * We use short pauses (1us) for low latency. 30,000 iterations is
335 * longer than a full restart would require so it should be more
336 * than long enough.
337 */
6d2010ae 338
b0d623f7
A
339 mp_wait_for_cpu_up(slot_num, 30000, 1);
340 mp_enable_preemption();
341
bd504ef0
A
342 KERNEL_DEBUG_CONSTANT(
343 TRACE_MP_CPU_FAST_START | DBG_FUNC_END,
344 slot_num, cpu_datap(slot_num)->cpu_running, 0, 0, 0);
345
b0d623f7
A
346 /*
347 * Check to make sure that the CPU is really running. If not,
348 * go through the slow path.
349 */
0a7de745
A
350 if (cpu_datap(slot_num)->cpu_running) {
351 return KERN_SUCCESS;
352 } else {
353 return KERN_FAILURE;
354 }
b0d623f7
A
355}
356
7e4a7d39
A
357static void
358started_cpu(void)
359{
360 /* Here on the started cpu with cpu_running set TRUE */
c910b4d9 361
7e4a7d39
A
362 if (TSC_sync_margin &&
363 start_info.target_cpu == cpu_number()) {
364 /*
365 * I've just started-up, synchronize again with the starter cpu
366 * and then snap my TSC.
367 */
368 tsc_target = 0;
369 atomic_decl(&tsc_entry_barrier, 1);
0a7de745
A
370 while (tsc_entry_barrier != 0) {
371 ; /* spin for starter and target at barrier */
372 }
7e4a7d39
A
373 tsc_target = rdtsc64();
374 atomic_decl(&tsc_exit_barrier, 1);
375 }
376}
c910b4d9
A
377
378static void
379start_cpu(void *arg)
380{
0a7de745
A
381 int i = 1000;
382 processor_start_info_t *psip = (processor_start_info_t *) arg;
c910b4d9
A
383
384 /* Ignore this if the current processor is not the starter */
0a7de745 385 if (cpu_number() != psip->starter_cpu) {
c910b4d9 386 return;
0a7de745 387 }
c910b4d9 388
bd504ef0 389 DBG("start_cpu(%p) about to start cpu %d, lapic %d\n",
0a7de745 390 arg, psip->target_cpu, psip->target_lapic);
bd504ef0
A
391
392 KERNEL_DEBUG_CONSTANT(
393 TRACE_MP_CPU_START | DBG_FUNC_START,
394 psip->target_cpu,
395 psip->target_lapic, 0, 0, 0);
396
6d2010ae 397 i386_start_cpu(psip->target_lapic, psip->target_cpu);
c910b4d9 398
0a7de745 399#ifdef POSTCODE_DELAY
c910b4d9
A
400 /* Wait much longer if postcodes are displayed for a delay period. */
401 i *= 10000;
402#endif
bd504ef0 403 DBG("start_cpu(%p) about to wait for cpu %d\n",
0a7de745 404 arg, psip->target_cpu);
bd504ef0 405
0a7de745 406 mp_wait_for_cpu_up(psip->target_cpu, i * 100, 100);
bd504ef0
A
407
408 KERNEL_DEBUG_CONSTANT(
409 TRACE_MP_CPU_START | DBG_FUNC_END,
410 psip->target_cpu,
411 cpu_datap(psip->target_cpu)->cpu_running, 0, 0, 0);
412
7e4a7d39
A
413 if (TSC_sync_margin &&
414 cpu_datap(psip->target_cpu)->cpu_running) {
415 /*
416 * Compare the TSC from the started processor with ours.
417 * Report and log/panic if it diverges by more than
418 * TSC_sync_margin (TSC_SYNC_MARGIN) ticks. This margin
419 * can be overriden by boot-arg (with 0 meaning no checking).
420 */
0a7de745
A
421 uint64_t tsc_starter;
422 int64_t tsc_delta;
7e4a7d39 423 atomic_decl(&tsc_entry_barrier, 1);
0a7de745
A
424 while (tsc_entry_barrier != 0) {
425 ; /* spin for both processors at barrier */
426 }
7e4a7d39
A
427 tsc_starter = rdtsc64();
428 atomic_decl(&tsc_exit_barrier, 1);
0a7de745
A
429 while (tsc_exit_barrier != 0) {
430 ; /* spin for target to store its TSC */
431 }
7e4a7d39
A
432 tsc_delta = tsc_target - tsc_starter;
433 kprintf("TSC sync for cpu %d: 0x%016llx delta 0x%llx (%lld)\n",
0a7de745
A
434 psip->target_cpu, tsc_target, tsc_delta, tsc_delta);
435 if (ABS(tsc_delta) > (int64_t) TSC_sync_margin) {
7e4a7d39
A
436#if DEBUG
437 panic(
438#else
439 printf(
440#endif
441 "Unsynchronized TSC for cpu %d: "
0a7de745 442 "0x%016llx, delta 0x%llx\n",
7e4a7d39
A
443 psip->target_cpu, tsc_target, tsc_delta);
444 }
445 }
c910b4d9
A
446}
447
55e303ae
A
448kern_return_t
449intel_startCPU(
0a7de745 450 int slot_num)
55e303ae 451{
0a7de745
A
452 int lapic = cpu_to_lapic[slot_num];
453 boolean_t istate;
55e303ae 454
91447636
A
455 assert(lapic != -1);
456
457 DBGLOG_CPU_INIT(slot_num);
55e303ae 458
91447636 459 DBG("intel_startCPU(%d) lapic_id=%d\n", slot_num, lapic);
6d2010ae 460 DBG("IdlePTD(%p): 0x%x\n", &IdlePTD, (int) (uintptr_t)IdlePTD);
55e303ae 461
0c530ab8
A
462 /*
463 * Initialize (or re-initialize) the descriptor tables for this cpu.
464 * Propagate processor mode to slave.
465 */
5ba3f43e 466 cpu_desc_init(cpu_datap(slot_num));
91447636 467
c910b4d9 468 /* Serialize use of the slave boot stack, etc. */
b0d623f7 469 lck_mtx_lock(&mp_cpu_boot_lock);
55e303ae 470
c910b4d9 471 istate = ml_set_interrupts_enabled(FALSE);
91447636 472 if (slot_num == get_cpu_number()) {
c910b4d9 473 ml_set_interrupts_enabled(istate);
b0d623f7 474 lck_mtx_unlock(&mp_cpu_boot_lock);
91447636
A
475 return KERN_SUCCESS;
476 }
55e303ae 477
b0d623f7
A
478 start_info.starter_cpu = cpu_number();
479 start_info.target_cpu = slot_num;
c910b4d9 480 start_info.target_lapic = lapic;
7e4a7d39
A
481 tsc_entry_barrier = 2;
482 tsc_exit_barrier = 2;
55e303ae 483
c910b4d9 484 /*
b0d623f7 485 * Perform the processor startup sequence with all running
c910b4d9
A
486 * processors rendezvous'ed. This is required during periods when
487 * the cache-disable bit is set for MTRR/PAT initialization.
488 */
b0d623f7 489 mp_rendezvous_no_intrs(start_cpu, (void *) &start_info);
55e303ae 490
7e4a7d39
A
491 start_info.target_cpu = 0;
492
c910b4d9 493 ml_set_interrupts_enabled(istate);
b0d623f7 494 lck_mtx_unlock(&mp_cpu_boot_lock);
55e303ae 495
91447636 496 if (!cpu_datap(slot_num)->cpu_running) {
0c530ab8 497 kprintf("Failed to start CPU %02d\n", slot_num);
91447636
A
498 printf("Failed to start CPU %02d, rebooting...\n", slot_num);
499 delay(1000000);
b0d623f7 500 halt_cpu();
55e303ae
A
501 return KERN_SUCCESS;
502 } else {
2d21ac55 503 kprintf("Started cpu %d (lapic id %08x)\n", slot_num, lapic);
55e303ae
A
504 return KERN_SUCCESS;
505 }
506}
507
0a7de745
A
508#if MP_DEBUG
509cpu_signal_event_log_t *cpu_signal[MAX_CPUS];
510cpu_signal_event_log_t *cpu_handle[MAX_CPUS];
55e303ae
A
511
512MP_EVENT_NAME_DECL();
513
0a7de745 514#endif /* MP_DEBUG */
55e303ae 515
fe8ab488
A
516/*
517 * Note: called with NULL state when polling for TLB flush and cross-calls.
518 */
593a1d5f 519int
0c530ab8 520cpu_signal_handler(x86_saved_state_t *regs)
55e303ae 521{
0a7de745 522#if !MACH_KDP
39236c6e
A
523#pragma unused (regs)
524#endif /* !MACH_KDP */
0a7de745
A
525 int my_cpu;
526 volatile int *my_word;
55e303ae 527
6d2010ae 528 SCHED_STATS_IPI(current_processor());
55e303ae
A
529
530 my_cpu = cpu_number();
060df5ea
A
531 my_word = &cpu_data_ptr[my_cpu]->cpu_signals;
532 /* Store the initial set of signals for diagnostics. New
533 * signals could arrive while these are being processed
534 * so it's no more than a hint.
535 */
6d2010ae 536
060df5ea 537 cpu_data_ptr[my_cpu]->cpu_prior_signals = *my_word;
55e303ae
A
538
539 do {
0a7de745 540#if MACH_KDP
fe8ab488 541 if (i_bit(MP_KDP, my_word)) {
0a7de745 542 DBGLOG(cpu_handle, my_cpu, MP_KDP);
55e303ae 543 i_bit_clear(MP_KDP, my_word);
0c530ab8
A
544/* Ensure that the i386_kernel_state at the base of the
545 * current thread's stack (if any) is synchronized with the
546 * context at the moment of the interrupt, to facilitate
547 * access through the debugger.
0c530ab8 548 */
b0d623f7 549 sync_iss_to_iks(regs);
0a7de745 550 if (pmsafe_debug && !kdp_snapshot) {
d41d1dae 551 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
0a7de745 552 }
b0d623f7 553 mp_kdp_wait(TRUE, FALSE);
0a7de745 554 if (pmsafe_debug && !kdp_snapshot) {
d41d1dae 555 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL);
0a7de745 556 }
55e303ae 557 } else
0a7de745 558#endif /* MACH_KDP */
91447636 559 if (i_bit(MP_TLB_FLUSH, my_word)) {
0a7de745 560 DBGLOG(cpu_handle, my_cpu, MP_TLB_FLUSH);
55e303ae
A
561 i_bit_clear(MP_TLB_FLUSH, my_word);
562 pmap_update_interrupt();
2d21ac55 563 } else if (i_bit(MP_CALL, my_word)) {
0a7de745 564 DBGLOG(cpu_handle, my_cpu, MP_CALL);
2d21ac55
A
565 i_bit_clear(MP_CALL, my_word);
566 mp_cpus_call_action();
c910b4d9 567 } else if (i_bit(MP_CALL_PM, my_word)) {
0a7de745 568 DBGLOG(cpu_handle, my_cpu, MP_CALL_PM);
c910b4d9
A
569 i_bit_clear(MP_CALL_PM, my_word);
570 mp_call_PM();
55e303ae 571 }
fe8ab488
A
572 if (regs == NULL) {
573 /* Called to poll only for cross-calls and TLB flush */
574 break;
575 } else if (i_bit(MP_AST, my_word)) {
0a7de745 576 DBGLOG(cpu_handle, my_cpu, MP_AST);
fe8ab488
A
577 i_bit_clear(MP_AST, my_word);
578 ast_check(cpu_to_processor(my_cpu));
579 }
55e303ae
A
580 } while (*my_word);
581
593a1d5f 582 return 0;
55e303ae
A
583}
584
fe8ab488 585extern void kprintf_break_lock(void);
d9a64523 586int
2d21ac55 587NMIInterruptHandler(x86_saved_state_t *regs)
0c530ab8 588{
0a7de745
A
589 void *stackptr;
590 char pstr[256];
591 uint64_t now = mach_absolute_time();
060df5ea 592
6d2010ae 593 if (panic_active() && !panicDebugging) {
0a7de745 594 if (pmsafe_debug) {
6d2010ae 595 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
0a7de745
A
596 }
597 for (;;) {
6d2010ae 598 cpu_pause();
0a7de745 599 }
6d2010ae
A
600 }
601
060df5ea 602 atomic_incl(&NMIPI_acks, 1);
39236c6e 603 atomic_incl(&NMI_count, 1);
0c530ab8 604 sync_iss_to_iks_unconditionally(regs);
0a7de745 605 __asm__ volatile ("movq %%rbp, %0" : "=m" (stackptr));
935ed37a 606
0a7de745 607 if (cpu_number() == debugger_cpu) {
fe8ab488 608 goto NMExit;
0a7de745 609 }
593a1d5f 610
5ba3f43e
A
611 if (NMI_panic_reason == SPINLOCK_TIMEOUT) {
612 snprintf(&pstr[0], sizeof(pstr),
0a7de745
A
613 "Panic(CPU %d, time %llu): NMIPI for spinlock acquisition timeout, spinlock: %p, spinlock owner: %p, current_thread: %p, spinlock_owner_cpu: 0x%x\n",
614 cpu_number(), now, spinlock_timed_out, (void *) spinlock_timed_out->interlock.lock_data, current_thread(), spinlock_owner_cpu);
fe8ab488 615 panic_i386_backtrace(stackptr, 64, &pstr[0], TRUE, regs);
5ba3f43e
A
616 } else if (NMI_panic_reason == TLB_FLUSH_TIMEOUT) {
617 snprintf(&pstr[0], sizeof(pstr),
0a7de745
A
618 "Panic(CPU %d, time %llu): NMIPI for unresponsive processor: TLB flush timeout, TLB state:0x%x\n",
619 cpu_number(), now, current_cpu_datap()->cpu_tlb_invalid);
6d2010ae 620 panic_i386_backtrace(stackptr, 48, &pstr[0], TRUE, regs);
5ba3f43e
A
621 } else if (NMI_panic_reason == CROSSCALL_TIMEOUT) {
622 snprintf(&pstr[0], sizeof(pstr),
0a7de745
A
623 "Panic(CPU %d, time %llu): NMIPI for unresponsive processor: cross-call timeout\n",
624 cpu_number(), now);
5ba3f43e
A
625 panic_i386_backtrace(stackptr, 64, &pstr[0], TRUE, regs);
626 } else if (NMI_panic_reason == INTERRUPT_WATCHDOG) {
627 snprintf(&pstr[0], sizeof(pstr),
0a7de745
A
628 "Panic(CPU %d, time %llu): NMIPI for unresponsive processor: interrupt watchdog for vector 0x%x\n",
629 cpu_number(), now, vector_timed_out);
5ba3f43e
A
630 panic_i386_backtrace(stackptr, 64, &pstr[0], TRUE, regs);
631 }
0a7de745 632
b0d623f7 633#if MACH_KDP
0a7de745 634 if (pmsafe_debug && !kdp_snapshot) {
d41d1dae 635 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
0a7de745 636 }
060df5ea 637 current_cpu_datap()->cpu_NMI_acknowledged = TRUE;
15129b1c 638 i_bit_clear(MP_KDP, &current_cpu_datap()->cpu_signals);
5ba3f43e 639 if (panic_active() || NMI_panic_reason != NONE) {
fe8ab488 640 mp_kdp_wait(FALSE, TRUE);
39037602 641 } else if (!mp_kdp_trap &&
0a7de745
A
642 !mp_kdp_is_NMI &&
643 virtualized && (debug_boot_arg & DB_NMI)) {
fe8ab488
A
644 /*
645 * Under a VMM with the debug boot-arg set, drop into kdp.
646 * Since an NMI is involved, there's a risk of contending with
0a7de745 647 * a panic. And side-effects of NMIs may result in entry into,
fe8ab488
A
648 * and continuing from, the debugger being unreliable.
649 */
39037602
A
650 if (__sync_bool_compare_and_swap(&mp_kdp_is_NMI, FALSE, TRUE)) {
651 kprintf_break_lock();
652 kprintf("Debugger entry requested by NMI\n");
653 kdp_i386_trap(T_DEBUG, saved_state64(regs), 0, 0);
654 printf("Debugger entry requested by NMI\n");
655 mp_kdp_is_NMI = FALSE;
656 } else {
657 mp_kdp_wait(FALSE, FALSE);
658 }
fe8ab488
A
659 } else {
660 mp_kdp_wait(FALSE, FALSE);
661 }
0a7de745 662 if (pmsafe_debug && !kdp_snapshot) {
d41d1dae 663 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL);
0a7de745 664 }
b0d623f7 665#endif
0a7de745 666NMExit:
0c530ab8
A
667 return 1;
668}
669
2d21ac55
A
670
671/*
672 * cpu_interrupt is really just to be used by the scheduler to
673 * get a CPU's attention it may not always issue an IPI. If an
674 * IPI is always needed then use i386_cpu_IPI.
675 */
676void
677cpu_interrupt(int cpu)
678{
6d2010ae
A
679 boolean_t did_IPI = FALSE;
680
2d21ac55
A
681 if (smp_initialized
682 && pmCPUExitIdle(cpu_datap(cpu))) {
683 i386_cpu_IPI(cpu);
6d2010ae 684 did_IPI = TRUE;
2d21ac55 685 }
6d2010ae
A
686
687 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_REMOTE_AST), cpu, did_IPI, 0, 0, 0);
55e303ae
A
688}
689
0c530ab8
A
690/*
691 * Send a true NMI via the local APIC to the specified CPU.
692 */
935ed37a 693void
0c530ab8
A
694cpu_NMI_interrupt(int cpu)
695{
0c530ab8 696 if (smp_initialized) {
6d2010ae 697 i386_send_NMI(cpu);
0c530ab8 698 }
0c530ab8
A
699}
700
39236c6e
A
701void
702NMI_cpus(void)
703{
0a7de745
A
704 unsigned int cpu;
705 boolean_t intrs_enabled;
706 uint64_t tsc_timeout;
39236c6e
A
707
708 intrs_enabled = ml_set_interrupts_enabled(FALSE);
d9a64523 709 NMIPI_enable(TRUE);
39236c6e 710 for (cpu = 0; cpu < real_ncpus; cpu++) {
0a7de745 711 if (!cpu_is_running(cpu)) {
39236c6e 712 continue;
0a7de745 713 }
39236c6e
A
714 cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE;
715 cpu_NMI_interrupt(cpu);
716 tsc_timeout = !machine_timeout_suspended() ?
0a7de745
A
717 rdtsc64() + (1000 * 1000 * 1000 * 10ULL) :
718 ~0ULL;
39236c6e
A
719 while (!cpu_datap(cpu)->cpu_NMI_acknowledged) {
720 handle_pending_TLB_flushes();
721 cpu_pause();
0a7de745 722 if (rdtsc64() > tsc_timeout) {
39236c6e 723 panic("NMI_cpus() timeout cpu %d", cpu);
0a7de745 724 }
39236c6e
A
725 }
726 cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE;
727 }
d9a64523 728 NMIPI_enable(FALSE);
39236c6e
A
729
730 ml_set_interrupts_enabled(intrs_enabled);
731}
732
0a7de745 733static void(*volatile mp_PM_func)(void) = NULL;
c910b4d9
A
734
735static void
736mp_call_PM(void)
737{
738 assert(!ml_get_interrupts_enabled());
739
0a7de745 740 if (mp_PM_func != NULL) {
c910b4d9 741 mp_PM_func();
0a7de745 742 }
c910b4d9
A
743}
744
745void
746cpu_PM_interrupt(int cpu)
747{
748 assert(!ml_get_interrupts_enabled());
749
750 if (mp_PM_func != NULL) {
0a7de745 751 if (cpu == cpu_number()) {
c910b4d9 752 mp_PM_func();
0a7de745 753 } else {
c910b4d9 754 i386_signal_cpu(cpu, MP_CALL_PM, ASYNC);
0a7de745 755 }
c910b4d9
A
756 }
757}
758
759void
760PM_interrupt_register(void (*fn)(void))
761{
762 mp_PM_func = fn;
763}
764
55e303ae
A
765void
766i386_signal_cpu(int cpu, mp_event_t event, mp_sync_t mode)
767{
0a7de745
A
768 volatile int *signals = &cpu_datap(cpu)->cpu_signals;
769 uint64_t tsc_timeout;
770
6601e61a 771
0a7de745 772 if (!cpu_datap(cpu)->cpu_running) {
55e303ae 773 return;
0a7de745 774 }
55e303ae 775
0a7de745
A
776 if (event == MP_TLB_FLUSH) {
777 KERNEL_DEBUG(TRACE_MP_TLB_FLUSH | DBG_FUNC_START, cpu, 0, 0, 0, 0);
778 }
6601e61a 779
0c530ab8 780 DBGLOG(cpu_signal, cpu, event);
0a7de745 781
55e303ae 782 i_bit_set(event, signals);
2d21ac55 783 i386_cpu_IPI(cpu);
55e303ae 784 if (mode == SYNC) {
0a7de745 785again:
39236c6e 786 tsc_timeout = !machine_timeout_suspended() ?
0a7de745
A
787 rdtsc64() + (1000 * 1000 * 1000) :
788 ~0ULL;
91447636 789 while (i_bit(event, signals) && rdtsc64() < tsc_timeout) {
55e303ae
A
790 cpu_pause();
791 }
792 if (i_bit(event, signals)) {
793 DBG("i386_signal_cpu(%d, 0x%x, SYNC) timed out\n",
0a7de745 794 cpu, event);
55e303ae
A
795 goto again;
796 }
797 }
0a7de745
A
798 if (event == MP_TLB_FLUSH) {
799 KERNEL_DEBUG(TRACE_MP_TLB_FLUSH | DBG_FUNC_END, cpu, 0, 0, 0, 0);
800 }
55e303ae
A
801}
802
39236c6e
A
803/*
804 * Helper function called when busy-waiting: panic if too long
805 * a TSC-based time has elapsed since the start of the spin.
806 */
fe8ab488
A
807static boolean_t
808mp_spin_timeout(uint64_t tsc_start)
39236c6e 809{
0a7de745 810 uint64_t tsc_timeout;
39236c6e
A
811
812 cpu_pause();
0a7de745 813 if (machine_timeout_suspended()) {
fe8ab488 814 return FALSE;
0a7de745 815 }
39236c6e
A
816
817 /*
818 * The timeout is 4 * the spinlock timeout period
819 * unless we have serial console printing (kprintf) enabled
820 * in which case we allow an even greater margin.
821 */
39037602 822 tsc_timeout = disable_serial_output ? LockTimeOutTSC << 2
0a7de745
A
823 : LockTimeOutTSC << 4;
824 return rdtsc64() > tsc_start + tsc_timeout;
fe8ab488
A
825}
826
827/*
828 * Helper function to take a spinlock while ensuring that incoming IPIs
829 * are still serviced if interrupts are masked while we spin.
39037602 830 * Returns current interrupt state.
fe8ab488 831 */
5ba3f43e 832boolean_t
fe8ab488
A
833mp_safe_spin_lock(usimple_lock_t lock)
834{
835 if (ml_get_interrupts_enabled()) {
0a7de745 836 simple_lock(lock, LCK_GRP_NULL);
fe8ab488
A
837 return TRUE;
838 } else {
839 uint64_t tsc_spin_start = rdtsc64();
0a7de745 840 while (!simple_lock_try(lock, LCK_GRP_NULL)) {
fe8ab488
A
841 cpu_signal_handler(NULL);
842 if (mp_spin_timeout(tsc_spin_start)) {
843 uint32_t lock_cpu;
844 uintptr_t lowner = (uintptr_t)
0a7de745 845 lock->interlock.lock_data;
fe8ab488
A
846 spinlock_timed_out = lock;
847 lock_cpu = spinlock_timeout_NMI(lowner);
5ba3f43e
A
848 NMIPI_panic(cpu_to_cpumask(lock_cpu), SPINLOCK_TIMEOUT);
849 panic("mp_safe_spin_lock() timed out, lock: %p, owner thread: 0x%lx, current_thread: %p, owner on CPU 0x%x, time: %llu",
0a7de745 850 lock, lowner, current_thread(), lock_cpu, mach_absolute_time());
fe8ab488
A
851 }
852 }
853 return FALSE;
0a7de745 854 }
39236c6e
A
855}
856
55e303ae
A
857/*
858 * All-CPU rendezvous:
0a7de745 859 * - CPUs are signalled,
55e303ae
A
860 * - all execute the setup function (if specified),
861 * - rendezvous (i.e. all cpus reach a barrier),
862 * - all execute the action function (if specified),
863 * - rendezvous again,
864 * - execute the teardown function (if specified), and then
865 * - resume.
866 *
867 * Note that the supplied external functions _must_ be reentrant and aware
868 * that they are running in parallel and in an unknown lock context.
869 */
870
871static void
39037602 872mp_rendezvous_action(__unused void *null)
55e303ae 873{
0a7de745
A
874 boolean_t intrs_enabled;
875 uint64_t tsc_spin_start;
55e303ae 876
d9a64523
A
877 /*
878 * Note that mp_rv_lock was acquired by the thread that initiated the
879 * rendezvous and must have been acquired before we enter
880 * mp_rendezvous_action().
881 */
882 current_cpu_datap()->cpu_rendezvous_in_progress = TRUE;
883
55e303ae 884 /* setup function */
0a7de745 885 if (mp_rv_setup_func != NULL) {
55e303ae 886 mp_rv_setup_func(mp_rv_func_arg);
0a7de745 887 }
2d21ac55
A
888
889 intrs_enabled = ml_get_interrupts_enabled();
890
55e303ae 891 /* spin on entry rendezvous */
0c530ab8 892 atomic_incl(&mp_rv_entry, 1);
39236c6e 893 tsc_spin_start = rdtsc64();
490019cf 894
0c530ab8 895 while (mp_rv_entry < mp_rv_ncpus) {
2d21ac55 896 /* poll for pesky tlb flushes if interrupts disabled */
0a7de745 897 if (!intrs_enabled) {
2d21ac55 898 handle_pending_TLB_flushes();
0a7de745 899 }
490019cf
A
900 if (mp_spin_timeout(tsc_spin_start)) {
901 panic("mp_rv_action() entry: %ld of %d responses, start: 0x%llx, cur: 0x%llx", mp_rv_entry, mp_rv_ncpus, tsc_spin_start, rdtsc64());
902 }
0c530ab8 903 }
6d2010ae 904
55e303ae 905 /* action function */
0a7de745 906 if (mp_rv_action_func != NULL) {
55e303ae 907 mp_rv_action_func(mp_rv_func_arg);
0a7de745 908 }
6d2010ae 909
55e303ae 910 /* spin on exit rendezvous */
0c530ab8 911 atomic_incl(&mp_rv_exit, 1);
39236c6e 912 tsc_spin_start = rdtsc64();
2d21ac55 913 while (mp_rv_exit < mp_rv_ncpus) {
0a7de745 914 if (!intrs_enabled) {
2d21ac55 915 handle_pending_TLB_flushes();
0a7de745
A
916 }
917 if (mp_spin_timeout(tsc_spin_start)) {
490019cf 918 panic("mp_rv_action() exit: %ld of %d responses, start: 0x%llx, cur: 0x%llx", mp_rv_exit, mp_rv_ncpus, tsc_spin_start, rdtsc64());
0a7de745 919 }
2d21ac55 920 }
6d2010ae 921
55e303ae 922 /* teardown function */
0a7de745 923 if (mp_rv_teardown_func != NULL) {
55e303ae 924 mp_rv_teardown_func(mp_rv_func_arg);
0a7de745 925 }
0c530ab8 926
d9a64523
A
927 current_cpu_datap()->cpu_rendezvous_in_progress = FALSE;
928
0c530ab8
A
929 /* Bump completion count */
930 atomic_incl(&mp_rv_complete, 1);
55e303ae
A
931}
932
933void
0a7de745
A
934mp_rendezvous(void (*setup_func)(void *),
935 void (*action_func)(void *),
936 void (*teardown_func)(void *),
937 void *arg)
55e303ae 938{
0a7de745 939 uint64_t tsc_spin_start;
55e303ae
A
940
941 if (!smp_initialized) {
0a7de745 942 if (setup_func != NULL) {
55e303ae 943 setup_func(arg);
0a7de745
A
944 }
945 if (action_func != NULL) {
55e303ae 946 action_func(arg);
0a7de745
A
947 }
948 if (teardown_func != NULL) {
55e303ae 949 teardown_func(arg);
0a7de745 950 }
55e303ae
A
951 return;
952 }
0a7de745 953
55e303ae 954 /* obtain rendezvous lock */
d9a64523 955 mp_rendezvous_lock();
55e303ae
A
956
957 /* set static function pointers */
958 mp_rv_setup_func = setup_func;
959 mp_rv_action_func = action_func;
960 mp_rv_teardown_func = teardown_func;
961 mp_rv_func_arg = arg;
962
0c530ab8
A
963 mp_rv_entry = 0;
964 mp_rv_exit = 0;
965 mp_rv_complete = 0;
55e303ae
A
966
967 /*
968 * signal other processors, which will call mp_rendezvous_action()
2d21ac55 969 * with interrupts disabled
55e303ae 970 */
39037602 971 mp_rv_ncpus = mp_cpus_call(CPUMASK_OTHERS, NOSYNC, &mp_rendezvous_action, NULL) + 1;
55e303ae
A
972
973 /* call executor function on this cpu */
39037602 974 mp_rendezvous_action(NULL);
55e303ae 975
0c530ab8
A
976 /*
977 * Spin for everyone to complete.
978 * This is necessary to ensure that all processors have proceeded
979 * from the exit barrier before we release the rendezvous structure.
980 */
39236c6e 981 tsc_spin_start = rdtsc64();
0c530ab8 982 while (mp_rv_complete < mp_rv_ncpus) {
0a7de745 983 if (mp_spin_timeout(tsc_spin_start)) {
490019cf 984 panic("mp_rendezvous() timeout: %ld of %d responses, start: 0x%llx, cur: 0x%llx", mp_rv_complete, mp_rv_ncpus, tsc_spin_start, rdtsc64());
0a7de745 985 }
0c530ab8 986 }
0a7de745 987
2d21ac55
A
988 /* Tidy up */
989 mp_rv_setup_func = NULL;
990 mp_rv_action_func = NULL;
991 mp_rv_teardown_func = NULL;
992 mp_rv_func_arg = NULL;
993
55e303ae 994 /* release lock */
d9a64523
A
995 mp_rendezvous_unlock();
996}
997
998void
999mp_rendezvous_lock(void)
1000{
1001 (void) mp_safe_spin_lock(&mp_rv_lock);
1002}
1003
1004void
1005mp_rendezvous_unlock(void)
1006{
55e303ae
A
1007 simple_unlock(&mp_rv_lock);
1008}
1009
0c530ab8
A
1010void
1011mp_rendezvous_break_lock(void)
1012{
1013 simple_lock_init(&mp_rv_lock, 0);
1014}
1015
1016static void
1017setup_disable_intrs(__unused void * param_not_used)
1018{
1019 /* disable interrupts before the first barrier */
1020 boolean_t intr = ml_set_interrupts_enabled(FALSE);
1021
1022 current_cpu_datap()->cpu_iflag = intr;
1023 DBG("CPU%d: %s\n", get_cpu_number(), __FUNCTION__);
1024}
1025
1026static void
1027teardown_restore_intrs(__unused void * param_not_used)
1028{
1029 /* restore interrupt flag following MTRR changes */
1030 ml_set_interrupts_enabled(current_cpu_datap()->cpu_iflag);
1031 DBG("CPU%d: %s\n", get_cpu_number(), __FUNCTION__);
1032}
1033
1034/*
1035 * A wrapper to mp_rendezvous() to call action_func() with interrupts disabled.
1036 * This is exported for use by kexts.
1037 */
1038void
1039mp_rendezvous_no_intrs(
0a7de745
A
1040 void (*action_func)(void *),
1041 void *arg)
0c530ab8
A
1042{
1043 mp_rendezvous(setup_disable_intrs,
0a7de745
A
1044 action_func,
1045 teardown_restore_intrs,
1046 arg);
0c530ab8
A
1047}
1048
6d2010ae
A
1049
1050typedef struct {
0a7de745
A
1051 queue_chain_t link; /* queue linkage */
1052 void (*func)(void *, void *); /* routine to call */
1053 void *arg0; /* routine's 1st arg */
1054 void *arg1; /* routine's 2nd arg */
1055 cpumask_t *maskp; /* completion response mask */
6d2010ae 1056} mp_call_t;
316670eb
A
1057
1058
1059typedef struct {
0a7de745
A
1060 queue_head_t queue;
1061 decl_simple_lock_data(, lock);
316670eb 1062} mp_call_queue_t;
0a7de745
A
1063#define MP_CPUS_CALL_BUFS_PER_CPU MAX_CPUS
1064static mp_call_queue_t mp_cpus_call_freelist;
1065static mp_call_queue_t mp_cpus_call_head[MAX_CPUS];
6d2010ae
A
1066
1067static inline boolean_t
316670eb 1068mp_call_head_lock(mp_call_queue_t *cqp)
6d2010ae 1069{
0a7de745 1070 boolean_t intrs_enabled;
6d2010ae
A
1071
1072 intrs_enabled = ml_set_interrupts_enabled(FALSE);
0a7de745 1073 simple_lock(&cqp->lock, LCK_GRP_NULL);
6d2010ae
A
1074
1075 return intrs_enabled;
1076}
1077
5ba3f43e
A
1078/*
1079 * Deliver an NMIPI to a set of processors to cause them to panic .
1080 */
fe8ab488 1081void
0a7de745
A
1082NMIPI_panic(cpumask_t cpu_mask, NMI_reason_t why)
1083{
d9a64523
A
1084 unsigned int cpu;
1085 cpumask_t cpu_bit;
fe8ab488
A
1086 uint64_t deadline;
1087
5c9f4661 1088 NMIPI_enable(TRUE);
5ba3f43e
A
1089 NMI_panic_reason = why;
1090
fe8ab488 1091 for (cpu = 0, cpu_bit = 1; cpu < real_ncpus; cpu++, cpu_bit <<= 1) {
0a7de745 1092 if ((cpu_mask & cpu_bit) == 0) {
5ba3f43e 1093 continue;
0a7de745 1094 }
5ba3f43e
A
1095 cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE;
1096 cpu_NMI_interrupt(cpu);
1097 }
1098
1099 /* Wait (only so long) for NMi'ed cpus to respond */
1100 deadline = mach_absolute_time() + LockTimeOut;
1101 for (cpu = 0, cpu_bit = 1; cpu < real_ncpus; cpu++, cpu_bit <<= 1) {
0a7de745 1102 if ((cpu_mask & cpu_bit) == 0) {
5ba3f43e 1103 continue;
0a7de745 1104 }
5ba3f43e 1105 while (!cpu_datap(cpu)->cpu_NMI_acknowledged &&
0a7de745 1106 mach_absolute_time() < deadline) {
5ba3f43e
A
1107 cpu_pause();
1108 }
fe8ab488 1109 }
fe8ab488
A
1110}
1111
1112#if MACH_ASSERT
6d2010ae 1113static inline boolean_t
316670eb 1114mp_call_head_is_locked(mp_call_queue_t *cqp)
6d2010ae
A
1115{
1116 return !ml_get_interrupts_enabled() &&
0a7de745 1117 hw_lock_held((hw_lock_t)&cqp->lock);
6d2010ae 1118}
fe8ab488 1119#endif
6d2010ae
A
1120
1121static inline void
316670eb 1122mp_call_head_unlock(mp_call_queue_t *cqp, boolean_t intrs_enabled)
6d2010ae 1123{
316670eb 1124 simple_unlock(&cqp->lock);
6d2010ae
A
1125 ml_set_interrupts_enabled(intrs_enabled);
1126}
1127
1128static inline mp_call_t *
1129mp_call_alloc(void)
1130{
0a7de745
A
1131 mp_call_t *callp = NULL;
1132 boolean_t intrs_enabled;
1133 mp_call_queue_t *cqp = &mp_cpus_call_freelist;
316670eb
A
1134
1135 intrs_enabled = mp_call_head_lock(cqp);
0a7de745 1136 if (!queue_empty(&cqp->queue)) {
316670eb 1137 queue_remove_first(&cqp->queue, callp, typeof(callp), link);
0a7de745 1138 }
316670eb 1139 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae 1140
6d2010ae
A
1141 return callp;
1142}
1143
1144static inline void
1145mp_call_free(mp_call_t *callp)
0c530ab8 1146{
0a7de745
A
1147 boolean_t intrs_enabled;
1148 mp_call_queue_t *cqp = &mp_cpus_call_freelist;
316670eb
A
1149
1150 intrs_enabled = mp_call_head_lock(cqp);
1151 queue_enter_first(&cqp->queue, callp, typeof(callp), link);
1152 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1153}
1154
1155static inline mp_call_t *
316670eb 1156mp_call_dequeue_locked(mp_call_queue_t *cqp)
6d2010ae 1157{
0a7de745 1158 mp_call_t *callp = NULL;
0c530ab8 1159
316670eb 1160 assert(mp_call_head_is_locked(cqp));
0a7de745 1161 if (!queue_empty(&cqp->queue)) {
316670eb 1162 queue_remove_first(&cqp->queue, callp, typeof(callp), link);
0a7de745 1163 }
6d2010ae
A
1164 return callp;
1165}
1166
316670eb
A
1167static inline void
1168mp_call_enqueue_locked(
0a7de745
A
1169 mp_call_queue_t *cqp,
1170 mp_call_t *callp)
316670eb
A
1171{
1172 queue_enter(&cqp->queue, callp, typeof(callp), link);
1173}
1174
6d2010ae
A
1175/* Called on the boot processor to initialize global structures */
1176static void
1177mp_cpus_call_init(void)
1178{
0a7de745 1179 mp_call_queue_t *cqp = &mp_cpus_call_freelist;
316670eb 1180
6d2010ae 1181 DBG("mp_cpus_call_init()\n");
316670eb
A
1182 simple_lock_init(&cqp->lock, 0);
1183 queue_init(&cqp->queue);
6d2010ae
A
1184}
1185
1186/*
fe8ab488 1187 * Called at processor registration to add call buffers to the free list
6d2010ae 1188 * and to initialize the per-cpu call queue.
6d2010ae 1189 */
fe8ab488
A
1190void
1191mp_cpus_call_cpu_init(int cpu)
6d2010ae 1192{
0a7de745
A
1193 int i;
1194 mp_call_queue_t *cqp = &mp_cpus_call_head[cpu];
1195 mp_call_t *callp;
6d2010ae 1196
316670eb
A
1197 simple_lock_init(&cqp->lock, 0);
1198 queue_init(&cqp->queue);
6d2010ae
A
1199 for (i = 0; i < MP_CPUS_CALL_BUFS_PER_CPU; i++) {
1200 callp = (mp_call_t *) kalloc(sizeof(mp_call_t));
6d2010ae 1201 mp_call_free(callp);
0c530ab8 1202 }
6d2010ae 1203
fe8ab488 1204 DBG("mp_cpus_call_init(%d) done\n", cpu);
0c530ab8
A
1205}
1206
2d21ac55
A
1207/*
1208 * This is called from cpu_signal_handler() to process an MP_CALL signal.
6d2010ae 1209 * And also from i386_deactivate_cpu() when a cpu is being taken offline.
2d21ac55
A
1210 */
1211static void
1212mp_cpus_call_action(void)
1213{
0a7de745
A
1214 mp_call_queue_t *cqp;
1215 boolean_t intrs_enabled;
1216 mp_call_t *callp;
1217 mp_call_t call;
6d2010ae
A
1218
1219 assert(!ml_get_interrupts_enabled());
316670eb
A
1220 cqp = &mp_cpus_call_head[cpu_number()];
1221 intrs_enabled = mp_call_head_lock(cqp);
1222 while ((callp = mp_call_dequeue_locked(cqp)) != NULL) {
6d2010ae
A
1223 /* Copy call request to the stack to free buffer */
1224 call = *callp;
1225 mp_call_free(callp);
1226 if (call.func != NULL) {
316670eb 1227 mp_call_head_unlock(cqp, intrs_enabled);
6d2010ae
A
1228 KERNEL_DEBUG_CONSTANT(
1229 TRACE_MP_CPUS_CALL_ACTION,
4bd07ac2
A
1230 VM_KERNEL_UNSLIDE(call.func), VM_KERNEL_UNSLIDE_OR_PERM(call.arg0),
1231 VM_KERNEL_UNSLIDE_OR_PERM(call.arg1), VM_KERNEL_ADDRPERM(call.maskp), 0);
6d2010ae 1232 call.func(call.arg0, call.arg1);
316670eb 1233 (void) mp_call_head_lock(cqp);
6d2010ae 1234 }
0a7de745 1235 if (call.maskp != NULL) {
fe8ab488 1236 i_bit_set(cpu_number(), call.maskp);
0a7de745 1237 }
6d2010ae 1238 }
316670eb 1239 mp_call_head_unlock(cqp, intrs_enabled);
2d21ac55
A
1240}
1241
1242/*
1243 * mp_cpus_call() runs a given function on cpus specified in a given cpu mask.
6d2010ae
A
1244 * Possible modes are:
1245 * SYNC: function is called serially on target cpus in logical cpu order
1246 * waiting for each call to be acknowledged before proceeding
1247 * ASYNC: function call is queued to the specified cpus
1248 * waiting for all calls to complete in parallel before returning
1249 * NOSYNC: function calls are queued
0a7de745 1250 * but we return before confirmation of calls completing.
2d21ac55
A
1251 * The action function may be NULL.
1252 * The cpu mask may include the local cpu. Offline cpus are ignored.
6d2010ae 1253 * The return value is the number of cpus on which the call was made or queued.
2d21ac55
A
1254 */
1255cpu_t
1256mp_cpus_call(
0a7de745
A
1257 cpumask_t cpus,
1258 mp_sync_t mode,
1259 void (*action_func)(void *),
1260 void *arg)
6d2010ae
A
1261{
1262 return mp_cpus_call1(
0a7de745
A
1263 cpus,
1264 mode,
1265 (void (*)(void *, void *))action_func,
1266 arg,
1267 NULL,
1268 NULL);
6d2010ae
A
1269}
1270
1271static void
0a7de745
A
1272mp_cpus_call_wait(boolean_t intrs_enabled,
1273 cpumask_t cpus_called,
1274 cpumask_t *cpus_responded)
6d2010ae 1275{
0a7de745
A
1276 mp_call_queue_t *cqp;
1277 uint64_t tsc_spin_start;
6d2010ae 1278
39037602 1279 assert(ml_get_interrupts_enabled() == 0 || get_preemption_level() != 0);
316670eb 1280 cqp = &mp_cpus_call_head[cpu_number()];
6d2010ae 1281
39236c6e 1282 tsc_spin_start = rdtsc64();
fe8ab488 1283 while (*cpus_responded != cpus_called) {
6d2010ae 1284 if (!intrs_enabled) {
316670eb 1285 /* Sniffing w/o locking */
0a7de745 1286 if (!queue_empty(&cqp->queue)) {
6d2010ae 1287 mp_cpus_call_action();
0a7de745 1288 }
fe8ab488
A
1289 cpu_signal_handler(NULL);
1290 }
1291 if (mp_spin_timeout(tsc_spin_start)) {
0a7de745 1292 cpumask_t cpus_unresponsive;
fe8ab488 1293
fe8ab488 1294 cpus_unresponsive = cpus_called & ~(*cpus_responded);
5ba3f43e 1295 NMIPI_panic(cpus_unresponsive, CROSSCALL_TIMEOUT);
3e170ce0 1296 panic("mp_cpus_call_wait() timeout, cpus: 0x%llx",
0a7de745 1297 cpus_unresponsive);
6d2010ae 1298 }
6d2010ae
A
1299 }
1300}
1301
1302cpu_t
1303mp_cpus_call1(
0a7de745
A
1304 cpumask_t cpus,
1305 mp_sync_t mode,
1306 void (*action_func)(void *, void *),
1307 void *arg0,
1308 void *arg1,
1309 cpumask_t *cpus_calledp)
1310{
1311 cpu_t cpu = 0;
1312 boolean_t intrs_enabled = FALSE;
1313 boolean_t call_self = FALSE;
1314 cpumask_t cpus_called = 0;
1315 cpumask_t cpus_responded = 0;
1316 long cpus_call_count = 0;
1317 uint64_t tsc_spin_start;
1318 boolean_t topo_lock;
6d2010ae
A
1319
1320 KERNEL_DEBUG_CONSTANT(
1321 TRACE_MP_CPUS_CALL | DBG_FUNC_START,
4bd07ac2 1322 cpus, mode, VM_KERNEL_UNSLIDE(action_func), VM_KERNEL_UNSLIDE_OR_PERM(arg0), VM_KERNEL_UNSLIDE_OR_PERM(arg1));
2d21ac55
A
1323
1324 if (!smp_initialized) {
0a7de745 1325 if ((cpus & CPUMASK_SELF) == 0) {
6d2010ae 1326 goto out;
0a7de745 1327 }
2d21ac55 1328 if (action_func != NULL) {
6d2010ae
A
1329 intrs_enabled = ml_set_interrupts_enabled(FALSE);
1330 action_func(arg0, arg1);
2d21ac55
A
1331 ml_set_interrupts_enabled(intrs_enabled);
1332 }
6d2010ae
A
1333 call_self = TRUE;
1334 goto out;
2d21ac55 1335 }
2d21ac55 1336
6d2010ae
A
1337 /*
1338 * Queue the call for each non-local requested cpu.
fe8ab488
A
1339 * This is performed under the topo lock to prevent changes to
1340 * cpus online state and to prevent concurrent rendezvouses --
1341 * although an exception is made if we're calling only the master
1342 * processor since that always remains active. Note: this exception
1343 * is expected for longterm timer nosync cross-calls to the master cpu.
0a7de745 1344 */
fe8ab488
A
1345 mp_disable_preemption();
1346 intrs_enabled = ml_get_interrupts_enabled();
1347 topo_lock = (cpus != cpu_to_cpumask(master_cpu));
1348 if (topo_lock) {
1349 ml_set_interrupts_enabled(FALSE);
1350 (void) mp_safe_spin_lock(&x86_topo_lock);
1351 }
2d21ac55
A
1352 for (cpu = 0; cpu < (cpu_t) real_ncpus; cpu++) {
1353 if (((cpu_to_cpumask(cpu) & cpus) == 0) ||
0a7de745 1354 !cpu_is_running(cpu)) {
2d21ac55 1355 continue;
0a7de745 1356 }
fe8ab488 1357 tsc_spin_start = rdtsc64();
2d21ac55
A
1358 if (cpu == (cpu_t) cpu_number()) {
1359 /*
1360 * We don't IPI ourself and if calling asynchronously,
1361 * we defer our call until we have signalled all others.
1362 */
1363 call_self = TRUE;
1364 if (mode == SYNC && action_func != NULL) {
6d2010ae
A
1365 KERNEL_DEBUG_CONSTANT(
1366 TRACE_MP_CPUS_CALL_LOCAL,
316670eb 1367 VM_KERNEL_UNSLIDE(action_func),
4bd07ac2 1368 VM_KERNEL_UNSLIDE_OR_PERM(arg0), VM_KERNEL_UNSLIDE_OR_PERM(arg1), 0, 0);
6d2010ae 1369 action_func(arg0, arg1);
2d21ac55
A
1370 }
1371 } else {
1372 /*
6d2010ae 1373 * Here to queue a call to cpu and IPI.
2d21ac55 1374 */
0a7de745
A
1375 mp_call_t *callp = NULL;
1376 mp_call_queue_t *cqp = &mp_cpus_call_head[cpu];
1377 boolean_t intrs_inner;
316670eb 1378
0a7de745
A
1379queue_call:
1380 if (callp == NULL) {
316670eb 1381 callp = mp_call_alloc();
0a7de745 1382 }
fe8ab488 1383 intrs_inner = mp_call_head_lock(cqp);
39037602
A
1384 if (callp == NULL) {
1385 mp_call_head_unlock(cqp, intrs_inner);
1386 KERNEL_DEBUG_CONSTANT(
1387 TRACE_MP_CPUS_CALL_NOBUF,
1388 cpu, 0, 0, 0, 0);
1389 if (!intrs_inner) {
1390 /* Sniffing w/o locking */
0a7de745 1391 if (!queue_empty(&cqp->queue)) {
39037602 1392 mp_cpus_call_action();
0a7de745 1393 }
39037602 1394 handle_pending_TLB_flushes();
2d21ac55 1395 }
0a7de745 1396 if (mp_spin_timeout(tsc_spin_start)) {
39037602 1397 panic("mp_cpus_call1() timeout start: 0x%llx, cur: 0x%llx",
0a7de745
A
1398 tsc_spin_start, rdtsc64());
1399 }
39037602 1400 goto queue_call;
6d2010ae 1401 }
39037602 1402 callp->maskp = (mode == NOSYNC) ? NULL : &cpus_responded;
316670eb
A
1403 callp->func = action_func;
1404 callp->arg0 = arg0;
1405 callp->arg1 = arg1;
1406 mp_call_enqueue_locked(cqp, callp);
fe8ab488 1407 cpus_call_count++;
6d2010ae
A
1408 cpus_called |= cpu_to_cpumask(cpu);
1409 i386_signal_cpu(cpu, MP_CALL, ASYNC);
fe8ab488 1410 mp_call_head_unlock(cqp, intrs_inner);
6d2010ae 1411 if (mode == SYNC) {
fe8ab488 1412 mp_cpus_call_wait(intrs_inner, cpus_called, &cpus_responded);
2d21ac55
A
1413 }
1414 }
1415 }
fe8ab488
A
1416 if (topo_lock) {
1417 simple_unlock(&x86_topo_lock);
1418 ml_set_interrupts_enabled(intrs_enabled);
1419 }
2d21ac55 1420
6d2010ae 1421 /* Call locally if mode not SYNC */
0a7de745 1422 if (mode != SYNC && call_self) {
6d2010ae
A
1423 KERNEL_DEBUG_CONSTANT(
1424 TRACE_MP_CPUS_CALL_LOCAL,
4bd07ac2 1425 VM_KERNEL_UNSLIDE(action_func), VM_KERNEL_UNSLIDE_OR_PERM(arg0), VM_KERNEL_UNSLIDE_OR_PERM(arg1), 0, 0);
6d2010ae
A
1426 if (action_func != NULL) {
1427 ml_set_interrupts_enabled(FALSE);
1428 action_func(arg0, arg1);
2d21ac55
A
1429 ml_set_interrupts_enabled(intrs_enabled);
1430 }
2d21ac55 1431 }
2d21ac55 1432
6d2010ae 1433 /* For ASYNC, now wait for all signaled cpus to complete their calls */
0a7de745 1434 if (mode == ASYNC) {
fe8ab488 1435 mp_cpus_call_wait(intrs_enabled, cpus_called, &cpus_responded);
0a7de745 1436 }
6d2010ae 1437
39037602
A
1438 /* Safe to allow pre-emption now */
1439 mp_enable_preemption();
1440
6d2010ae 1441out:
0a7de745 1442 if (call_self) {
fe8ab488
A
1443 cpus_called |= cpu_to_cpumask(cpu);
1444 cpus_call_count++;
1445 }
6d2010ae 1446
0a7de745 1447 if (cpus_calledp) {
6d2010ae 1448 *cpus_calledp = cpus_called;
0a7de745 1449 }
6d2010ae
A
1450
1451 KERNEL_DEBUG_CONSTANT(
1452 TRACE_MP_CPUS_CALL | DBG_FUNC_END,
39037602 1453 cpus_call_count, cpus_called, 0, 0, 0);
2d21ac55 1454
fe8ab488 1455 return (cpu_t) cpus_call_count;
2d21ac55
A
1456}
1457
6d2010ae 1458
2d21ac55 1459static void
39037602 1460mp_broadcast_action(__unused void *null)
2d21ac55 1461{
0a7de745
A
1462 /* call action function */
1463 if (mp_bc_action_func != NULL) {
1464 mp_bc_action_func(mp_bc_func_arg);
1465 }
2d21ac55 1466
0a7de745
A
1467 /* if we're the last one through, wake up the instigator */
1468 if (atomic_decl_and_test(&mp_bc_count, 1)) {
1469 thread_wakeup(((event_t)(uintptr_t) &mp_bc_count));
1470 }
2d21ac55
A
1471}
1472
1473/*
1474 * mp_broadcast() runs a given function on all active cpus.
1475 * The caller blocks until the functions has run on all cpus.
0a7de745 1476 * The caller will also block if there is another pending broadcast.
2d21ac55
A
1477 */
1478void
1479mp_broadcast(
0a7de745
A
1480 void (*action_func)(void *),
1481 void *arg)
1482{
1483 if (!smp_initialized) {
1484 if (action_func != NULL) {
1485 action_func(arg);
1486 }
1487 return;
1488 }
1489
1490 /* obtain broadcast lock */
1491 lck_mtx_lock(&mp_bc_lock);
1492
1493 /* set static function pointers */
1494 mp_bc_action_func = action_func;
1495 mp_bc_func_arg = arg;
1496
1497 assert_wait((event_t)(uintptr_t)&mp_bc_count, THREAD_UNINT);
1498
1499 /*
1500 * signal other processors, which will call mp_broadcast_action()
1501 */
1502 mp_bc_count = real_ncpus; /* assume max possible active */
1503 mp_bc_ncpus = mp_cpus_call(CPUMASK_OTHERS, NOSYNC, *mp_broadcast_action, NULL) + 1;
1504 atomic_decl(&mp_bc_count, real_ncpus - mp_bc_ncpus); /* subtract inactive */
1505
1506 /* call executor function on this cpu */
1507 mp_broadcast_action(NULL);
1508
1509 /* block for other cpus to have run action_func */
1510 if (mp_bc_ncpus > 1) {
1511 thread_block(THREAD_CONTINUE_NULL);
1512 } else {
1513 clear_wait(current_thread(), THREAD_AWAKENED);
1514 }
1515
1516 /* release lock */
1517 lck_mtx_unlock(&mp_bc_lock);
2d21ac55
A
1518}
1519
fe8ab488
A
1520void
1521mp_cpus_kick(cpumask_t cpus)
1522{
0a7de745
A
1523 cpu_t cpu;
1524 boolean_t intrs_enabled = FALSE;
fe8ab488
A
1525
1526 intrs_enabled = ml_set_interrupts_enabled(FALSE);
1527 mp_safe_spin_lock(&x86_topo_lock);
1528
1529 for (cpu = 0; cpu < (cpu_t) real_ncpus; cpu++) {
1530 if ((cpu == (cpu_t) cpu_number())
0a7de745
A
1531 || ((cpu_to_cpumask(cpu) & cpus) == 0)
1532 || !cpu_is_running(cpu)) {
1533 continue;
fe8ab488
A
1534 }
1535
1536 lapic_send_ipi(cpu, LAPIC_VECTOR(KICK));
1537 }
1538
1539 simple_unlock(&x86_topo_lock);
1540 ml_set_interrupts_enabled(intrs_enabled);
1541}
1542
2d21ac55
A
1543void
1544i386_activate_cpu(void)
1545{
0a7de745 1546 cpu_data_t *cdp = current_cpu_datap();
2d21ac55
A
1547
1548 assert(!ml_get_interrupts_enabled());
1549
1550 if (!smp_initialized) {
1551 cdp->cpu_running = TRUE;
1552 return;
1553 }
1554
5ba3f43e 1555 mp_safe_spin_lock(&x86_topo_lock);
2d21ac55 1556 cdp->cpu_running = TRUE;
7e4a7d39 1557 started_cpu();
0a7de745 1558 pmap_tlbi_range(0, ~0ULL, true, 0);
2d21ac55
A
1559 simple_unlock(&x86_topo_lock);
1560}
1561
1562void
1563i386_deactivate_cpu(void)
1564{
0a7de745 1565 cpu_data_t *cdp = current_cpu_datap();
2d21ac55
A
1566
1567 assert(!ml_get_interrupts_enabled());
0a7de745 1568
bd504ef0
A
1569 KERNEL_DEBUG_CONSTANT(
1570 TRACE_MP_CPU_DEACTIVATE | DBG_FUNC_START,
1571 0, 0, 0, 0, 0);
2d21ac55 1572
5ba3f43e 1573 mp_safe_spin_lock(&x86_topo_lock);
2d21ac55
A
1574 cdp->cpu_running = FALSE;
1575 simple_unlock(&x86_topo_lock);
1576
bd504ef0
A
1577 /*
1578 * Move all of this cpu's timers to the master/boot cpu,
1579 * and poke it in case there's a sooner deadline for it to schedule.
1580 */
c910b4d9 1581 timer_queue_shutdown(&cdp->rtclock_timer.queue);
39236c6e 1582 mp_cpus_call(cpu_to_cpumask(master_cpu), ASYNC, timer_queue_expire_local, NULL);
c910b4d9 1583
5ba3f43e
A
1584#if MONOTONIC
1585 mt_cpu_down(cdp);
1586#endif /* MONOTONIC */
1587
2d21ac55 1588 /*
bd504ef0
A
1589 * Open an interrupt window
1590 * and ensure any pending IPI or timer is serviced
2d21ac55 1591 */
bd504ef0
A
1592 mp_disable_preemption();
1593 ml_set_interrupts_enabled(TRUE);
1594
0a7de745 1595 while (cdp->cpu_signals && x86_lcpu()->rtcDeadline != EndOfAllTime) {
bd504ef0 1596 cpu_pause();
0a7de745 1597 }
bd504ef0
A
1598 /*
1599 * Ensure there's no remaining timer deadline set
1600 * - AICPM may have left one active.
1601 */
1602 setPop(0);
1603
1604 ml_set_interrupts_enabled(FALSE);
1605 mp_enable_preemption();
1606
1607 KERNEL_DEBUG_CONSTANT(
1608 TRACE_MP_CPU_DEACTIVATE | DBG_FUNC_END,
1609 0, 0, 0, 0, 0);
2d21ac55
A
1610}
1611
0a7de745 1612int pmsafe_debug = 1;
2d21ac55 1613
0a7de745
A
1614#if MACH_KDP
1615volatile boolean_t mp_kdp_trap = FALSE;
1616volatile boolean_t mp_kdp_is_NMI = FALSE;
1617volatile unsigned long mp_kdp_ncpus;
1618boolean_t mp_kdp_state;
91447636 1619
55e303ae
A
1620
1621void
5ba3f43e 1622mp_kdp_enter(boolean_t proceed_on_failure)
55e303ae 1623{
0a7de745
A
1624 unsigned int cpu;
1625 unsigned int ncpus = 0;
1626 unsigned int my_cpu;
1627 uint64_t tsc_timeout;
55e303ae
A
1628
1629 DBG("mp_kdp_enter()\n");
1630
1631 /*
1632 * Here to enter the debugger.
1633 * In case of races, only one cpu is allowed to enter kdp after
1634 * stopping others.
1635 */
91447636 1636 mp_kdp_state = ml_set_interrupts_enabled(FALSE);
060df5ea 1637 my_cpu = cpu_number();
7ddcb079
A
1638
1639 if (my_cpu == (unsigned) debugger_cpu) {
1640 kprintf("\n\nRECURSIVE DEBUGGER ENTRY DETECTED\n\n");
1641 kdp_reset();
1642 return;
1643 }
1644
5ba3f43e
A
1645 uint64_t start_time = cpu_datap(my_cpu)->debugger_entry_time = mach_absolute_time();
1646 int locked = 0;
1647 while (!locked || mp_kdp_trap) {
1648 if (locked) {
1649 simple_unlock(&x86_topo_lock);
1650 }
1651 if (proceed_on_failure) {
1652 if (mach_absolute_time() - start_time > 500000000ll) {
d9a64523 1653 paniclog_append_noflush("mp_kdp_enter() can't get x86_topo_lock! Debugging anyway! #YOLO\n");
5ba3f43e
A
1654 break;
1655 }
0a7de745 1656 locked = simple_lock_try(&x86_topo_lock, LCK_GRP_NULL);
5ba3f43e
A
1657 if (!locked) {
1658 cpu_pause();
1659 }
1660 } else {
1661 mp_safe_spin_lock(&x86_topo_lock);
1662 locked = TRUE;
1663 }
2d21ac55 1664
5ba3f43e
A
1665 if (locked && mp_kdp_trap) {
1666 simple_unlock(&x86_topo_lock);
1667 DBG("mp_kdp_enter() race lost\n");
b0d623f7 1668#if MACH_KDP
5ba3f43e 1669 mp_kdp_wait(TRUE, FALSE);
b0d623f7 1670#endif
5ba3f43e
A
1671 locked = FALSE;
1672 }
55e303ae 1673 }
5ba3f43e 1674
0a7de745 1675 if (pmsafe_debug && !kdp_snapshot) {
5ba3f43e 1676 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_SAFE);
0a7de745 1677 }
5ba3f43e 1678
593a1d5f 1679 debugger_cpu = my_cpu;
060df5ea 1680 ncpus = 1;
5ba3f43e 1681 atomic_incl((volatile long *)&mp_kdp_ncpus, 1);
55e303ae 1682 mp_kdp_trap = TRUE;
060df5ea 1683 debugger_entry_time = cpu_datap(my_cpu)->debugger_entry_time;
55e303ae 1684
0c530ab8
A
1685 /*
1686 * Deliver a nudge to other cpus, counting how many
1687 */
55e303ae 1688 DBG("mp_kdp_enter() signaling other processors\n");
2d21ac55 1689 if (force_immediate_debugger_NMI == FALSE) {
060df5ea 1690 for (cpu = 0; cpu < real_ncpus; cpu++) {
0a7de745 1691 if (cpu == my_cpu || !cpu_is_running(cpu)) {
2d21ac55 1692 continue;
0a7de745 1693 }
2d21ac55
A
1694 ncpus++;
1695 i386_signal_cpu(cpu, MP_KDP, ASYNC);
1696 }
1697 /*
1698 * Wait other processors to synchronize
1699 */
1700 DBG("mp_kdp_enter() waiting for (%d) processors to suspend\n", ncpus);
0c530ab8 1701
2d21ac55
A
1702 /*
1703 * This timeout is rather arbitrary; we don't want to NMI
1704 * processors that are executing at potentially
1705 * "unsafe-to-interrupt" points such as the trampolines,
1706 * but neither do we want to lose state by waiting too long.
1707 */
39037602 1708 tsc_timeout = rdtsc64() + (LockTimeOutTSC);
0c530ab8 1709
2d21ac55
A
1710 while (mp_kdp_ncpus != ncpus && rdtsc64() < tsc_timeout) {
1711 /*
1712 * A TLB shootdown request may be pending--this would
1713 * result in the requesting processor waiting in
1714 * PMAP_UPDATE_TLBS() until this processor deals with it.
1715 * Process it, so it can now enter mp_kdp_wait()
1716 */
1717 handle_pending_TLB_flushes();
1718 cpu_pause();
1719 }
1720 /* If we've timed out, and some processor(s) are still unresponsive,
5c9f4661
A
1721 * interrupt them with an NMI via the local APIC, iff a panic is
1722 * in progress.
0c530ab8 1723 */
5c9f4661
A
1724 if (panic_active()) {
1725 NMIPI_enable(TRUE);
1726 }
2d21ac55 1727 if (mp_kdp_ncpus != ncpus) {
d9a64523 1728 unsigned int wait_cycles = 0;
0a7de745 1729 if (proceed_on_failure) {
d9a64523 1730 paniclog_append_noflush("mp_kdp_enter() timed-out on cpu %d, NMI-ing\n", my_cpu);
0a7de745 1731 } else {
d9a64523 1732 DBG("mp_kdp_enter() timed-out on cpu %d, NMI-ing\n", my_cpu);
0a7de745 1733 }
2d21ac55 1734 for (cpu = 0; cpu < real_ncpus; cpu++) {
0a7de745 1735 if (cpu == my_cpu || !cpu_is_running(cpu)) {
2d21ac55 1736 continue;
0a7de745 1737 }
a39ff7e2 1738 if (cpu_signal_pending(cpu, MP_KDP)) {
d9a64523 1739 cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE;
2d21ac55 1740 cpu_NMI_interrupt(cpu);
a39ff7e2 1741 }
2d21ac55 1742 }
39037602
A
1743 /* Wait again for the same timeout */
1744 tsc_timeout = rdtsc64() + (LockTimeOutTSC);
1745 while (mp_kdp_ncpus != ncpus && rdtsc64() < tsc_timeout) {
1746 handle_pending_TLB_flushes();
1747 cpu_pause();
d9a64523 1748 ++wait_cycles;
39037602
A
1749 }
1750 if (mp_kdp_ncpus != ncpus) {
d9a64523
A
1751 paniclog_append_noflush("mp_kdp_enter() NMI pending on cpus:");
1752 for (cpu = 0; cpu < real_ncpus; cpu++) {
0a7de745 1753 if (cpu_is_running(cpu) && !cpu_datap(cpu)->cpu_NMI_acknowledged) {
d9a64523 1754 paniclog_append_noflush(" %d", cpu);
0a7de745 1755 }
d9a64523
A
1756 }
1757 paniclog_append_noflush("\n");
1758 if (proceed_on_failure) {
1759 paniclog_append_noflush("mp_kdp_enter() timed-out during %s wait after NMI;"
1760 "expected %u acks but received %lu after %u loops in %llu ticks\n",
0a7de745 1761 (locked ? "locked" : "unlocked"), ncpus, mp_kdp_ncpus, wait_cycles, LockTimeOutTSC);
d9a64523
A
1762 } else {
1763 panic("mp_kdp_enter() timed-out during %s wait after NMI;"
1764 "expected %u acks but received %lu after %u loops in %llu ticks",
0a7de745 1765 (locked ? "locked" : "unlocked"), ncpus, mp_kdp_ncpus, wait_cycles, LockTimeOutTSC);
d9a64523 1766 }
39037602 1767 }
2d21ac55 1768 }
0a7de745 1769 } else {
0c530ab8 1770 for (cpu = 0; cpu < real_ncpus; cpu++) {
0a7de745 1771 if (cpu == my_cpu || !cpu_is_running(cpu)) {
0c530ab8 1772 continue;
0a7de745 1773 }
2d21ac55 1774 cpu_NMI_interrupt(cpu);
0c530ab8 1775 }
0a7de745 1776 }
0c530ab8 1777
5ba3f43e
A
1778 if (locked) {
1779 simple_unlock(&x86_topo_lock);
1780 }
1781
bd504ef0 1782 DBG("mp_kdp_enter() %d processors done %s\n",
6d2010ae 1783 (int)mp_kdp_ncpus, (mp_kdp_ncpus == ncpus) ? "OK" : "timed out");
0a7de745 1784
91447636 1785 postcode(MP_KDP_ENTER);
55e303ae
A
1786}
1787
d9a64523
A
1788boolean_t
1789mp_kdp_all_cpus_halted()
1790{
1791 unsigned int ncpus = 0, cpu = 0, my_cpu = 0;
1792
1793 my_cpu = cpu_number();
1794 ncpus = 1; /* current CPU */
1795 for (cpu = 0; cpu < real_ncpus; cpu++) {
0a7de745 1796 if (cpu == my_cpu || !cpu_is_running(cpu)) {
d9a64523 1797 continue;
0a7de745 1798 }
d9a64523
A
1799 ncpus++;
1800 }
1801
0a7de745 1802 return mp_kdp_ncpus == ncpus;
d9a64523
A
1803}
1804
0c530ab8
A
1805static boolean_t
1806cpu_signal_pending(int cpu, mp_event_t event)
1807{
0a7de745 1808 volatile int *signals = &cpu_datap(cpu)->cpu_signals;
0c530ab8
A
1809 boolean_t retval = FALSE;
1810
0a7de745 1811 if (i_bit(event, signals)) {
0c530ab8 1812 retval = TRUE;
0a7de745 1813 }
0c530ab8
A
1814 return retval;
1815}
b0d623f7 1816
0a7de745
A
1817long
1818kdp_x86_xcpu_invoke(const uint16_t lcpu, kdp_x86_xcpu_func_t func,
1819 void *arg0, void *arg1)
b0d623f7 1820{
0a7de745 1821 if (lcpu > (real_ncpus - 1)) {
b0d623f7 1822 return -1;
0a7de745 1823 }
b0d623f7 1824
0a7de745 1825 if (func == NULL) {
b0d623f7 1826 return -1;
0a7de745 1827 }
b0d623f7
A
1828
1829 kdp_xcpu_call_func.func = func;
0a7de745 1830 kdp_xcpu_call_func.ret = -1;
b0d623f7
A
1831 kdp_xcpu_call_func.arg0 = arg0;
1832 kdp_xcpu_call_func.arg1 = arg1;
1833 kdp_xcpu_call_func.cpu = lcpu;
1834 DBG("Invoking function %p on CPU %d\n", func, (int32_t)lcpu);
0a7de745 1835 while (kdp_xcpu_call_func.cpu != KDP_XCPU_NONE) {
b0d623f7 1836 cpu_pause();
0a7de745
A
1837 }
1838 return kdp_xcpu_call_func.ret;
b0d623f7
A
1839}
1840
1841static void
1842kdp_x86_xcpu_poll(void)
1843{
1844 if ((uint16_t)cpu_number() == kdp_xcpu_call_func.cpu) {
0a7de745 1845 kdp_xcpu_call_func.ret =
b0d623f7 1846 kdp_xcpu_call_func.func(kdp_xcpu_call_func.arg0,
0a7de745
A
1847 kdp_xcpu_call_func.arg1,
1848 cpu_number());
b0d623f7
A
1849 kdp_xcpu_call_func.cpu = KDP_XCPU_NONE;
1850 }
1851}
0c530ab8 1852
55e303ae 1853static void
b0d623f7 1854mp_kdp_wait(boolean_t flush, boolean_t isNMI)
55e303ae 1855{
6601e61a 1856 DBG("mp_kdp_wait()\n");
813fb2f6 1857
bd504ef0 1858 current_cpu_datap()->debugger_ipi_time = mach_absolute_time();
b0d623f7 1859#if CONFIG_MCA
2d21ac55
A
1860 /* If we've trapped due to a machine-check, save MCA registers */
1861 mca_check_save();
b0d623f7 1862#endif
2d21ac55 1863
2d21ac55 1864 atomic_incl((volatile long *)&mp_kdp_ncpus, 1);
b0d623f7 1865 while (mp_kdp_trap || (isNMI == TRUE)) {
0a7de745 1866 /*
2d21ac55
A
1867 * A TLB shootdown request may be pending--this would result
1868 * in the requesting processor waiting in PMAP_UPDATE_TLBS()
1869 * until this processor handles it.
0c530ab8
A
1870 * Process it, so it can now enter mp_kdp_wait()
1871 */
0a7de745 1872 if (flush) {
2d21ac55 1873 handle_pending_TLB_flushes();
0a7de745 1874 }
b0d623f7
A
1875
1876 kdp_x86_xcpu_poll();
55e303ae
A
1877 cpu_pause();
1878 }
2d21ac55 1879
0c530ab8 1880 atomic_decl((volatile long *)&mp_kdp_ncpus, 1);
55e303ae
A
1881 DBG("mp_kdp_wait() done\n");
1882}
1883
1884void
1885mp_kdp_exit(void)
1886{
1887 DBG("mp_kdp_exit()\n");
593a1d5f 1888 debugger_cpu = -1;
0c530ab8 1889 atomic_decl((volatile long *)&mp_kdp_ncpus, 1);
b0d623f7
A
1890
1891 debugger_exit_time = mach_absolute_time();
1892
55e303ae 1893 mp_kdp_trap = FALSE;
39236c6e 1894 mfence();
55e303ae
A
1895
1896 /* Wait other processors to stop spinning. XXX needs timeout */
1897 DBG("mp_kdp_exit() waiting for processors to resume\n");
0c530ab8 1898 while (mp_kdp_ncpus > 0) {
0a7de745 1899 /*
0c530ab8
A
1900 * a TLB shootdown request may be pending... this would result in the requesting
1901 * processor waiting in PMAP_UPDATE_TLBS() until this processor deals with it.
1902 * Process it, so it can now enter mp_kdp_wait()
1903 */
0a7de745 1904 handle_pending_TLB_flushes();
0c530ab8 1905
55e303ae
A
1906 cpu_pause();
1907 }
2d21ac55 1908
0a7de745
A
1909 if (pmsafe_debug && !kdp_snapshot) {
1910 pmSafeMode(&current_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL);
1911 }
2d21ac55 1912
6d2010ae
A
1913 debugger_exit_time = mach_absolute_time();
1914
55e303ae 1915 DBG("mp_kdp_exit() done\n");
91447636 1916 (void) ml_set_interrupts_enabled(mp_kdp_state);
5ba3f43e 1917 postcode(MP_KDP_EXIT);
39037602
A
1918}
1919
0a7de745 1920#endif /* MACH_KDP */
55e303ae 1921
b0d623f7 1922boolean_t
0a7de745
A
1923mp_recent_debugger_activity(void)
1924{
060df5ea 1925 uint64_t abstime = mach_absolute_time();
0a7de745
A
1926 return ((abstime - debugger_entry_time) < LastDebuggerEntryAllowance) ||
1927 ((abstime - debugger_exit_time) < LastDebuggerEntryAllowance);
b0d623f7
A
1928}
1929
55e303ae
A
1930/*ARGSUSED*/
1931void
1932init_ast_check(
0a7de745 1933 __unused processor_t processor)
55e303ae
A
1934{
1935}
1936
1937void
1938cause_ast_check(
0a7de745 1939 processor_t processor)
55e303ae 1940{
0a7de745 1941 int cpu = processor->cpu_id;
55e303ae
A
1942
1943 if (cpu != cpu_number()) {
1944 i386_signal_cpu(cpu, MP_AST, ASYNC);
6d2010ae 1945 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_REMOTE_AST), cpu, 1, 0, 0, 0);
55e303ae
A
1946 }
1947}
1948
593a1d5f
A
1949void
1950slave_machine_init(void *param)
91447636
A
1951{
1952 /*
0a7de745 1953 * Here in process context, but with interrupts disabled.
91447636
A
1954 */
1955 DBG("slave_machine_init() CPU%d\n", get_cpu_number());
1956
593a1d5f
A
1957 if (param == FULL_SLAVE_INIT) {
1958 /*
1959 * Cold start
1960 */
1961 clock_init();
593a1d5f 1962 }
0a7de745 1963 cpu_machine_init(); /* Interrupts enabled hereafter */
55e303ae
A
1964}
1965
b0d623f7 1966#undef cpu_number
0a7de745
A
1967int
1968cpu_number(void)
55e303ae
A
1969{
1970 return get_cpu_number();
1971}
1972
6d2010ae
A
1973static void
1974cpu_prewarm_init()
1975{
1976 int i;
1977
1978 simple_lock_init(&cpu_warm_lock, 0);
1979 queue_init(&cpu_warm_call_list);
1980 for (i = 0; i < NUM_CPU_WARM_CALLS; i++) {
1981 enqueue_head(&cpu_warm_call_list, (queue_entry_t)&cpu_warm_call_arr[i]);
1982 }
1983}
1984
1985static timer_call_t
1986grab_warm_timer_call()
1987{
1988 spl_t x;
1989 timer_call_t call = NULL;
1990
1991 x = splsched();
0a7de745 1992 simple_lock(&cpu_warm_lock, LCK_GRP_NULL);
6d2010ae
A
1993 if (!queue_empty(&cpu_warm_call_list)) {
1994 call = (timer_call_t) dequeue_head(&cpu_warm_call_list);
1995 }
1996 simple_unlock(&cpu_warm_lock);
1997 splx(x);
1998
1999 return call;
2000}
2001
2002static void
2003free_warm_timer_call(timer_call_t call)
2004{
2005 spl_t x;
2006
2007 x = splsched();
0a7de745 2008 simple_lock(&cpu_warm_lock, LCK_GRP_NULL);
6d2010ae
A
2009 enqueue_head(&cpu_warm_call_list, (queue_entry_t)call);
2010 simple_unlock(&cpu_warm_lock);
2011 splx(x);
2012}
2013
2014/*
2015 * Runs in timer call context (interrupts disabled).
2016 */
2017static void
2018cpu_warm_timer_call_func(
0a7de745
A
2019 call_entry_param_t p0,
2020 __unused call_entry_param_t p1)
6d2010ae
A
2021{
2022 free_warm_timer_call((timer_call_t)p0);
2023 return;
2024}
2025
2026/*
2027 * Runs with interrupts disabled on the CPU we wish to warm (i.e. CPU 0).
2028 */
2029static void
2030_cpu_warm_setup(
0a7de745 2031 void *arg)
6d2010ae
A
2032{
2033 cpu_warm_data_t cwdp = (cpu_warm_data_t)arg;
2034
39236c6e 2035 timer_call_enter(cwdp->cwd_call, cwdp->cwd_deadline, TIMER_CALL_SYS_CRITICAL | TIMER_CALL_LOCAL);
6d2010ae
A
2036 cwdp->cwd_result = 0;
2037
2038 return;
2039}
2040
2041/*
2042 * Not safe to call with interrupts disabled.
2043 */
2044kern_return_t
2045ml_interrupt_prewarm(
0a7de745 2046 uint64_t deadline)
6d2010ae
A
2047{
2048 struct cpu_warm_data cwd;
2049 timer_call_t call;
2050 cpu_t ct;
2051
2052 if (ml_get_interrupts_enabled() == FALSE) {
2053 panic("%s: Interrupts disabled?\n", __FUNCTION__);
2054 }
2055
0a7de745
A
2056 /*
2057 * If the platform doesn't need our help, say that we succeeded.
6d2010ae
A
2058 */
2059 if (!ml_get_interrupt_prewake_applicable()) {
2060 return KERN_SUCCESS;
2061 }
2062
2063 /*
2064 * Grab a timer call to use.
2065 */
2066 call = grab_warm_timer_call();
2067 if (call == NULL) {
2068 return KERN_RESOURCE_SHORTAGE;
2069 }
2070
2071 timer_call_setup(call, cpu_warm_timer_call_func, call);
2072 cwd.cwd_call = call;
2073 cwd.cwd_deadline = deadline;
2074 cwd.cwd_result = 0;
2075
2076 /*
2077 * For now, non-local interrupts happen on the master processor.
2078 */
2079 ct = mp_cpus_call(cpu_to_cpumask(master_cpu), SYNC, _cpu_warm_setup, &cwd);
2080 if (ct == 0) {
2081 free_warm_timer_call(call);
2082 return KERN_FAILURE;
2083 } else {
2084 return cwd.cwd_result;
2085 }
2086}
39037602
A
2087
2088#if DEBUG || DEVELOPMENT
2089void
2090kernel_spin(uint64_t spin_ns)
2091{
0a7de745
A
2092 boolean_t istate;
2093 uint64_t spin_abs;
2094 uint64_t deadline;
2095 cpu_data_t *cdp;
39037602
A
2096
2097 kprintf("kernel_spin(%llu) spinning uninterruptibly\n", spin_ns);
2098 istate = ml_set_interrupts_enabled(FALSE);
5ba3f43e 2099 cdp = current_cpu_datap();
39037602 2100 nanoseconds_to_absolutetime(spin_ns, &spin_abs);
5ba3f43e
A
2101
2102 /* Fake interrupt handler entry for testing mp_interrupt_watchdog() */
2103 cdp->cpu_int_event_time = mach_absolute_time();
2104 cdp->cpu_int_state = (void *) USER_STATE(current_thread());
2105
39037602 2106 deadline = mach_absolute_time() + spin_ns;
0a7de745 2107 while (mach_absolute_time() < deadline) {
39037602 2108 cpu_pause();
0a7de745 2109 }
5ba3f43e
A
2110
2111 cdp->cpu_int_event_time = 0;
2112 cdp->cpu_int_state = NULL;
2113
39037602
A
2114 ml_set_interrupts_enabled(istate);
2115 kprintf("kernel_spin() continuing\n");
2116}
5ba3f43e
A
2117
2118/*
2119 * Called from the scheduler's maintenance thread,
2120 * scan running processors for long-running ISRs and:
2121 * - panic if longer than LockTimeOut, or
2122 * - log if more than a quantum.
2123 */
2124void
2125mp_interrupt_watchdog(void)
2126{
0a7de745
A
2127 cpu_t cpu;
2128 boolean_t intrs_enabled = FALSE;
2129 uint16_t cpu_int_num;
2130 uint64_t cpu_int_event_time;
2131 uint64_t cpu_rip;
2132 uint64_t cpu_int_duration;
2133 uint64_t now;
2134 x86_saved_state_t *cpu_int_state;
2135
2136 if (__improbable(!mp_interrupt_watchdog_enabled)) {
5ba3f43e 2137 return;
0a7de745 2138 }
5ba3f43e
A
2139
2140 intrs_enabled = ml_set_interrupts_enabled(FALSE);
2141 now = mach_absolute_time();
2142 /*
2143 * While timeouts are not suspended,
2144 * check all other processors for long outstanding interrupt handling.
2145 */
2146 for (cpu = 0;
0a7de745
A
2147 cpu < (cpu_t) real_ncpus && !machine_timeout_suspended();
2148 cpu++) {
5ba3f43e 2149 if ((cpu == (cpu_t) cpu_number()) ||
0a7de745 2150 (!cpu_is_running(cpu))) {
5ba3f43e 2151 continue;
0a7de745 2152 }
5ba3f43e 2153 cpu_int_event_time = cpu_datap(cpu)->cpu_int_event_time;
0a7de745 2154 if (cpu_int_event_time == 0) {
5ba3f43e 2155 continue;
0a7de745
A
2156 }
2157 if (__improbable(now < cpu_int_event_time)) {
2158 continue; /* skip due to inter-processor skew */
2159 }
5ba3f43e 2160 cpu_int_state = cpu_datap(cpu)->cpu_int_state;
0a7de745 2161 if (__improbable(cpu_int_state == NULL)) {
5ba3f43e
A
2162 /* The interrupt may have been dismissed */
2163 continue;
0a7de745 2164 }
5ba3f43e
A
2165
2166 /* Here with a cpu handling an interrupt */
2167
2168 cpu_int_duration = now - cpu_int_event_time;
2169 if (__improbable(cpu_int_duration > LockTimeOut)) {
2170 cpu_int_num = saved_state64(cpu_int_state)->isf.trapno;
2171 cpu_rip = saved_state64(cpu_int_state)->isf.rip;
2172 vector_timed_out = cpu_int_num;
2173 NMIPI_panic(cpu_to_cpumask(cpu), INTERRUPT_WATCHDOG);
2174 panic("Interrupt watchdog, "
0a7de745
A
2175 "cpu: %d interrupt: 0x%x time: %llu..%llu state: %p RIP: 0x%llx",
2176 cpu, cpu_int_num, cpu_int_event_time, now, cpu_int_state, cpu_rip);
5ba3f43e
A
2177 /* NOT REACHED */
2178 } else if (__improbable(cpu_int_duration > (uint64_t) std_quantum)) {
2179 mp_interrupt_watchdog_events++;
2180 cpu_int_num = saved_state64(cpu_int_state)->isf.trapno;
2181 cpu_rip = saved_state64(cpu_int_state)->isf.rip;
2182 ml_set_interrupts_enabled(intrs_enabled);
2183 printf("Interrupt watchdog, "
0a7de745
A
2184 "cpu: %d interrupt: 0x%x time: %llu..%llu RIP: 0x%llx\n",
2185 cpu, cpu_int_num, cpu_int_event_time, now, cpu_rip);
5ba3f43e
A
2186 return;
2187 }
2188 }
2189
2190 ml_set_interrupts_enabled(intrs_enabled);
2191}
39037602 2192#endif