]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/local_apic.c
This commit was generated by cvs2svn to compensate for changes in r147462,
[FreeBSD/FreeBSD.git] / sys / amd64 / amd64 / local_apic.c
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$");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/bus.h>
40 #include <sys/kernel.h>
41 #include <sys/pcpu.h>
42 #include <sys/smp.h>
43 #include <sys/proc.h>
44
45 #include <vm/vm.h>
46 #include <vm/pmap.h>
47
48 #include <machine/apicreg.h>
49 #include <machine/cputypes.h>
50 #include <machine/frame.h>
51 #include <machine/intr_machdep.h>
52 #include <machine/apicvar.h>
53 #include <machine/md_var.h>
54 #include <machine/smp.h>
55 #include <machine/specialreg.h>
56
57 /*
58  * We can handle up to 60 APICs via our logical cluster IDs, but currently
59  * the physical IDs on Intel processors up to the Pentium 4 are limited to
60  * 16.
61  */
62 #define MAX_APICID      16
63
64 /* Sanity checks on IDT vectors. */
65 CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
66 CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
67 CTASSERT(APIC_LOCAL_INTS == 240);
68 CTASSERT(IPI_STOP < APIC_SPURIOUS_INT);
69
70 #define LAPIC_TIMER_HZ_DIVIDER          2
71 #define LAPIC_TIMER_STATHZ_DIVIDER      15
72 #define LAPIC_TIMER_PROFHZ_DIVIDER      3
73
74 /*
75  * Support for local APICs.  Local APICs manage interrupts on each
76  * individual processor as opposed to I/O APICs which receive interrupts
77  * from I/O devices and then forward them on to the local APICs.
78  *
79  * Local APICs can also send interrupts to each other thus providing the
80  * mechanism for IPIs.
81  */
82
83 struct lvt {
84         u_int lvt_edgetrigger:1;
85         u_int lvt_activehi:1;
86         u_int lvt_masked:1;
87         u_int lvt_active:1;
88         u_int lvt_mode:16;
89         u_int lvt_vector:8;
90 };
91
92 struct lapic {
93         struct lvt la_lvts[LVT_MAX + 1];
94         u_int la_id:8;
95         u_int la_cluster:4;
96         u_int la_cluster_id:2;
97         u_int la_present:1;
98         u_long *la_timer_count;
99         u_long la_hard_ticks;
100         u_long la_stat_ticks;
101         u_long la_prof_ticks;
102 } static lapics[MAX_APICID];
103
104 /* XXX: should thermal be an NMI? */
105
106 /* Global defaults for local APIC LVT entries. */
107 static struct lvt lvts[LVT_MAX + 1] = {
108         { 1, 1, 1, 1, APIC_LVT_DM_EXTINT, 0 },  /* LINT0: masked ExtINT */
109         { 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },     /* LINT1: NMI */
110         { 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT },      /* Timer */
111         { 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },      /* Error */
112         { 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },     /* PMC */
113         { 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT },    /* Thermal */
114 };
115
116 static inthand_t *ioint_handlers[] = {
117         NULL,                   /* 0 - 31 */
118         IDTVEC(apic_isr1),      /* 32 - 63 */
119         IDTVEC(apic_isr2),      /* 64 - 95 */
120         IDTVEC(apic_isr3),      /* 96 - 127 */
121         IDTVEC(apic_isr4),      /* 128 - 159 */
122         IDTVEC(apic_isr5),      /* 160 - 191 */
123         IDTVEC(apic_isr6),      /* 192 - 223 */
124         IDTVEC(apic_isr7),      /* 224 - 255 */
125 };
126
127 static u_int32_t lapic_timer_divisors[] = { 
128         APIC_TDCR_1, APIC_TDCR_2, APIC_TDCR_4, APIC_TDCR_8, APIC_TDCR_16,
129         APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128
130 };
131
132 volatile lapic_t *lapic;
133 static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
134
135 static void     lapic_enable(void);
136 static void     lapic_timer_enable_intr(void);
137 static void     lapic_timer_oneshot(u_int count);
138 static void     lapic_timer_periodic(u_int count);
139 static void     lapic_timer_set_divisor(u_int divisor);
140 static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
141
142 static uint32_t
143 lvt_mode(struct lapic *la, u_int pin, uint32_t value)
144 {
145         struct lvt *lvt;
146
147         KASSERT(pin <= LVT_MAX, ("%s: pin %u out of range", __func__, pin));
148         if (la->la_lvts[pin].lvt_active)
149                 lvt = &la->la_lvts[pin];
150         else
151                 lvt = &lvts[pin];
152
153         value &= ~(APIC_LVT_M | APIC_LVT_TM | APIC_LVT_IIPP | APIC_LVT_DM |
154             APIC_LVT_VECTOR);
155         if (lvt->lvt_edgetrigger == 0)
156                 value |= APIC_LVT_TM;
157         if (lvt->lvt_activehi == 0)
158                 value |= APIC_LVT_IIPP_INTALO;
159         if (lvt->lvt_masked)
160                 value |= APIC_LVT_M;
161         value |= lvt->lvt_mode;
162         switch (lvt->lvt_mode) {
163         case APIC_LVT_DM_NMI:
164         case APIC_LVT_DM_SMI:
165         case APIC_LVT_DM_INIT:
166         case APIC_LVT_DM_EXTINT:
167                 if (!lvt->lvt_edgetrigger) {
168                         printf("lapic%u: Forcing LINT%u to edge trigger\n",
169                             la->la_id, pin);
170                         value |= APIC_LVT_TM;
171                 }
172                 /* Use a vector of 0. */
173                 break;
174         case APIC_LVT_DM_FIXED:
175                 value |= lvt->lvt_vector;
176                 break;
177         default:
178                 panic("bad APIC LVT delivery mode: %#x\n", value);
179         }
180         return (value);
181 }
182
183 /*
184  * Map the local APIC and setup necessary interrupt vectors.
185  */
186 void
187 lapic_init(uintptr_t addr)
188 {
189
190         /* Map the local APIC and setup the spurious interrupt handler. */
191         KASSERT(trunc_page(addr) == addr,
192             ("local APIC not aligned on a page boundary"));
193         lapic = (lapic_t *)pmap_mapdev(addr, sizeof(lapic_t));
194         setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
195
196         /* Perform basic initialization of the BSP's local APIC. */
197         lapic_enable();
198
199         /* Set BSP's per-CPU local APIC ID. */
200         PCPU_SET(apic_id, lapic_id());
201
202         /* Local APIC timer interrupt. */
203         setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYSIGT, SEL_KPL, 0);
204
205         /* XXX: error/thermal interrupts */
206 }
207
208 /*
209  * Create a local APIC instance.
210  */
211 void
212 lapic_create(u_int apic_id, int boot_cpu)
213 {
214         int i;
215
216         if (apic_id >= MAX_APICID) {
217                 printf("APIC: Ignoring local APIC with ID %d\n", apic_id);
218                 if (boot_cpu)
219                         panic("Can't ignore BSP");
220                 return;
221         }
222         KASSERT(!lapics[apic_id].la_present, ("duplicate local APIC %u",
223             apic_id));
224
225         /*
226          * Assume no local LVT overrides and a cluster of 0 and
227          * intra-cluster ID of 0.
228          */
229         lapics[apic_id].la_present = 1;
230         lapics[apic_id].la_id = apic_id;
231         for (i = 0; i < LVT_MAX; i++) {
232                 lapics[apic_id].la_lvts[i] = lvts[i];
233                 lapics[apic_id].la_lvts[i].lvt_active = 0;
234         }
235
236 #ifdef SMP
237         cpu_add(apic_id, boot_cpu);
238 #endif
239 }
240
241 /*
242  * Dump contents of local APIC registers
243  */
244 void
245 lapic_dump(const char* str)
246 {
247
248         printf("cpu%d %s:\n", PCPU_GET(cpuid), str);
249         printf("     ID: 0x%08x   VER: 0x%08x LDR: 0x%08x DFR: 0x%08x\n",
250             lapic->id, lapic->version, lapic->ldr, lapic->dfr);
251         printf("  lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n",
252             lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr);
253         printf("  timer: 0x%08x therm: 0x%08x err: 0x%08x pcm: 0x%08x\n",
254             lapic->lvt_timer, lapic->lvt_thermal, lapic->lvt_error,
255             lapic->lvt_pcint);
256 }
257
258 void
259 lapic_enable_intr(u_int irq)
260 {
261         u_int vector;
262
263         vector = apic_irq_to_idt(irq);
264         KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
265         KASSERT(ioint_handlers[vector / 32] != NULL,
266             ("No ISR handler for IRQ %u", irq));
267         setidt(vector, ioint_handlers[vector / 32], SDT_SYSIGT, SEL_KPL,  0);
268 }
269
270 void
271 lapic_setup(void)
272 {
273         struct lapic *la;
274         u_int32_t value, maxlvt;
275         register_t eflags;
276         char buf[MAXCOMLEN + 1];
277
278         la = &lapics[lapic_id()];
279         KASSERT(la->la_present, ("missing APIC structure"));
280         eflags = intr_disable();
281         maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
282
283         /* Initialize the TPR to allow all interrupts. */
284         lapic_set_tpr(0);
285
286         /* Use the cluster model for logical IDs. */
287         value = lapic->dfr;
288         value &= ~APIC_DFR_MODEL_MASK;
289         value |= APIC_DFR_MODEL_CLUSTER;
290         lapic->dfr = value;
291
292         /* Set this APIC's logical ID. */
293         value = lapic->ldr;
294         value &= ~APIC_ID_MASK;
295         value |= (la->la_cluster << APIC_ID_CLUSTER_SHIFT |
296             1 << la->la_cluster_id) << APIC_ID_SHIFT;
297         lapic->ldr = value;
298
299         /* Setup spurious vector and enable the local APIC. */
300         lapic_enable();
301
302         /* Program LINT[01] LVT entries. */
303         lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0);
304         lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1);
305 #ifdef  HWPMC_HOOKS
306         /* Program the PMC LVT entry if present. */
307         if (maxlvt >= LVT_PMC)
308                 lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
309 #endif
310
311         /* Program timer LVT and setup handler. */
312         lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
313         snprintf(buf, sizeof(buf), "lapic%d: timer", lapic_id());
314         intrcnt_add(buf, &la->la_timer_count);
315         if (PCPU_GET(cpuid) != 0) {
316                 KASSERT(lapic_timer_period != 0, ("lapic%u: zero divisor",
317                     lapic_id()));
318                 lapic_timer_set_divisor(lapic_timer_divisor);
319                 lapic_timer_periodic(lapic_timer_period);
320                 lapic_timer_enable_intr();
321         }
322
323         /* XXX: Performance counter, error, and thermal LVTs */
324
325         intr_restore(eflags);
326 }
327
328 /*
329  * Called by cpu_initclocks() on the BSP to setup the local APIC timer so
330  * that it can drive hardclock, statclock, and profclock.  This function
331  * returns true if it is able to use the local APIC timer to drive the
332  * clocks and false if it is not able.
333  */
334 int
335 lapic_setup_clock(void)
336 {
337         u_long value;
338
339         /* Can't drive the timer without a local APIC. */
340         if (lapic == NULL)
341                 return (0);
342
343         /* Start off with a divisor of 2 (power on reset default). */
344         lapic_timer_divisor = 2;
345
346         /* Try to calibrate the local APIC timer. */
347         do {
348                 lapic_timer_set_divisor(lapic_timer_divisor);
349                 lapic_timer_oneshot(APIC_TIMER_MAX_COUNT);
350                 DELAY(2000000);
351                 value = APIC_TIMER_MAX_COUNT - lapic->ccr_timer;
352                 if (value != APIC_TIMER_MAX_COUNT)
353                         break;
354                 lapic_timer_divisor <<= 1;
355         } while (lapic_timer_divisor <= 128);
356         if (lapic_timer_divisor > 128)
357                 panic("lapic: Divisor too big");
358         value /= 2;
359         if (bootverbose)
360                 printf("lapic: Divisor %lu, Frequency %lu hz\n",
361                     lapic_timer_divisor, value);
362
363         /*
364          * We will drive the timer at a small multiple of hz and drive
365          * both of the other timers with similarly small but relatively
366          * prime divisors.
367          */
368         lapic_timer_hz = hz * LAPIC_TIMER_HZ_DIVIDER;
369         stathz = lapic_timer_hz / LAPIC_TIMER_STATHZ_DIVIDER;
370         profhz = lapic_timer_hz / LAPIC_TIMER_PROFHZ_DIVIDER;
371         lapic_timer_period = value / lapic_timer_hz;
372
373         /*
374          * Start up the timer on the BSP.  The APs will kick off their
375          * timer during lapic_setup().
376          */
377         lapic_timer_periodic(lapic_timer_period);
378         lapic_timer_enable_intr();
379         return (1);
380 }
381
382 void
383 lapic_disable(void)
384 {
385         uint32_t value;
386
387         /* Software disable the local APIC. */
388         value = lapic->svr;
389         value &= ~APIC_SVR_SWEN;
390         lapic->svr = value;
391 }
392
393 static void
394 lapic_enable(void)
395 {
396         u_int32_t value;
397
398         /* Program the spurious vector to enable the local APIC. */
399         value = lapic->svr;
400         value &= ~(APIC_SVR_VECTOR | APIC_SVR_FOCUS);
401         value |= (APIC_SVR_FEN | APIC_SVR_SWEN | APIC_SPURIOUS_INT);
402         lapic->svr = value;
403 }
404
405 int
406 lapic_id(void)
407 {
408
409         KASSERT(lapic != NULL, ("local APIC is not mapped"));
410         return (lapic->id >> APIC_ID_SHIFT);
411 }
412
413 int
414 lapic_intr_pending(u_int vector)
415 {
416         volatile u_int32_t *irr;
417
418         /*
419          * The IRR registers are an array of 128-bit registers each of
420          * which only describes 32 interrupts in the low 32 bits..  Thus,
421          * we divide the vector by 32 to get the 128-bit index.  We then
422          * multiply that index by 4 to get the equivalent index from
423          * treating the IRR as an array of 32-bit registers.  Finally, we
424          * modulus the vector by 32 to determine the individual bit to
425          * test.
426          */
427         irr = &lapic->irr0;
428         return (irr[(vector / 32) * 4] & 1 << (vector % 32));
429 }
430
431 void
432 lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
433 {
434         struct lapic *la;
435
436         KASSERT(lapics[apic_id].la_present, ("%s: APIC %u doesn't exist",
437             __func__, apic_id));
438         KASSERT(cluster <= APIC_MAX_CLUSTER, ("%s: cluster %u too big",
439             __func__, cluster));
440         KASSERT(cluster_id <= APIC_MAX_INTRACLUSTER_ID,
441             ("%s: intra cluster id %u too big", __func__, cluster_id));
442         la = &lapics[apic_id];
443         la->la_cluster = cluster;
444         la->la_cluster_id = cluster_id;
445 }
446
447 int
448 lapic_set_lvt_mask(u_int apic_id, u_int pin, u_char masked)
449 {
450
451         if (pin > LVT_MAX)
452                 return (EINVAL);
453         if (apic_id == APIC_ID_ALL) {
454                 lvts[pin].lvt_masked = masked;
455                 if (bootverbose)
456                         printf("lapic:");
457         } else {
458                 KASSERT(lapics[apic_id].la_present,
459                     ("%s: missing APIC %u", __func__, apic_id));
460                 lapics[apic_id].la_lvts[pin].lvt_masked = masked;
461                 lapics[apic_id].la_lvts[pin].lvt_active = 1;
462                 if (bootverbose)
463                         printf("lapic%u:", apic_id);
464         }
465         if (bootverbose)
466                 printf(" LINT%u %s\n", pin, masked ? "masked" : "unmasked");
467         return (0);
468 }
469
470 int
471 lapic_set_lvt_mode(u_int apic_id, u_int pin, u_int32_t mode)
472 {
473         struct lvt *lvt;
474
475         if (pin > LVT_MAX)
476                 return (EINVAL);
477         if (apic_id == APIC_ID_ALL) {
478                 lvt = &lvts[pin];
479                 if (bootverbose)
480                         printf("lapic:");
481         } else {
482                 KASSERT(lapics[apic_id].la_present,
483                     ("%s: missing APIC %u", __func__, apic_id));
484                 lvt = &lapics[apic_id].la_lvts[pin];
485                 lvt->lvt_active = 1;
486                 if (bootverbose)
487                         printf("lapic%u:", apic_id);
488         }
489         lvt->lvt_mode = mode;
490         switch (mode) {
491         case APIC_LVT_DM_NMI:
492         case APIC_LVT_DM_SMI:
493         case APIC_LVT_DM_INIT:
494         case APIC_LVT_DM_EXTINT:
495                 lvt->lvt_edgetrigger = 1;
496                 lvt->lvt_activehi = 1;
497                 if (mode == APIC_LVT_DM_EXTINT)
498                         lvt->lvt_masked = 1;
499                 else
500                         lvt->lvt_masked = 0;
501                 break;
502         default:
503                 panic("Unsupported delivery mode: 0x%x\n", mode);
504         }
505         if (bootverbose) {
506                 printf(" Routing ");
507                 switch (mode) {
508                 case APIC_LVT_DM_NMI:
509                         printf("NMI");
510                         break;
511                 case APIC_LVT_DM_SMI:
512                         printf("SMI");
513                         break;
514                 case APIC_LVT_DM_INIT:
515                         printf("INIT");
516                         break;
517                 case APIC_LVT_DM_EXTINT:
518                         printf("ExtINT");
519                         break;
520                 }
521                 printf(" -> LINT%u\n", pin);
522         }
523         return (0);
524 }
525
526 int
527 lapic_set_lvt_polarity(u_int apic_id, u_int pin, enum intr_polarity pol)
528 {
529
530         if (pin > LVT_MAX || pol == INTR_POLARITY_CONFORM)
531                 return (EINVAL);
532         if (apic_id == APIC_ID_ALL) {
533                 lvts[pin].lvt_activehi = (pol == INTR_POLARITY_HIGH);
534                 if (bootverbose)
535                         printf("lapic:");
536         } else {
537                 KASSERT(lapics[apic_id].la_present,
538                     ("%s: missing APIC %u", __func__, apic_id));
539                 lapics[apic_id].la_lvts[pin].lvt_active = 1;
540                 lapics[apic_id].la_lvts[pin].lvt_activehi =
541                     (pol == INTR_POLARITY_HIGH);
542                 if (bootverbose)
543                         printf("lapic%u:", apic_id);
544         }
545         if (bootverbose)
546                 printf(" LINT%u polarity: %s\n", pin,
547                     pol == INTR_POLARITY_HIGH ? "high" : "low");
548         return (0);
549 }
550
551 int
552 lapic_set_lvt_triggermode(u_int apic_id, u_int pin, enum intr_trigger trigger)
553 {
554
555         if (pin > LVT_MAX || trigger == INTR_TRIGGER_CONFORM)
556                 return (EINVAL);
557         if (apic_id == APIC_ID_ALL) {
558                 lvts[pin].lvt_edgetrigger = (trigger == INTR_TRIGGER_EDGE);
559                 if (bootverbose)
560                         printf("lapic:");
561         } else {
562                 KASSERT(lapics[apic_id].la_present,
563                     ("%s: missing APIC %u", __func__, apic_id));
564                 lapics[apic_id].la_lvts[pin].lvt_edgetrigger =
565                     (trigger == INTR_TRIGGER_EDGE);
566                 lapics[apic_id].la_lvts[pin].lvt_active = 1;
567                 if (bootverbose)
568                         printf("lapic%u:", apic_id);
569         }
570         if (bootverbose)
571                 printf(" LINT%u trigger: %s\n", pin,
572                     trigger == INTR_TRIGGER_EDGE ? "edge" : "level");
573         return (0);
574 }
575
576 /*
577  * Adjust the TPR of the current CPU so that it blocks all interrupts below
578  * the passed in vector.
579  */
580 void
581 lapic_set_tpr(u_int vector)
582 {
583 #ifdef CHEAP_TPR
584         lapic->tpr = vector;
585 #else
586         u_int32_t tpr;
587
588         tpr = lapic->tpr & ~APIC_TPR_PRIO;
589         tpr |= vector;
590         lapic->tpr = tpr;
591 #endif
592 }
593
594 void
595 lapic_eoi(void)
596 {
597
598         lapic->eoi = 0;
599 }
600
601 void
602 lapic_handle_intr(void *cookie, struct intrframe frame)
603 {
604         struct intsrc *isrc;
605         int vec = (uintptr_t)cookie;
606
607         if (vec == -1)
608                 panic("Couldn't get vector from ISR!");
609         isrc = intr_lookup_source(apic_idt_to_irq(vec));
610         intr_execute_handlers(isrc, &frame);
611 }
612
613 void
614 lapic_handle_timer(struct clockframe frame)
615 {
616         struct lapic *la;
617
618         la = &lapics[PCPU_GET(apic_id)];
619         (*la->la_timer_count)++;
620         critical_enter();
621
622         /* Fire hardclock at hz. */
623         la->la_hard_ticks += hz;
624         if (la->la_hard_ticks >= lapic_timer_hz) {
625                 la->la_hard_ticks -= lapic_timer_hz;
626                 if (PCPU_GET(cpuid) == 0)
627                         hardclock(&frame);
628                 else
629                         hardclock_process(&frame);
630         }
631
632         /* Fire statclock at stathz. */
633         la->la_stat_ticks += stathz;
634         if (la->la_stat_ticks >= lapic_timer_hz) {
635                 la->la_stat_ticks -= lapic_timer_hz;
636                 statclock(&frame);
637         }
638
639         /* Fire profclock at profhz, but only when needed. */
640         la->la_prof_ticks += profhz;
641         if (la->la_prof_ticks >= lapic_timer_hz) {
642                 la->la_prof_ticks -= lapic_timer_hz;
643                 if (profprocs != 0)
644                         profclock(&frame);
645         }
646         critical_exit();
647 }
648
649 static void
650 lapic_timer_set_divisor(u_int divisor)
651 {
652
653         KASSERT(powerof2(divisor), ("lapic: invalid divisor %u", divisor));
654         KASSERT(ffs(divisor) <= sizeof(lapic_timer_divisors) /
655             sizeof(u_int32_t), ("lapic: invalid divisor %u", divisor));
656         lapic->dcr_timer = lapic_timer_divisors[ffs(divisor) - 1];
657 }
658
659 static void
660 lapic_timer_oneshot(u_int count)
661 {
662         u_int32_t value;
663
664         value = lapic->lvt_timer;
665         value &= ~APIC_LVTT_TM;
666         value |= APIC_LVTT_TM_ONE_SHOT;
667         lapic->lvt_timer = value;
668         lapic->icr_timer = count;
669 }
670
671 static void
672 lapic_timer_periodic(u_int count)
673 {
674         u_int32_t value;
675
676         value = lapic->lvt_timer;
677         value &= ~APIC_LVTT_TM;
678         value |= APIC_LVTT_TM_PERIODIC;
679         lapic->lvt_timer = value;
680         lapic->icr_timer = count;
681 }
682
683 static void
684 lapic_timer_enable_intr(void)
685 {
686         u_int32_t value;
687
688         value = lapic->lvt_timer;
689         value &= ~APIC_LVT_M;
690         lapic->lvt_timer = value;
691 }
692
693 /* Translate between IDT vectors and IRQ vectors. */
694 u_int
695 apic_irq_to_idt(u_int irq)
696 {
697         u_int vector;
698
699         KASSERT(irq < NUM_IO_INTS, ("Invalid IRQ %u", irq));
700         vector = irq + APIC_IO_INTS;
701         if (vector >= IDT_SYSCALL)
702                 vector++;
703         return (vector);
704 }
705
706 u_int
707 apic_idt_to_irq(u_int vector)
708 {
709
710         KASSERT(vector >= APIC_IO_INTS && vector != IDT_SYSCALL &&
711             vector <= APIC_IO_INTS + NUM_IO_INTS,
712             ("Vector %u does not map to an IRQ line", vector));
713         if (vector > IDT_SYSCALL)
714                 vector--;
715         return (vector - APIC_IO_INTS);
716 }
717
718 /*
719  * APIC probing support code.  This includes code to manage enumerators.
720  */
721
722 static SLIST_HEAD(, apic_enumerator) enumerators =
723         SLIST_HEAD_INITIALIZER(enumerators);
724 static struct apic_enumerator *best_enum;
725         
726 void
727 apic_register_enumerator(struct apic_enumerator *enumerator)
728 {
729 #ifdef INVARIANTS
730         struct apic_enumerator *apic_enum;
731
732         SLIST_FOREACH(apic_enum, &enumerators, apic_next) {
733                 if (apic_enum == enumerator)
734                         panic("%s: Duplicate register of %s", __func__,
735                             enumerator->apic_name);
736         }
737 #endif
738         SLIST_INSERT_HEAD(&enumerators, enumerator, apic_next);
739 }
740
741 /*
742  * We have to look for CPU's very, very early because certain subsystems
743  * want to know how many CPU's we have extremely early on in the boot
744  * process.
745  */
746 static void
747 apic_init(void *dummy __unused)
748 {
749         struct apic_enumerator *enumerator;
750         int retval, best;
751
752         /* We only support built in local APICs. */
753         if (!(cpu_feature & CPUID_APIC))
754                 return;
755
756         /* Don't probe if APIC mode is disabled. */
757         if (resource_disabled("apic", 0))
758                 return;
759
760         /* First, probe all the enumerators to find the best match. */
761         best_enum = NULL;
762         best = 0;
763         SLIST_FOREACH(enumerator, &enumerators, apic_next) {
764                 retval = enumerator->apic_probe();
765                 if (retval > 0)
766                         continue;
767                 if (best_enum == NULL || best < retval) {
768                         best_enum = enumerator;
769                         best = retval;
770                 }
771         }
772         if (best_enum == NULL) {
773                 if (bootverbose)
774                         printf("APIC: Could not find any APICs.\n");
775                 return;
776         }
777
778         if (bootverbose)
779                 printf("APIC: Using the %s enumerator.\n",
780                     best_enum->apic_name);
781
782         /* Second, probe the CPU's in the system. */
783         retval = best_enum->apic_probe_cpus();
784         if (retval != 0)
785                 printf("%s: Failed to probe CPUs: returned %d\n",
786                     best_enum->apic_name, retval);
787 }
788 SYSINIT(apic_init, SI_SUB_TUNABLES - 1, SI_ORDER_SECOND, apic_init, NULL)
789
790 /*
791  * Setup the local APIC.  We have to do this prior to starting up the APs
792  * in the SMP case.
793  */
794 static void
795 apic_setup_local(void *dummy __unused)
796 {
797         int retval;
798
799         if (best_enum == NULL)
800                 return;
801         retval = best_enum->apic_setup_local();
802         if (retval != 0)
803                 printf("%s: Failed to setup the local APIC: returned %d\n",
804                     best_enum->apic_name, retval);
805 #ifdef SMP
806         /* Last, setup the cpu topology now that we have probed CPUs */
807         mp_topology();
808 #endif
809 }
810 SYSINIT(apic_setup_local, SI_SUB_CPU, SI_ORDER_FIRST, apic_setup_local, NULL)
811
812 /*
813  * Setup the I/O APICs.
814  */
815 static void
816 apic_setup_io(void *dummy __unused)
817 {
818         int retval;
819
820         if (best_enum == NULL)
821                 return;
822         retval = best_enum->apic_setup_io();
823         if (retval != 0)
824                 printf("%s: Failed to setup I/O APICs: returned %d\n",
825                     best_enum->apic_name, retval);
826
827         /*
828          * Finish setting up the local APIC on the BSP once we know how to
829          * properly program the LINT pins.
830          */
831         lapic_setup();
832         if (bootverbose)
833                 lapic_dump("BSP");
834 }
835 SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_SECOND, apic_setup_io, NULL)
836
837 #ifdef SMP
838 /*
839  * Inter Processor Interrupt functions.  The lapic_ipi_*() functions are
840  * private to the sys/i386 code.  The public interface for the rest of the
841  * kernel is defined in mp_machdep.c.
842  */
843 int
844 lapic_ipi_wait(int delay)
845 {
846         int x, incr;
847
848         /*
849          * Wait delay loops for IPI to be sent.  This is highly bogus
850          * since this is sensitive to CPU clock speed.  If delay is
851          * -1, we wait forever.
852          */
853         if (delay == -1) {
854                 incr = 0;
855                 delay = 1;
856         } else
857                 incr = 1;
858         for (x = 0; x < delay; x += incr) {
859                 if ((lapic->icr_lo & APIC_DELSTAT_MASK) == APIC_DELSTAT_IDLE)
860                         return (1);
861                 ia32_pause();
862         }
863         return (0);
864 }
865
866 void
867 lapic_ipi_raw(register_t icrlo, u_int dest)
868 {
869         register_t value, eflags;
870
871         /* XXX: Need more sanity checking of icrlo? */
872         KASSERT(lapic != NULL, ("%s called too early", __func__));
873         KASSERT((dest & ~(APIC_ID_MASK >> APIC_ID_SHIFT)) == 0,
874             ("%s: invalid dest field", __func__));
875         KASSERT((icrlo & APIC_ICRLO_RESV_MASK) == 0,
876             ("%s: reserved bits set in ICR LO register", __func__));
877
878         /* Set destination in ICR HI register if it is being used. */
879         eflags = intr_disable();
880         if ((icrlo & APIC_DEST_MASK) == APIC_DEST_DESTFLD) {
881                 value = lapic->icr_hi;
882                 value &= ~APIC_ID_MASK;
883                 value |= dest << APIC_ID_SHIFT;
884                 lapic->icr_hi = value;
885         }
886
887         /* Program the contents of the IPI and dispatch it. */
888         value = lapic->icr_lo;
889         value &= APIC_ICRLO_RESV_MASK;
890         value |= icrlo;
891         lapic->icr_lo = value;
892         intr_restore(eflags);
893 }
894
895 #define BEFORE_SPIN     1000000
896 #ifdef DETECT_DEADLOCK
897 #define AFTER_SPIN      1000
898 #endif
899
900 void
901 lapic_ipi_vectored(u_int vector, int dest)
902 {
903         register_t icrlo, destfield;
904
905         KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
906             ("%s: invalid vector %d", __func__, vector));
907
908         icrlo = vector | APIC_DELMODE_FIXED | APIC_DESTMODE_PHY |
909             APIC_LEVEL_DEASSERT | APIC_TRIGMOD_EDGE;
910         destfield = 0;
911         switch (dest) {
912         case APIC_IPI_DEST_SELF:
913                 icrlo |= APIC_DEST_SELF;
914                 break;
915         case APIC_IPI_DEST_ALL:
916                 icrlo |= APIC_DEST_ALLISELF;
917                 break;
918         case APIC_IPI_DEST_OTHERS:
919                 icrlo |= APIC_DEST_ALLESELF;
920                 break;
921         default:
922                 KASSERT((dest & ~(APIC_ID_MASK >> APIC_ID_SHIFT)) == 0,
923                     ("%s: invalid destination 0x%x", __func__, dest));
924                 destfield = dest;
925         }
926
927         /* Wait for an earlier IPI to finish. */
928         if (!lapic_ipi_wait(BEFORE_SPIN))
929                 panic("APIC: Previous IPI is stuck");
930
931         lapic_ipi_raw(icrlo, destfield);
932
933 #ifdef DETECT_DEADLOCK
934         /* Wait for IPI to be delivered. */
935         if (!lapic_ipi_wait(AFTER_SPIN)) {
936 #ifdef needsattention
937                 /*
938                  * XXX FIXME:
939                  *
940                  * The above function waits for the message to actually be
941                  * delivered.  It breaks out after an arbitrary timeout
942                  * since the message should eventually be delivered (at
943                  * least in theory) and that if it wasn't we would catch
944                  * the failure with the check above when the next IPI is
945                  * sent.
946                  *
947                  * We could skip this wait entirely, EXCEPT it probably
948                  * protects us from other routines that assume that the
949                  * message was delivered and acted upon when this function
950                  * returns.
951                  */
952                 printf("APIC: IPI might be stuck\n");
953 #else /* !needsattention */
954                 /* Wait until mesage is sent without a timeout. */
955                 while (lapic->icr_lo & APIC_DELSTAT_PEND)
956                         ia32_pause();
957 #endif /* needsattention */
958         }
959 #endif /* DETECT_DEADLOCK */
960 }
961 #endif /* SMP */