local_apic.c revision 204641
1/*-
2 * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3 * Copyright (c) 1996, by Steve Passe
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. The name of the developer may NOT be used to endorse or promote products
12 *    derived from this software without specific prior written permission.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/*
31 * Local APIC support on Pentium and later processors.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/i386/i386/local_apic.c 204641 2010-03-03 17:13:29Z attilio $");
36
37#include "opt_atpic.h"
38#include "opt_hwpmc_hooks.h"
39#include "opt_kdtrace.h"
40
41#include "opt_ddb.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/bus.h>
46#include <sys/kernel.h>
47#include <sys/lock.h>
48#include <sys/mutex.h>
49#include <sys/pcpu.h>
50#include <sys/proc.h>
51#include <sys/sched.h>
52#include <sys/smp.h>
53
54#include <vm/vm.h>
55#include <vm/pmap.h>
56
57#include <machine/apicreg.h>
58#include <machine/cpu.h>
59#include <machine/cputypes.h>
60#include <machine/frame.h>
61#include <machine/intr_machdep.h>
62#include <machine/apicvar.h>
63#include <machine/md_var.h>
64#include <machine/smp.h>
65#include <machine/specialreg.h>
66
67#ifdef DDB
68#include <sys/interrupt.h>
69#include <ddb/ddb.h>
70#endif
71
72#ifdef KDTRACE_HOOKS
73#include <sys/dtrace_bsd.h>
74cyclic_clock_func_t	lapic_cyclic_clock_func[MAXCPU];
75#endif
76
77/* Sanity checks on IDT vectors. */
78CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
79CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
80CTASSERT(APIC_LOCAL_INTS == 240);
81CTASSERT(IPI_STOP < APIC_SPURIOUS_INT);
82
83/* Magic IRQ values for the timer and syscalls. */
84#define	IRQ_TIMER	(NUM_IO_INTS + 1)
85#define	IRQ_SYSCALL	(NUM_IO_INTS + 2)
86
87/*
88 * Support for local APICs.  Local APICs manage interrupts on each
89 * individual processor as opposed to I/O APICs which receive interrupts
90 * from I/O devices and then forward them on to the local APICs.
91 *
92 * Local APICs can also send interrupts to each other thus providing the
93 * mechanism for IPIs.
94 */
95
96struct lvt {
97	u_int lvt_edgetrigger:1;
98	u_int lvt_activehi:1;
99	u_int lvt_masked:1;
100	u_int lvt_active:1;
101	u_int lvt_mode:16;
102	u_int lvt_vector:8;
103};
104
105struct lapic {
106	struct lvt la_lvts[LVT_MAX + 1];
107	u_int la_id:8;
108	u_int la_cluster:4;
109	u_int la_cluster_id:2;
110	u_int la_present:1;
111	u_long *la_timer_count;
112	u_long la_hard_ticks;
113	u_long la_stat_ticks;
114	u_long la_prof_ticks;
115	/* Include IDT_SYSCALL to make indexing easier. */
116	int la_ioint_irqs[APIC_NUM_IOINTS + 1];
117} static lapics[MAX_APIC_ID + 1];
118
119/* XXX: should thermal be an NMI? */
120
121/* Global defaults for local APIC LVT entries. */
122static struct lvt lvts[LVT_MAX + 1] = {
123	{ 1, 1, 1, 1, APIC_LVT_DM_EXTINT, 0 },	/* LINT0: masked ExtINT */
124	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* LINT1: NMI */
125	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT },	/* Timer */
126	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
127	{ 1, 1, 1, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
128	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT },	/* Thermal */
129};
130
131static inthand_t *ioint_handlers[] = {
132	NULL,			/* 0 - 31 */
133	IDTVEC(apic_isr1),	/* 32 - 63 */
134	IDTVEC(apic_isr2),	/* 64 - 95 */
135	IDTVEC(apic_isr3),	/* 96 - 127 */
136	IDTVEC(apic_isr4),	/* 128 - 159 */
137	IDTVEC(apic_isr5),	/* 160 - 191 */
138	IDTVEC(apic_isr6),	/* 192 - 223 */
139	IDTVEC(apic_isr7),	/* 224 - 255 */
140};
141
142
143static u_int32_t lapic_timer_divisors[] = {
144	APIC_TDCR_1, APIC_TDCR_2, APIC_TDCR_4, APIC_TDCR_8, APIC_TDCR_16,
145	APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128
146};
147
148extern inthand_t IDTVEC(rsvd);
149
150volatile lapic_t *lapic;
151vm_paddr_t lapic_paddr;
152static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
153static enum lapic_clock clockcoverage;
154
155static void	lapic_enable(void);
156static void	lapic_resume(struct pic *pic);
157static void	lapic_timer_enable_intr(void);
158static void	lapic_timer_oneshot(u_int count);
159static void	lapic_timer_periodic(u_int count);
160static void	lapic_timer_set_divisor(u_int divisor);
161static uint32_t	lvt_mode(struct lapic *la, u_int pin, uint32_t value);
162
163struct pic lapic_pic = { .pic_resume = lapic_resume };
164
165static uint32_t
166lvt_mode(struct lapic *la, u_int pin, uint32_t value)
167{
168	struct lvt *lvt;
169
170	KASSERT(pin <= LVT_MAX, ("%s: pin %u out of range", __func__, pin));
171	if (la->la_lvts[pin].lvt_active)
172		lvt = &la->la_lvts[pin];
173	else
174		lvt = &lvts[pin];
175
176	value &= ~(APIC_LVT_M | APIC_LVT_TM | APIC_LVT_IIPP | APIC_LVT_DM |
177	    APIC_LVT_VECTOR);
178	if (lvt->lvt_edgetrigger == 0)
179		value |= APIC_LVT_TM;
180	if (lvt->lvt_activehi == 0)
181		value |= APIC_LVT_IIPP_INTALO;
182	if (lvt->lvt_masked)
183		value |= APIC_LVT_M;
184	value |= lvt->lvt_mode;
185	switch (lvt->lvt_mode) {
186	case APIC_LVT_DM_NMI:
187	case APIC_LVT_DM_SMI:
188	case APIC_LVT_DM_INIT:
189	case APIC_LVT_DM_EXTINT:
190		if (!lvt->lvt_edgetrigger) {
191			printf("lapic%u: Forcing LINT%u to edge trigger\n",
192			    la->la_id, pin);
193			value |= APIC_LVT_TM;
194		}
195		/* Use a vector of 0. */
196		break;
197	case APIC_LVT_DM_FIXED:
198		value |= lvt->lvt_vector;
199		break;
200	default:
201		panic("bad APIC LVT delivery mode: %#x\n", value);
202	}
203	return (value);
204}
205
206/*
207 * Map the local APIC and setup necessary interrupt vectors.
208 */
209void
210lapic_init(vm_paddr_t addr)
211{
212
213	/* Map the local APIC and setup the spurious interrupt handler. */
214	KASSERT(trunc_page(addr) == addr,
215	    ("local APIC not aligned on a page boundary"));
216	lapic = pmap_mapdev(addr, sizeof(lapic_t));
217	lapic_paddr = addr;
218	setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_SYS386IGT, SEL_KPL,
219	    GSEL(GCODE_SEL, SEL_KPL));
220
221	/* Perform basic initialization of the BSP's local APIC. */
222	lapic_enable();
223
224	/* Set BSP's per-CPU local APIC ID. */
225	PCPU_SET(apic_id, lapic_id());
226
227	/* Local APIC timer interrupt. */
228	setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYS386IGT, SEL_KPL,
229	    GSEL(GCODE_SEL, SEL_KPL));
230
231	/* XXX: error/thermal interrupts */
232}
233
234/*
235 * Create a local APIC instance.
236 */
237void
238lapic_create(u_int apic_id, int boot_cpu)
239{
240	int i;
241
242	if (apic_id > MAX_APIC_ID) {
243		printf("APIC: Ignoring local APIC with ID %d\n", apic_id);
244		if (boot_cpu)
245			panic("Can't ignore BSP");
246		return;
247	}
248	KASSERT(!lapics[apic_id].la_present, ("duplicate local APIC %u",
249	    apic_id));
250
251	/*
252	 * Assume no local LVT overrides and a cluster of 0 and
253	 * intra-cluster ID of 0.
254	 */
255	lapics[apic_id].la_present = 1;
256	lapics[apic_id].la_id = apic_id;
257	for (i = 0; i < LVT_MAX; i++) {
258		lapics[apic_id].la_lvts[i] = lvts[i];
259		lapics[apic_id].la_lvts[i].lvt_active = 0;
260	}
261	for (i = 0; i <= APIC_NUM_IOINTS; i++)
262	    lapics[apic_id].la_ioint_irqs[i] = -1;
263	lapics[apic_id].la_ioint_irqs[IDT_SYSCALL - APIC_IO_INTS] = IRQ_SYSCALL;
264	lapics[apic_id].la_ioint_irqs[APIC_TIMER_INT - APIC_IO_INTS] =
265	    IRQ_TIMER;
266
267#ifdef SMP
268	cpu_add(apic_id, boot_cpu);
269#endif
270}
271
272/*
273 * Dump contents of local APIC registers
274 */
275void
276lapic_dump(const char* str)
277{
278
279	printf("cpu%d %s:\n", PCPU_GET(cpuid), str);
280	printf("     ID: 0x%08x   VER: 0x%08x LDR: 0x%08x DFR: 0x%08x\n",
281	    lapic->id, lapic->version, lapic->ldr, lapic->dfr);
282	printf("  lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n",
283	    lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr);
284	printf("  timer: 0x%08x therm: 0x%08x err: 0x%08x pcm: 0x%08x\n",
285	    lapic->lvt_timer, lapic->lvt_thermal, lapic->lvt_error,
286	    lapic->lvt_pcint);
287}
288
289void
290lapic_setup(int boot)
291{
292	struct lapic *la;
293	u_int32_t maxlvt;
294	register_t eflags;
295	char buf[MAXCOMLEN + 1];
296
297	la = &lapics[lapic_id()];
298	KASSERT(la->la_present, ("missing APIC structure"));
299	eflags = intr_disable();
300	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
301
302	/* Initialize the TPR to allow all interrupts. */
303	lapic_set_tpr(0);
304
305	/* Setup spurious vector and enable the local APIC. */
306	lapic_enable();
307
308	/* Program LINT[01] LVT entries. */
309	lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0);
310	lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1);
311
312	/* Program the PMC LVT entry if present. */
313	if (maxlvt >= LVT_PMC)
314		lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
315
316	/* Program timer LVT and setup handler. */
317	lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
318	if (boot) {
319		snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
320		intrcnt_add(buf, &la->la_timer_count);
321	}
322
323	/* We don't setup the timer during boot on the BSP until later. */
324	if (!(boot && PCPU_GET(cpuid) == 0) && lapic_timer_hz != 0) {
325		KASSERT(lapic_timer_period != 0, ("lapic%u: zero divisor",
326		    lapic_id()));
327		lapic_timer_set_divisor(lapic_timer_divisor);
328		lapic_timer_periodic(lapic_timer_period);
329		lapic_timer_enable_intr();
330	}
331
332	/* XXX: Error and thermal LVTs */
333
334	intr_restore(eflags);
335}
336
337void
338lapic_reenable_pmc(void)
339{
340#ifdef HWPMC_HOOKS
341	uint32_t value;
342
343	value =  lapic->lvt_pcint;
344	value &= ~APIC_LVT_M;
345	lapic->lvt_pcint = value;
346#endif
347}
348
349#ifdef HWPMC_HOOKS
350static void
351lapic_update_pmc(void *dummy)
352{
353	struct lapic *la;
354
355	la = &lapics[lapic_id()];
356	lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
357}
358#endif
359
360int
361lapic_enable_pmc(void)
362{
363#ifdef HWPMC_HOOKS
364	u_int32_t maxlvt;
365
366	/* Fail if the local APIC is not present. */
367	if (lapic == NULL)
368		return (0);
369
370	/* Fail if the PMC LVT is not present. */
371	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
372	if (maxlvt < LVT_PMC)
373		return (0);
374
375	lvts[LVT_PMC].lvt_masked = 0;
376
377#ifdef SMP
378	/*
379	 * If hwpmc was loaded at boot time then the APs may not be
380	 * started yet.  In that case, don't forward the request to
381	 * them as they will program the lvt when they start.
382	 */
383	if (smp_started)
384		smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
385	else
386#endif
387		lapic_update_pmc(NULL);
388	return (1);
389#else
390	return (0);
391#endif
392}
393
394void
395lapic_disable_pmc(void)
396{
397#ifdef HWPMC_HOOKS
398	u_int32_t maxlvt;
399
400	/* Fail if the local APIC is not present. */
401	if (lapic == NULL)
402		return;
403
404	/* Fail if the PMC LVT is not present. */
405	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
406	if (maxlvt < LVT_PMC)
407		return;
408
409	lvts[LVT_PMC].lvt_masked = 1;
410
411#ifdef SMP
412	/* The APs should always be started when hwpmc is unloaded. */
413	KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early"));
414#endif
415	smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
416#endif
417}
418
419/*
420 * Called by cpu_initclocks() on the BSP to setup the local APIC timer so
421 * that it can drive hardclock, statclock, and profclock.
422 */
423enum lapic_clock
424lapic_setup_clock(enum lapic_clock srcsdes)
425{
426	u_long value;
427	int i;
428
429	/* lapic_setup_clock() should not be called with LAPIC_CLOCK_NONE. */
430	MPASS(srcsdes != LAPIC_CLOCK_NONE);
431
432	/* Can't drive the timer without a local APIC. */
433	if (lapic == NULL ||
434	    (resource_int_value("apic", 0, "clock", &i) == 0 && i == 0)) {
435		clockcoverage = LAPIC_CLOCK_NONE;
436		return (clockcoverage);
437	}
438
439	/* Start off with a divisor of 2 (power on reset default). */
440	lapic_timer_divisor = 2;
441
442	/* Try to calibrate the local APIC timer. */
443	do {
444		lapic_timer_set_divisor(lapic_timer_divisor);
445		lapic_timer_oneshot(APIC_TIMER_MAX_COUNT);
446		DELAY(2000000);
447		value = APIC_TIMER_MAX_COUNT - lapic->ccr_timer;
448		if (value != APIC_TIMER_MAX_COUNT)
449			break;
450		lapic_timer_divisor <<= 1;
451	} while (lapic_timer_divisor <= 128);
452	if (lapic_timer_divisor > 128)
453		panic("lapic: Divisor too big");
454	value /= 2;
455	if (bootverbose)
456		printf("lapic: Divisor %lu, Frequency %lu Hz\n",
457		    lapic_timer_divisor, value);
458
459	/*
460	 * We want to run stathz in the neighborhood of 128hz.  We would
461	 * like profhz to run as often as possible, so we let it run on
462	 * each clock tick.  We try to honor the requested 'hz' value as
463	 * much as possible.
464	 *
465	 * If 'hz' is above 1500, then we just let the lapic timer
466	 * (and profhz) run at hz.  If 'hz' is below 1500 but above
467	 * 750, then we let the lapic timer run at 2 * 'hz'.  If 'hz'
468	 * is below 750 then we let the lapic timer run at 4 * 'hz'.
469	 *
470	 * Please note that stathz and profhz are set only if all the
471	 * clocks are handled through the local APIC.
472	 */
473	if (srcsdes == LAPIC_CLOCK_ALL) {
474		if (hz >= 1500)
475			lapic_timer_hz = hz;
476		else if (hz >= 750)
477			lapic_timer_hz = hz * 2;
478		else
479			lapic_timer_hz = hz * 4;
480	} else
481		lapic_timer_hz = hz;
482	lapic_timer_period = value / lapic_timer_hz;
483	if (srcsdes == LAPIC_CLOCK_ALL) {
484		if (lapic_timer_hz < 128)
485			stathz = lapic_timer_hz;
486		else
487			stathz = lapic_timer_hz / (lapic_timer_hz / 128);
488		profhz = lapic_timer_hz;
489	}
490
491	/*
492	 * Start up the timer on the BSP.  The APs will kick off their
493	 * timer during lapic_setup().
494	 */
495	lapic_timer_periodic(lapic_timer_period);
496	lapic_timer_enable_intr();
497	clockcoverage = srcsdes;
498	return (srcsdes);
499}
500
501void
502lapic_disable(void)
503{
504	uint32_t value;
505
506	/* Software disable the local APIC. */
507	value = lapic->svr;
508	value &= ~APIC_SVR_SWEN;
509	lapic->svr = value;
510}
511
512static void
513lapic_enable(void)
514{
515	u_int32_t value;
516
517	/* Program the spurious vector to enable the local APIC. */
518	value = lapic->svr;
519	value &= ~(APIC_SVR_VECTOR | APIC_SVR_FOCUS);
520	value |= (APIC_SVR_FEN | APIC_SVR_SWEN | APIC_SPURIOUS_INT);
521	lapic->svr = value;
522}
523
524/* Reset the local APIC on the BSP during resume. */
525static void
526lapic_resume(struct pic *pic)
527{
528
529	lapic_setup(0);
530}
531
532int
533lapic_id(void)
534{
535
536	KASSERT(lapic != NULL, ("local APIC is not mapped"));
537	return (lapic->id >> APIC_ID_SHIFT);
538}
539
540int
541lapic_intr_pending(u_int vector)
542{
543	volatile u_int32_t *irr;
544
545	/*
546	 * The IRR registers are an array of 128-bit registers each of
547	 * which only describes 32 interrupts in the low 32 bits..  Thus,
548	 * we divide the vector by 32 to get the 128-bit index.  We then
549	 * multiply that index by 4 to get the equivalent index from
550	 * treating the IRR as an array of 32-bit registers.  Finally, we
551	 * modulus the vector by 32 to determine the individual bit to
552	 * test.
553	 */
554	irr = &lapic->irr0;
555	return (irr[(vector / 32) * 4] & 1 << (vector % 32));
556}
557
558void
559lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
560{
561	struct lapic *la;
562
563	KASSERT(lapics[apic_id].la_present, ("%s: APIC %u doesn't exist",
564	    __func__, apic_id));
565	KASSERT(cluster <= APIC_MAX_CLUSTER, ("%s: cluster %u too big",
566	    __func__, cluster));
567	KASSERT(cluster_id <= APIC_MAX_INTRACLUSTER_ID,
568	    ("%s: intra cluster id %u too big", __func__, cluster_id));
569	la = &lapics[apic_id];
570	la->la_cluster = cluster;
571	la->la_cluster_id = cluster_id;
572}
573
574int
575lapic_set_lvt_mask(u_int apic_id, u_int pin, u_char masked)
576{
577
578	if (pin > LVT_MAX)
579		return (EINVAL);
580	if (apic_id == APIC_ID_ALL) {
581		lvts[pin].lvt_masked = masked;
582		if (bootverbose)
583			printf("lapic:");
584	} else {
585		KASSERT(lapics[apic_id].la_present,
586		    ("%s: missing APIC %u", __func__, apic_id));
587		lapics[apic_id].la_lvts[pin].lvt_masked = masked;
588		lapics[apic_id].la_lvts[pin].lvt_active = 1;
589		if (bootverbose)
590			printf("lapic%u:", apic_id);
591	}
592	if (bootverbose)
593		printf(" LINT%u %s\n", pin, masked ? "masked" : "unmasked");
594	return (0);
595}
596
597int
598lapic_set_lvt_mode(u_int apic_id, u_int pin, u_int32_t mode)
599{
600	struct lvt *lvt;
601
602	if (pin > LVT_MAX)
603		return (EINVAL);
604	if (apic_id == APIC_ID_ALL) {
605		lvt = &lvts[pin];
606		if (bootverbose)
607			printf("lapic:");
608	} else {
609		KASSERT(lapics[apic_id].la_present,
610		    ("%s: missing APIC %u", __func__, apic_id));
611		lvt = &lapics[apic_id].la_lvts[pin];
612		lvt->lvt_active = 1;
613		if (bootverbose)
614			printf("lapic%u:", apic_id);
615	}
616	lvt->lvt_mode = mode;
617	switch (mode) {
618	case APIC_LVT_DM_NMI:
619	case APIC_LVT_DM_SMI:
620	case APIC_LVT_DM_INIT:
621	case APIC_LVT_DM_EXTINT:
622		lvt->lvt_edgetrigger = 1;
623		lvt->lvt_activehi = 1;
624		if (mode == APIC_LVT_DM_EXTINT)
625			lvt->lvt_masked = 1;
626		else
627			lvt->lvt_masked = 0;
628		break;
629	default:
630		panic("Unsupported delivery mode: 0x%x\n", mode);
631	}
632	if (bootverbose) {
633		printf(" Routing ");
634		switch (mode) {
635		case APIC_LVT_DM_NMI:
636			printf("NMI");
637			break;
638		case APIC_LVT_DM_SMI:
639			printf("SMI");
640			break;
641		case APIC_LVT_DM_INIT:
642			printf("INIT");
643			break;
644		case APIC_LVT_DM_EXTINT:
645			printf("ExtINT");
646			break;
647		}
648		printf(" -> LINT%u\n", pin);
649	}
650	return (0);
651}
652
653int
654lapic_set_lvt_polarity(u_int apic_id, u_int pin, enum intr_polarity pol)
655{
656
657	if (pin > LVT_MAX || pol == INTR_POLARITY_CONFORM)
658		return (EINVAL);
659	if (apic_id == APIC_ID_ALL) {
660		lvts[pin].lvt_activehi = (pol == INTR_POLARITY_HIGH);
661		if (bootverbose)
662			printf("lapic:");
663	} else {
664		KASSERT(lapics[apic_id].la_present,
665		    ("%s: missing APIC %u", __func__, apic_id));
666		lapics[apic_id].la_lvts[pin].lvt_active = 1;
667		lapics[apic_id].la_lvts[pin].lvt_activehi =
668		    (pol == INTR_POLARITY_HIGH);
669		if (bootverbose)
670			printf("lapic%u:", apic_id);
671	}
672	if (bootverbose)
673		printf(" LINT%u polarity: %s\n", pin,
674		    pol == INTR_POLARITY_HIGH ? "high" : "low");
675	return (0);
676}
677
678int
679lapic_set_lvt_triggermode(u_int apic_id, u_int pin, enum intr_trigger trigger)
680{
681
682	if (pin > LVT_MAX || trigger == INTR_TRIGGER_CONFORM)
683		return (EINVAL);
684	if (apic_id == APIC_ID_ALL) {
685		lvts[pin].lvt_edgetrigger = (trigger == INTR_TRIGGER_EDGE);
686		if (bootverbose)
687			printf("lapic:");
688	} else {
689		KASSERT(lapics[apic_id].la_present,
690		    ("%s: missing APIC %u", __func__, apic_id));
691		lapics[apic_id].la_lvts[pin].lvt_edgetrigger =
692		    (trigger == INTR_TRIGGER_EDGE);
693		lapics[apic_id].la_lvts[pin].lvt_active = 1;
694		if (bootverbose)
695			printf("lapic%u:", apic_id);
696	}
697	if (bootverbose)
698		printf(" LINT%u trigger: %s\n", pin,
699		    trigger == INTR_TRIGGER_EDGE ? "edge" : "level");
700	return (0);
701}
702
703/*
704 * Adjust the TPR of the current CPU so that it blocks all interrupts below
705 * the passed in vector.
706 */
707void
708lapic_set_tpr(u_int vector)
709{
710#ifdef CHEAP_TPR
711	lapic->tpr = vector;
712#else
713	u_int32_t tpr;
714
715	tpr = lapic->tpr & ~APIC_TPR_PRIO;
716	tpr |= vector;
717	lapic->tpr = tpr;
718#endif
719}
720
721void
722lapic_eoi(void)
723{
724
725	lapic->eoi = 0;
726}
727
728/*
729 * Read the contents of the error status register.  We have to write
730 * to the register first before reading from it.
731 */
732u_int
733lapic_error(void)
734{
735
736	lapic->esr = 0;
737	return (lapic->esr);
738}
739
740void
741lapic_handle_intr(int vector, struct trapframe *frame)
742{
743	struct intsrc *isrc;
744
745	if (vector == -1)
746		panic("Couldn't get vector from ISR!");
747	isrc = intr_lookup_source(apic_idt_to_irq(PCPU_GET(apic_id),
748	    vector));
749	intr_execute_handlers(isrc, frame);
750}
751
752void
753lapic_handle_timer(struct trapframe *frame)
754{
755	struct lapic *la;
756
757	/* Send EOI first thing. */
758	lapic_eoi();
759
760#if defined(SMP) && !defined(SCHED_ULE)
761	/*
762	 * Don't do any accounting for the disabled HTT cores, since it
763	 * will provide misleading numbers for the userland.
764	 *
765	 * No locking is necessary here, since even if we loose the race
766	 * when hlt_cpus_mask changes it is not a big deal, really.
767	 *
768	 * Don't do that for ULE, since ULE doesn't consider hlt_cpus_mask
769	 * and unlike other schedulers it actually schedules threads to
770	 * those CPUs.
771	 */
772	if ((hlt_cpus_mask & (1 << PCPU_GET(cpuid))) != 0)
773		return;
774#endif
775
776	/* Look up our local APIC structure for the tick counters. */
777	la = &lapics[PCPU_GET(apic_id)];
778	(*la->la_timer_count)++;
779	critical_enter();
780
781#ifdef KDTRACE_HOOKS
782	/*
783	 * If the DTrace hooks are configured and a callback function
784	 * has been registered, then call it to process the high speed
785	 * timers.
786	 */
787	int cpu = PCPU_GET(cpuid);
788	if (lapic_cyclic_clock_func[cpu] != NULL)
789		(*lapic_cyclic_clock_func[cpu])(frame);
790#endif
791
792	/* Fire hardclock at hz. */
793	la->la_hard_ticks += hz;
794	if (la->la_hard_ticks >= lapic_timer_hz) {
795		la->la_hard_ticks -= lapic_timer_hz;
796		if (PCPU_GET(cpuid) == 0)
797			hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
798		else
799			hardclock_cpu(TRAPF_USERMODE(frame));
800	}
801	if (clockcoverage == LAPIC_CLOCK_ALL) {
802
803		/* Fire statclock at stathz. */
804		la->la_stat_ticks += stathz;
805		if (la->la_stat_ticks >= lapic_timer_hz) {
806			la->la_stat_ticks -= lapic_timer_hz;
807			statclock(TRAPF_USERMODE(frame));
808		}
809
810		/* Fire profclock at profhz, but only when needed. */
811		la->la_prof_ticks += profhz;
812		if (la->la_prof_ticks >= lapic_timer_hz) {
813			la->la_prof_ticks -= lapic_timer_hz;
814			if (profprocs != 0)
815				profclock(TRAPF_USERMODE(frame),
816				    TRAPF_PC(frame));
817		}
818	}
819	critical_exit();
820}
821
822static void
823lapic_timer_set_divisor(u_int divisor)
824{
825
826	KASSERT(powerof2(divisor), ("lapic: invalid divisor %u", divisor));
827	KASSERT(ffs(divisor) <= sizeof(lapic_timer_divisors) /
828	    sizeof(u_int32_t), ("lapic: invalid divisor %u", divisor));
829	lapic->dcr_timer = lapic_timer_divisors[ffs(divisor) - 1];
830}
831
832static void
833lapic_timer_oneshot(u_int count)
834{
835	u_int32_t value;
836
837	value = lapic->lvt_timer;
838	value &= ~APIC_LVTT_TM;
839	value |= APIC_LVTT_TM_ONE_SHOT;
840	lapic->lvt_timer = value;
841	lapic->icr_timer = count;
842}
843
844static void
845lapic_timer_periodic(u_int count)
846{
847	u_int32_t value;
848
849	value = lapic->lvt_timer;
850	value &= ~APIC_LVTT_TM;
851	value |= APIC_LVTT_TM_PERIODIC;
852	lapic->lvt_timer = value;
853	lapic->icr_timer = count;
854}
855
856static void
857lapic_timer_enable_intr(void)
858{
859	u_int32_t value;
860
861	value = lapic->lvt_timer;
862	value &= ~APIC_LVT_M;
863	lapic->lvt_timer = value;
864}
865
866u_int
867apic_cpuid(u_int apic_id)
868{
869#ifdef SMP
870	return apic_cpuids[apic_id];
871#else
872	return 0;
873#endif
874}
875
876/* Request a free IDT vector to be used by the specified IRQ. */
877u_int
878apic_alloc_vector(u_int apic_id, u_int irq)
879{
880	u_int vector;
881
882	KASSERT(irq < NUM_IO_INTS, ("Invalid IRQ %u", irq));
883
884	/*
885	 * Search for a free vector.  Currently we just use a very simple
886	 * algorithm to find the first free vector.
887	 */
888	mtx_lock_spin(&icu_lock);
889	for (vector = 0; vector < APIC_NUM_IOINTS; vector++) {
890		if (lapics[apic_id].la_ioint_irqs[vector] != -1)
891			continue;
892		lapics[apic_id].la_ioint_irqs[vector] = irq;
893		mtx_unlock_spin(&icu_lock);
894		return (vector + APIC_IO_INTS);
895	}
896	mtx_unlock_spin(&icu_lock);
897	return (0);
898}
899
900/*
901 * Request 'count' free contiguous IDT vectors to be used by 'count'
902 * IRQs.  'count' must be a power of two and the vectors will be
903 * aligned on a boundary of 'align'.  If the request cannot be
904 * satisfied, 0 is returned.
905 */
906u_int
907apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
908{
909	u_int first, run, vector;
910
911	KASSERT(powerof2(count), ("bad count"));
912	KASSERT(powerof2(align), ("bad align"));
913	KASSERT(align >= count, ("align < count"));
914#ifdef INVARIANTS
915	for (run = 0; run < count; run++)
916		KASSERT(irqs[run] < NUM_IO_INTS, ("Invalid IRQ %u at index %u",
917		    irqs[run], run));
918#endif
919
920	/*
921	 * Search for 'count' free vectors.  As with apic_alloc_vector(),
922	 * this just uses a simple first fit algorithm.
923	 */
924	run = 0;
925	first = 0;
926	mtx_lock_spin(&icu_lock);
927	for (vector = 0; vector < APIC_NUM_IOINTS; vector++) {
928
929		/* Vector is in use, end run. */
930		if (lapics[apic_id].la_ioint_irqs[vector] != -1) {
931			run = 0;
932			first = 0;
933			continue;
934		}
935
936		/* Start a new run if run == 0 and vector is aligned. */
937		if (run == 0) {
938			if ((vector & (align - 1)) != 0)
939				continue;
940			first = vector;
941		}
942		run++;
943
944		/* Keep looping if the run isn't long enough yet. */
945		if (run < count)
946			continue;
947
948		/* Found a run, assign IRQs and return the first vector. */
949		for (vector = 0; vector < count; vector++)
950			lapics[apic_id].la_ioint_irqs[first + vector] =
951			    irqs[vector];
952		mtx_unlock_spin(&icu_lock);
953		return (first + APIC_IO_INTS);
954	}
955	mtx_unlock_spin(&icu_lock);
956	printf("APIC: Couldn't find APIC vectors for %u IRQs\n", count);
957	return (0);
958}
959
960/*
961 * Enable a vector for a particular apic_id.  Since all lapics share idt
962 * entries and ioint_handlers this enables the vector on all lapics.  lapics
963 * which do not have the vector configured would report spurious interrupts
964 * should it fire.
965 */
966void
967apic_enable_vector(u_int apic_id, u_int vector)
968{
969
970	KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
971	KASSERT(ioint_handlers[vector / 32] != NULL,
972	    ("No ISR handler for vector %u", vector));
973	setidt(vector, ioint_handlers[vector / 32], SDT_SYS386IGT, SEL_KPL,
974	    GSEL(GCODE_SEL, SEL_KPL));
975}
976
977void
978apic_disable_vector(u_int apic_id, u_int vector)
979{
980
981	KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
982	KASSERT(ioint_handlers[vector / 32] != NULL,
983	    ("No ISR handler for vector %u", vector));
984#ifdef notyet
985	/*
986	 * We can not currently clear the idt entry because other cpus
987	 * may have a valid vector at this offset.
988	 */
989	setidt(vector, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL,
990	    GSEL(GCODE_SEL, SEL_KPL));
991#endif
992}
993
994/* Release an APIC vector when it's no longer in use. */
995void
996apic_free_vector(u_int apic_id, u_int vector, u_int irq)
997{
998	struct thread *td;
999
1000	KASSERT(vector >= APIC_IO_INTS && vector != IDT_SYSCALL &&
1001	    vector <= APIC_IO_INTS + APIC_NUM_IOINTS,
1002	    ("Vector %u does not map to an IRQ line", vector));
1003	KASSERT(irq < NUM_IO_INTS, ("Invalid IRQ %u", irq));
1004	KASSERT(lapics[apic_id].la_ioint_irqs[vector - APIC_IO_INTS] ==
1005	    irq, ("IRQ mismatch"));
1006
1007	/*
1008	 * Bind us to the cpu that owned the vector before freeing it so
1009	 * we don't lose an interrupt delivery race.
1010	 */
1011	td = curthread;
1012	if (!rebooting) {
1013		thread_lock(td);
1014		if (sched_is_bound(td))
1015			panic("apic_free_vector: Thread already bound.\n");
1016		sched_bind(td, apic_cpuid(apic_id));
1017		thread_unlock(td);
1018	}
1019	mtx_lock_spin(&icu_lock);
1020	lapics[apic_id].la_ioint_irqs[vector - APIC_IO_INTS] = -1;
1021	mtx_unlock_spin(&icu_lock);
1022	if (!rebooting) {
1023		thread_lock(td);
1024		sched_unbind(td);
1025		thread_unlock(td);
1026	}
1027}
1028
1029/* Map an IDT vector (APIC) to an IRQ (interrupt source). */
1030u_int
1031apic_idt_to_irq(u_int apic_id, u_int vector)
1032{
1033	int irq;
1034
1035	KASSERT(vector >= APIC_IO_INTS && vector != IDT_SYSCALL &&
1036	    vector <= APIC_IO_INTS + APIC_NUM_IOINTS,
1037	    ("Vector %u does not map to an IRQ line", vector));
1038	irq = lapics[apic_id].la_ioint_irqs[vector - APIC_IO_INTS];
1039	if (irq < 0)
1040		irq = 0;
1041	return (irq);
1042}
1043
1044#ifdef DDB
1045/*
1046 * Dump data about APIC IDT vector mappings.
1047 */
1048DB_SHOW_COMMAND(apic, db_show_apic)
1049{
1050	struct intsrc *isrc;
1051	int i, verbose;
1052	u_int apic_id;
1053	u_int irq;
1054
1055	if (strcmp(modif, "vv") == 0)
1056		verbose = 2;
1057	else if (strcmp(modif, "v") == 0)
1058		verbose = 1;
1059	else
1060		verbose = 0;
1061	for (apic_id = 0; apic_id <= MAX_APIC_ID; apic_id++) {
1062		if (lapics[apic_id].la_present == 0)
1063			continue;
1064		db_printf("Interrupts bound to lapic %u\n", apic_id);
1065		for (i = 0; i < APIC_NUM_IOINTS + 1 && !db_pager_quit; i++) {
1066			irq = lapics[apic_id].la_ioint_irqs[i];
1067			if (irq == -1 || irq == IRQ_SYSCALL)
1068				continue;
1069			db_printf("vec 0x%2x -> ", i + APIC_IO_INTS);
1070			if (irq == IRQ_TIMER)
1071				db_printf("lapic timer\n");
1072			else if (irq < NUM_IO_INTS) {
1073				isrc = intr_lookup_source(irq);
1074				if (isrc == NULL || verbose == 0)
1075					db_printf("IRQ %u\n", irq);
1076				else
1077					db_dump_intr_event(isrc->is_event,
1078					    verbose == 2);
1079			} else
1080				db_printf("IRQ %u ???\n", irq);
1081		}
1082	}
1083}
1084
1085static void
1086dump_mask(const char *prefix, uint32_t v, int base)
1087{
1088	int i, first;
1089
1090	first = 1;
1091	for (i = 0; i < 32; i++)
1092		if (v & (1 << i)) {
1093			if (first) {
1094				db_printf("%s:", prefix);
1095				first = 0;
1096			}
1097			db_printf(" %02x", base + i);
1098		}
1099	if (!first)
1100		db_printf("\n");
1101}
1102
1103/* Show info from the lapic regs for this CPU. */
1104DB_SHOW_COMMAND(lapic, db_show_lapic)
1105{
1106	uint32_t v;
1107
1108	db_printf("lapic ID = %d\n", lapic_id());
1109	v = lapic->version;
1110	db_printf("version  = %d.%d\n", (v & APIC_VER_VERSION) >> 4,
1111	    v & 0xf);
1112	db_printf("max LVT  = %d\n", (v & APIC_VER_MAXLVT) >> MAXLVTSHIFT);
1113	v = lapic->svr;
1114	db_printf("SVR      = %02x (%s)\n", v & APIC_SVR_VECTOR,
1115	    v & APIC_SVR_ENABLE ? "enabled" : "disabled");
1116	db_printf("TPR      = %02x\n", lapic->tpr);
1117
1118#define dump_field(prefix, index)					\
1119	dump_mask(__XSTRING(prefix ## index), lapic->prefix ## index,	\
1120	    index * 32)
1121
1122	db_printf("In-service Interrupts:\n");
1123	dump_field(isr, 0);
1124	dump_field(isr, 1);
1125	dump_field(isr, 2);
1126	dump_field(isr, 3);
1127	dump_field(isr, 4);
1128	dump_field(isr, 5);
1129	dump_field(isr, 6);
1130	dump_field(isr, 7);
1131
1132	db_printf("TMR Interrupts:\n");
1133	dump_field(tmr, 0);
1134	dump_field(tmr, 1);
1135	dump_field(tmr, 2);
1136	dump_field(tmr, 3);
1137	dump_field(tmr, 4);
1138	dump_field(tmr, 5);
1139	dump_field(tmr, 6);
1140	dump_field(tmr, 7);
1141
1142	db_printf("IRR Interrupts:\n");
1143	dump_field(irr, 0);
1144	dump_field(irr, 1);
1145	dump_field(irr, 2);
1146	dump_field(irr, 3);
1147	dump_field(irr, 4);
1148	dump_field(irr, 5);
1149	dump_field(irr, 6);
1150	dump_field(irr, 7);
1151
1152#undef dump_field
1153}
1154#endif
1155
1156/*
1157 * APIC probing support code.  This includes code to manage enumerators.
1158 */
1159
1160static SLIST_HEAD(, apic_enumerator) enumerators =
1161	SLIST_HEAD_INITIALIZER(enumerators);
1162static struct apic_enumerator *best_enum;
1163
1164void
1165apic_register_enumerator(struct apic_enumerator *enumerator)
1166{
1167#ifdef INVARIANTS
1168	struct apic_enumerator *apic_enum;
1169
1170	SLIST_FOREACH(apic_enum, &enumerators, apic_next) {
1171		if (apic_enum == enumerator)
1172			panic("%s: Duplicate register of %s", __func__,
1173			    enumerator->apic_name);
1174	}
1175#endif
1176	SLIST_INSERT_HEAD(&enumerators, enumerator, apic_next);
1177}
1178
1179/*
1180 * Probe the APIC enumerators, enumerate CPUs, and initialize the
1181 * local APIC.
1182 */
1183static void
1184apic_init(void *dummy __unused)
1185{
1186	struct apic_enumerator *enumerator;
1187	uint64_t apic_base;
1188	int retval, best;
1189
1190	/* We only support built in local APICs. */
1191	if (!(cpu_feature & CPUID_APIC))
1192		return;
1193
1194	/* Don't probe if APIC mode is disabled. */
1195	if (resource_disabled("apic", 0))
1196		return;
1197
1198	/* First, probe all the enumerators to find the best match. */
1199	best_enum = NULL;
1200	best = 0;
1201	SLIST_FOREACH(enumerator, &enumerators, apic_next) {
1202		retval = enumerator->apic_probe();
1203		if (retval > 0)
1204			continue;
1205		if (best_enum == NULL || best < retval) {
1206			best_enum = enumerator;
1207			best = retval;
1208		}
1209	}
1210	if (best_enum == NULL) {
1211		if (bootverbose)
1212			printf("APIC: Could not find any APICs.\n");
1213		return;
1214	}
1215
1216	if (bootverbose)
1217		printf("APIC: Using the %s enumerator.\n",
1218		    best_enum->apic_name);
1219
1220	/*
1221	 * To work around an errata, we disable the local APIC on some
1222	 * CPUs during early startup.  We need to turn the local APIC back
1223	 * on on such CPUs now.
1224	 */
1225	if (cpu == CPU_686 && cpu_vendor_id == CPU_VENDOR_INTEL &&
1226	    (cpu_id & 0xff0) == 0x610) {
1227		apic_base = rdmsr(MSR_APICBASE);
1228		apic_base |= APICBASE_ENABLED;
1229		wrmsr(MSR_APICBASE, apic_base);
1230	}
1231
1232	/* Second, probe the CPU's in the system. */
1233	retval = best_enum->apic_probe_cpus();
1234	if (retval != 0)
1235		printf("%s: Failed to probe CPUs: returned %d\n",
1236		    best_enum->apic_name, retval);
1237
1238	/* Third, initialize the local APIC. */
1239	retval = best_enum->apic_setup_local();
1240	if (retval != 0)
1241		printf("%s: Failed to setup the local APIC: returned %d\n",
1242		    best_enum->apic_name, retval);
1243}
1244SYSINIT(apic_init, SI_SUB_CPU, SI_ORDER_SECOND, apic_init, NULL);
1245
1246/*
1247 * Setup the I/O APICs.
1248 */
1249static void
1250apic_setup_io(void *dummy __unused)
1251{
1252	int retval;
1253
1254	if (best_enum == NULL)
1255		return;
1256	retval = best_enum->apic_setup_io();
1257	if (retval != 0)
1258		printf("%s: Failed to setup I/O APICs: returned %d\n",
1259		    best_enum->apic_name, retval);
1260
1261#ifdef XEN
1262	return;
1263#endif
1264	/*
1265	 * Finish setting up the local APIC on the BSP once we know how to
1266	 * properly program the LINT pins.
1267	 */
1268	lapic_setup(1);
1269	intr_register_pic(&lapic_pic);
1270	if (bootverbose)
1271		lapic_dump("BSP");
1272
1273	/* Enable the MSI "pic". */
1274	msi_init();
1275}
1276SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_SECOND, apic_setup_io, NULL);
1277
1278#ifdef SMP
1279/*
1280 * Inter Processor Interrupt functions.  The lapic_ipi_*() functions are
1281 * private to the sys/i386 code.  The public interface for the rest of the
1282 * kernel is defined in mp_machdep.c.
1283 */
1284int
1285lapic_ipi_wait(int delay)
1286{
1287	int x, incr;
1288
1289	/*
1290	 * Wait delay loops for IPI to be sent.  This is highly bogus
1291	 * since this is sensitive to CPU clock speed.  If delay is
1292	 * -1, we wait forever.
1293	 */
1294	if (delay == -1) {
1295		incr = 0;
1296		delay = 1;
1297	} else
1298		incr = 1;
1299	for (x = 0; x < delay; x += incr) {
1300		if ((lapic->icr_lo & APIC_DELSTAT_MASK) == APIC_DELSTAT_IDLE)
1301			return (1);
1302		ia32_pause();
1303	}
1304	return (0);
1305}
1306
1307void
1308lapic_ipi_raw(register_t icrlo, u_int dest)
1309{
1310	register_t value, eflags;
1311
1312	/* XXX: Need more sanity checking of icrlo? */
1313	KASSERT(lapic != NULL, ("%s called too early", __func__));
1314	KASSERT((dest & ~(APIC_ID_MASK >> APIC_ID_SHIFT)) == 0,
1315	    ("%s: invalid dest field", __func__));
1316	KASSERT((icrlo & APIC_ICRLO_RESV_MASK) == 0,
1317	    ("%s: reserved bits set in ICR LO register", __func__));
1318
1319	/* Set destination in ICR HI register if it is being used. */
1320	eflags = intr_disable();
1321	if ((icrlo & APIC_DEST_MASK) == APIC_DEST_DESTFLD) {
1322		value = lapic->icr_hi;
1323		value &= ~APIC_ID_MASK;
1324		value |= dest << APIC_ID_SHIFT;
1325		lapic->icr_hi = value;
1326	}
1327
1328	/* Program the contents of the IPI and dispatch it. */
1329	value = lapic->icr_lo;
1330	value &= APIC_ICRLO_RESV_MASK;
1331	value |= icrlo;
1332	lapic->icr_lo = value;
1333	intr_restore(eflags);
1334}
1335
1336#define	BEFORE_SPIN	1000000
1337#ifdef DETECT_DEADLOCK
1338#define	AFTER_SPIN	1000
1339#endif
1340
1341void
1342lapic_ipi_vectored(u_int vector, int dest)
1343{
1344	register_t icrlo, destfield;
1345
1346	KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
1347	    ("%s: invalid vector %d", __func__, vector));
1348
1349	icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE;
1350
1351	/*
1352	 * IPI_STOP_HARD is just a "fake" vector used to send a NMI.
1353	 * Use special rules regard NMI if passed, otherwise specify
1354	 * the vector.
1355	 */
1356	if (vector == IPI_STOP_HARD)
1357		icrlo |= APIC_DELMODE_NMI | APIC_LEVEL_ASSERT;
1358	else
1359		icrlo |= vector | APIC_DELMODE_FIXED | APIC_LEVEL_DEASSERT;
1360	destfield = 0;
1361	switch (dest) {
1362	case APIC_IPI_DEST_SELF:
1363		icrlo |= APIC_DEST_SELF;
1364		break;
1365	case APIC_IPI_DEST_ALL:
1366		icrlo |= APIC_DEST_ALLISELF;
1367		break;
1368	case APIC_IPI_DEST_OTHERS:
1369		icrlo |= APIC_DEST_ALLESELF;
1370		break;
1371	default:
1372		KASSERT((dest & ~(APIC_ID_MASK >> APIC_ID_SHIFT)) == 0,
1373		    ("%s: invalid destination 0x%x", __func__, dest));
1374		destfield = dest;
1375	}
1376
1377	/* Wait for an earlier IPI to finish. */
1378	if (!lapic_ipi_wait(BEFORE_SPIN)) {
1379		if (panicstr != NULL)
1380			return;
1381		else
1382			panic("APIC: Previous IPI is stuck");
1383	}
1384
1385	lapic_ipi_raw(icrlo, destfield);
1386
1387#ifdef DETECT_DEADLOCK
1388	/* Wait for IPI to be delivered. */
1389	if (!lapic_ipi_wait(AFTER_SPIN)) {
1390#ifdef needsattention
1391		/*
1392		 * XXX FIXME:
1393		 *
1394		 * The above function waits for the message to actually be
1395		 * delivered.  It breaks out after an arbitrary timeout
1396		 * since the message should eventually be delivered (at
1397		 * least in theory) and that if it wasn't we would catch
1398		 * the failure with the check above when the next IPI is
1399		 * sent.
1400		 *
1401		 * We could skip this wait entirely, EXCEPT it probably
1402		 * protects us from other routines that assume that the
1403		 * message was delivered and acted upon when this function
1404		 * returns.
1405		 */
1406		printf("APIC: IPI might be stuck\n");
1407#else /* !needsattention */
1408		/* Wait until mesage is sent without a timeout. */
1409		while (lapic->icr_lo & APIC_DELSTAT_PEND)
1410			ia32_pause();
1411#endif /* needsattention */
1412	}
1413#endif /* DETECT_DEADLOCK */
1414}
1415#endif /* SMP */
1416