pc64: Make read_apic_timer() return remaining time in microseconds.
[dragonfly.git] / sys / platform / pc64 / apic / lapic.c
1 /*
2  * Copyright (c) 1996, by Steve Passe
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. The name of the developer may NOT be used to endorse or promote products
11  *    derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $
26  */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kernel.h>
31 #include <sys/bus.h>
32 #include <sys/machintr.h>
33 #include <machine/globaldata.h>
34 #include <machine/clock.h>
35 #include <machine/smp.h>
36 #include <machine/md_var.h>
37 #include <machine/pmap.h>
38 #include <machine/specialreg.h>
39 #include <machine_base/apic/lapic.h>
40 #include <machine_base/apic/ioapic.h>
41 #include <machine_base/apic/ioapic_abi.h>
42 #include <machine_base/apic/apicvar.h>
43 #include <machine_base/icu/icu_var.h>
44 #include <machine/segments.h>
45 #include <sys/thread2.h>
46 #include <sys/spinlock2.h>
47
48 #include <machine/cputypes.h>
49 #include <machine/intr_machdep.h>
50
51 extern int naps;
52
53 volatile lapic_t *lapic;
54
55 static void     lapic_timer_calibrate(void);
56 static void     lapic_timer_set_divisor(int);
57 static void     lapic_timer_fixup_handler(void *);
58 static void     lapic_timer_restart_handler(void *);
59
60
61 static int      lapic_timer_enable = 1;
62 TUNABLE_INT("hw.lapic_timer_enable", &lapic_timer_enable);
63
64 static void     lapic_timer_intr_reload(struct cputimer_intr *, sysclock_t);
65 static void     lapic_timer_intr_enable(struct cputimer_intr *);
66 static void     lapic_timer_intr_restart(struct cputimer_intr *);
67 static void     lapic_timer_intr_pmfixup(struct cputimer_intr *);
68
69 static struct cputimer_intr lapic_cputimer_intr = {
70         .freq = 0,
71         .reload = lapic_timer_intr_reload,
72         .enable = lapic_timer_intr_enable,
73         .config = cputimer_intr_default_config,
74         .restart = lapic_timer_intr_restart,
75         .pmfixup = lapic_timer_intr_pmfixup,
76         .initclock = cputimer_intr_default_initclock,
77         .pcpuhand = NULL,
78         .next = SLIST_ENTRY_INITIALIZER,
79         .name = "lapic",
80         .type = CPUTIMER_INTR_LAPIC,
81         .prio = CPUTIMER_INTR_PRIO_LAPIC,
82         .caps = CPUTIMER_INTR_CAP_NONE,
83         .priv = NULL
84 };
85
86 static int              lapic_timer_divisor_idx = -1;
87 static const uint32_t   lapic_timer_divisors[] = {
88         APIC_TDCR_2,    APIC_TDCR_4,    APIC_TDCR_8,    APIC_TDCR_16,
89         APIC_TDCR_32,   APIC_TDCR_64,   APIC_TDCR_128,  APIC_TDCR_1
90 };
91 #define APIC_TIMER_NDIVISORS (int)(NELEM(lapic_timer_divisors))
92
93 /*
94  * APIC ID <-> CPU ID mapping structures.
95  */
96 int     cpu_id_to_apic_id[NAPICID];
97 int     apic_id_to_cpu_id[NAPICID];
98 int     lapic_enable = 1;
99
100 /*
101  * Enable LAPIC, configure interrupts.
102  */
103 void
104 lapic_init(boolean_t bsp)
105 {
106         uint32_t timer;
107         u_int   temp;
108
109         /*
110          * Install vectors
111          *
112          * Since IDT is shared between BSP and APs, these vectors
113          * only need to be installed once; we do it on BSP.
114          */
115         if (bsp) {
116                 if (cpu_vendor_id == CPU_VENDOR_AMD &&
117                     CPUID_TO_FAMILY(cpu_id) >= 0x0f &&
118                     CPUID_TO_FAMILY(cpu_id) < 0x17) {   /* XXX */
119                         uint32_t tcr;
120
121                         /*
122                          * Set the LINTEN bit in the HyperTransport
123                          * Transaction Control Register.
124                          *
125                          * This will cause EXTINT and NMI interrupts
126                          * routed over the hypertransport bus to be
127                          * fed into the LAPIC LINT0/LINT1.  If the bit
128                          * isn't set, the interrupts will go to the
129                          * general cpu INTR/NMI pins.  On a dual-core
130                          * cpu the interrupt winds up going to BOTH cpus.
131                          * The first cpu that does the interrupt ack
132                          * cycle will get the correct interrupt.  The
133                          * second cpu that does it will get a spurious
134                          * interrupt vector (typically IRQ 7).
135                          */
136                         outl(0x0cf8,
137                             (1 << 31) | /* enable */
138                             (0 << 16) | /* bus */
139                             (0x18 << 11) | /* dev (cpu + 0x18) */
140                             (0 << 8) |  /* func */
141                             0x68        /* reg */
142                             );
143                         tcr = inl(0xcfc);
144                         if ((tcr & 0x00010000) == 0) {
145                                 kprintf("LAPIC: AMD LINTEN on\n");
146                                 outl(0xcfc, tcr|0x00010000);
147                         }
148                         outl(0x0cf8, 0);
149                 }
150
151                 /* Install a 'Spurious INTerrupt' vector */
152                 setidt_global(XSPURIOUSINT_OFFSET, Xspuriousint,
153                     SDT_SYSIGT, SEL_KPL, 0);
154
155                 /* Install a timer vector */
156                 setidt_global(XTIMER_OFFSET, Xtimer,
157                     SDT_SYSIGT, SEL_KPL, 0);
158
159                 /* Install an inter-CPU IPI for TLB invalidation */
160                 setidt_global(XINVLTLB_OFFSET, Xinvltlb,
161                     SDT_SYSIGT, SEL_KPL, 0);
162
163                 /* Install an inter-CPU IPI for IPIQ messaging */
164                 setidt_global(XIPIQ_OFFSET, Xipiq,
165                     SDT_SYSIGT, SEL_KPL, 0);
166
167                 /* Install an inter-CPU IPI for CPU stop/restart */
168                 setidt_global(XCPUSTOP_OFFSET, Xcpustop,
169                     SDT_SYSIGT, SEL_KPL, 0);
170
171                 /* Install an inter-CPU IPI for TLB invalidation */
172                 setidt_global(XSNIFF_OFFSET, Xsniff,
173                     SDT_SYSIGT, SEL_KPL, 0);
174         }
175
176         /*
177          * Setup LINT0 as ExtINT on the BSP.  This is theoretically an
178          * aggregate interrupt input from the 8259.  The INTA cycle
179          * will be routed to the external controller (the 8259) which
180          * is expected to supply the vector.
181          *
182          * Must be setup edge triggered, active high.
183          *
184          * Disable LINT0 on BSP, if I/O APIC is enabled.
185          *
186          * Disable LINT0 on the APs.  It doesn't matter what delivery
187          * mode we use because we leave it masked.
188          */
189         temp = lapic->lvt_lint0;
190         temp &= ~(APIC_LVT_MASKED | APIC_LVT_TRIG_MASK | 
191                   APIC_LVT_POLARITY_MASK | APIC_LVT_DM_MASK);
192         if (bsp) {
193                 temp |= APIC_LVT_DM_EXTINT;
194                 if (ioapic_enable)
195                         temp |= APIC_LVT_MASKED;
196         } else {
197                 temp |= APIC_LVT_DM_FIXED | APIC_LVT_MASKED;
198         }
199         lapic->lvt_lint0 = temp;
200
201         /*
202          * Setup LINT1 as NMI.
203          *
204          * Must be setup edge trigger, active high.
205          *
206          * Enable LINT1 on BSP, if I/O APIC is enabled.
207          *
208          * Disable LINT1 on the APs.
209          */
210         temp = lapic->lvt_lint1;
211         temp &= ~(APIC_LVT_MASKED | APIC_LVT_TRIG_MASK | 
212                   APIC_LVT_POLARITY_MASK | APIC_LVT_DM_MASK);
213         temp |= APIC_LVT_MASKED | APIC_LVT_DM_NMI;
214         if (bsp && ioapic_enable)
215                 temp &= ~APIC_LVT_MASKED;
216         lapic->lvt_lint1 = temp;
217
218         /*
219          * Mask the LAPIC error interrupt, LAPIC performance counter
220          * interrupt.
221          */
222         lapic->lvt_error = lapic->lvt_error | APIC_LVT_MASKED;
223         lapic->lvt_pcint = lapic->lvt_pcint | APIC_LVT_MASKED;
224
225         /*
226          * Set LAPIC timer vector and mask the LAPIC timer interrupt.
227          */
228         timer = lapic->lvt_timer;
229         timer &= ~APIC_LVTT_VECTOR;
230         timer |= XTIMER_OFFSET;
231         timer |= APIC_LVTT_MASKED;
232         lapic->lvt_timer = timer;
233
234         /*
235          * Set the Task Priority Register as needed.   At the moment allow
236          * interrupts on all cpus (the APs will remain CLId until they are
237          * ready to deal).
238          */
239         temp = lapic->tpr;
240         temp &= ~APIC_TPR_PRIO;         /* clear priority field */
241         lapic->tpr = temp;
242
243         /*
244          * AMD specific setup
245          */
246         if (cpu_vendor_id == CPU_VENDOR_AMD &&
247             (lapic->version & APIC_VER_AMD_EXT_SPACE)) {
248                 uint32_t ext_feat;
249                 uint32_t count;
250                 uint32_t max_count;
251                 uint32_t lvt;
252                 uint32_t i;
253
254                 ext_feat = lapic->ext_feat;
255                 count = (ext_feat & APIC_EXTFEAT_MASK) >> APIC_EXTFEAT_SHIFT;
256                 max_count = sizeof(lapic->ext_lvt) / sizeof(lapic->ext_lvt[0]);
257                 if (count > max_count)
258                         count = max_count;
259                 for (i = 0; i < count; ++i) {
260                         lvt = lapic->ext_lvt[i].lvt;
261
262                         lvt &= ~(APIC_LVT_POLARITY_MASK | APIC_LVT_TRIG_MASK |
263                                  APIC_LVT_DM_MASK | APIC_LVT_MASKED);
264                         lvt |= APIC_LVT_MASKED | APIC_LVT_DM_FIXED;
265
266                         switch(i) {
267                         case APIC_EXTLVT_IBS:
268                                 break;
269                         case APIC_EXTLVT_MCA:
270                                 break;
271                         case APIC_EXTLVT_DEI:
272                                 break;
273                         case APIC_EXTLVT_SBI:
274                                 break;
275                         default:
276                                 break;
277                         }
278                         if (bsp) {
279                                 kprintf("   LAPIC AMD elvt%d: 0x%08x",
280                                         i, lapic->ext_lvt[i].lvt);
281                                 if (lapic->ext_lvt[i].lvt != lvt)
282                                         kprintf(" -> 0x%08x", lvt);
283                                 kprintf("\n");
284                         }
285                         lapic->ext_lvt[i].lvt = lvt;
286                 }
287         }
288
289         /* 
290          * Enable the LAPIC 
291          */
292         temp = lapic->svr;
293         temp |= APIC_SVR_ENABLE;        /* enable the LAPIC */
294         temp &= ~APIC_SVR_FOCUS_DISABLE; /* enable lopri focus processor */
295
296         if (lapic->version & APIC_VER_EOI_SUPP) {
297                 if (temp & APIC_SVR_EOI_SUPP) {
298                         temp &= ~APIC_SVR_EOI_SUPP;
299                         if (bsp)
300                                 kprintf("    LAPIC disabling EOI supp\n");
301                 }
302         }
303
304         /*
305          * Set the spurious interrupt vector.  The low 4 bits of the vector
306          * must be 1111.
307          */
308         if ((XSPURIOUSINT_OFFSET & 0x0F) != 0x0F)
309                 panic("bad XSPURIOUSINT_OFFSET: 0x%08x", XSPURIOUSINT_OFFSET);
310         temp &= ~APIC_SVR_VECTOR;
311         temp |= XSPURIOUSINT_OFFSET;
312
313         lapic->svr = temp;
314
315         /*
316          * Pump out a few EOIs to clean out interrupts that got through
317          * before we were able to set the TPR.
318          */
319         lapic->eoi = 0;
320         lapic->eoi = 0;
321         lapic->eoi = 0;
322
323         if (bsp) {
324                 lapic_timer_calibrate();
325                 if (lapic_timer_enable) {
326                         if (cpu_thermal_feature & CPUID_THERMAL_ARAT) {
327                                 /*
328                                  * Local APIC timer will not stop
329                                  * in deep C-state.
330                                  */
331                                 lapic_cputimer_intr.caps |=
332                                     CPUTIMER_INTR_CAP_PS;
333                         }
334                         cputimer_intr_register(&lapic_cputimer_intr);
335                         cputimer_intr_select(&lapic_cputimer_intr, 0);
336                 }
337         } else {
338                 lapic_timer_set_divisor(lapic_timer_divisor_idx);
339         }
340
341         if (bootverbose)
342                 apic_dump("apic_initialize()");
343 }
344
345 static void
346 lapic_timer_set_divisor(int divisor_idx)
347 {
348         KKASSERT(divisor_idx >= 0 && divisor_idx < APIC_TIMER_NDIVISORS);
349         lapic->dcr_timer = lapic_timer_divisors[divisor_idx];
350 }
351
352 static void
353 lapic_timer_oneshot(u_int count)
354 {
355         uint32_t value;
356
357         value = lapic->lvt_timer;
358         value &= ~APIC_LVTT_PERIODIC;
359         lapic->lvt_timer = value;
360         lapic->icr_timer = count;
361 }
362
363 static void
364 lapic_timer_oneshot_quick(u_int count)
365 {
366         lapic->icr_timer = count;
367 }
368
369 static void
370 lapic_timer_calibrate(void)
371 {
372         sysclock_t value;
373
374         /* Try to calibrate the local APIC timer. */
375         for (lapic_timer_divisor_idx = 0;
376              lapic_timer_divisor_idx < APIC_TIMER_NDIVISORS;
377              lapic_timer_divisor_idx++) {
378                 lapic_timer_set_divisor(lapic_timer_divisor_idx);
379                 lapic_timer_oneshot(APIC_TIMER_MAX_COUNT);
380                 DELAY(2000000);
381                 value = APIC_TIMER_MAX_COUNT - lapic->ccr_timer;
382                 if (value != APIC_TIMER_MAX_COUNT)
383                         break;
384         }
385         if (lapic_timer_divisor_idx >= APIC_TIMER_NDIVISORS)
386                 panic("lapic: no proper timer divisor?!");
387         lapic_cputimer_intr.freq = value / 2;
388
389         kprintf("lapic: divisor index %d, frequency %u Hz\n",
390                 lapic_timer_divisor_idx, lapic_cputimer_intr.freq);
391 }
392
393 static void
394 lapic_timer_intr_reload(struct cputimer_intr *cti, sysclock_t reload)
395 {
396         struct globaldata *gd = mycpu;
397
398         reload = (int64_t)reload * cti->freq / sys_cputimer->freq;
399         if (reload < 2)
400                 reload = 2;
401
402         if (gd->gd_timer_running) {
403                 if (reload < lapic->ccr_timer)
404                         lapic_timer_oneshot_quick(reload);
405         } else {
406                 gd->gd_timer_running = 1;
407                 lapic_timer_oneshot_quick(reload);
408         }
409 }
410
411 static void
412 lapic_timer_intr_enable(struct cputimer_intr *cti __unused)
413 {
414         uint32_t timer;
415
416         timer = lapic->lvt_timer;
417         timer &= ~(APIC_LVTT_MASKED | APIC_LVTT_PERIODIC);
418         lapic->lvt_timer = timer;
419
420         lapic_timer_fixup_handler(NULL);
421 }
422
423 static void
424 lapic_timer_fixup_handler(void *arg)
425 {
426         int *started = arg;
427
428         if (started != NULL)
429                 *started = 0;
430
431         if (cpu_vendor_id == CPU_VENDOR_AMD) {
432                 /*
433                  * Detect the presence of C1E capability mostly on latest
434                  * dual-cores (or future) k8 family.  This feature renders
435                  * the local APIC timer dead, so we disable it by reading
436                  * the Interrupt Pending Message register and clearing both
437                  * C1eOnCmpHalt (bit 28) and SmiOnCmpHalt (bit 27).
438                  * 
439                  * Reference:
440                  *   "BIOS and Kernel Developer's Guide for AMD NPT
441                  *    Family 0Fh Processors"
442                  *   #32559 revision 3.00
443                  */
444                 if ((cpu_id & 0x00000f00) == 0x00000f00 &&
445                     (cpu_id & 0x0fff0000) >= 0x00040000) {
446                         uint64_t msr;
447
448                         msr = rdmsr(0xc0010055);
449                         if (msr & 0x18000000) {
450                                 struct globaldata *gd = mycpu;
451
452                                 kprintf("cpu%d: AMD C1E detected\n",
453                                         gd->gd_cpuid);
454                                 wrmsr(0xc0010055, msr & ~0x18000000ULL);
455
456                                 /*
457                                  * We are kinda stalled;
458                                  * kick start again.
459                                  */
460                                 gd->gd_timer_running = 1;
461                                 lapic_timer_oneshot_quick(2);
462
463                                 if (started != NULL)
464                                         *started = 1;
465                         }
466                 }
467         }
468 }
469
470 static void
471 lapic_timer_restart_handler(void *dummy __unused)
472 {
473         int started;
474
475         lapic_timer_fixup_handler(&started);
476         if (!started) {
477                 struct globaldata *gd = mycpu;
478
479                 gd->gd_timer_running = 1;
480                 lapic_timer_oneshot_quick(2);
481         }
482 }
483
484 /*
485  * This function is called only by ACPICA code currently:
486  * - AMD C1E fixup.  AMD C1E only seems to happen after ACPI
487  *   module controls PM.  So once ACPICA is attached, we try
488  *   to apply the fixup to prevent LAPIC timer from hanging.
489  */
490 static void
491 lapic_timer_intr_pmfixup(struct cputimer_intr *cti __unused)
492 {
493         lwkt_send_ipiq_mask(smp_active_mask,
494                             lapic_timer_fixup_handler, NULL);
495 }
496
497 static void
498 lapic_timer_intr_restart(struct cputimer_intr *cti __unused)
499 {
500         lwkt_send_ipiq_mask(smp_active_mask, lapic_timer_restart_handler, NULL);
501 }
502
503
504 /*
505  * dump contents of local APIC registers
506  */
507 void
508 apic_dump(char* str)
509 {
510         kprintf("SMP: CPU%d %s:\n", mycpu->gd_cpuid, str);
511         kprintf("     lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n",
512                 lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr);
513 }
514
515 /*
516  * Inter Processor Interrupt functions.
517  */
518
519 /*
520  * Send APIC IPI 'vector' to 'destType' via 'deliveryMode'.
521  *
522  *  destType is 1 of: APIC_DEST_SELF, APIC_DEST_ALLISELF, APIC_DEST_ALLESELF
523  *  vector is any valid SYSTEM INT vector
524  *  delivery_mode is 1 of: APIC_DELMODE_FIXED, APIC_DELMODE_LOWPRIO
525  *
526  * WARNINGS!
527  *
528  * We now implement a per-cpu interlock (gd->gd_npoll) to prevent more than
529  * one IPI from being sent to any given cpu at a time.  Thus we no longer
530  * have to process incoming IPIs while waiting for the status to clear.
531  * No deadlock should be possible.
532  *
533  * We now physically disable interrupts for the lapic ICR operation.  If
534  * we do not do this then it looks like an EOI sent to the lapic (which
535  * occurs even with a critical section) can interfere with the command
536  * register ready status and cause an IPI to be lost.
537  *
538  * e.g. an interrupt can occur, issue the EOI, IRET, and cause the command
539  * register to busy just before we write to icr_lo, resulting in a lost
540  * issuance.  This only appears to occur on Intel cpus and is not
541  * documented.  It could simply be that cpus are so fast these days that
542  * it was always an issue, but is only now rearing its ugly head.  This
543  * is conjecture.
544  */
545 int
546 apic_ipi(int dest_type, int vector, int delivery_mode)
547 {
548         uint32_t icr_hi;
549         uint32_t icr_lo;
550         int64_t tsc;
551         int loops = 1;
552
553         if ((lapic->icr_lo & APIC_DELSTAT_MASK) != 0) {
554                 tsc = rdtsc();
555                 while ((lapic->icr_lo & APIC_DELSTAT_MASK) != 0) {
556                         cpu_pause();
557                         if ((int64_t)(rdtsc() - (tsc + tsc_frequency)) > 0) {
558                                 kprintf("apic_ipi stall cpu %d (sing)\n",
559                                         mycpuid);
560                                 tsc = rdtsc();
561                                 if (++loops > 30)
562                                         panic("apic stall");
563                         }
564                 }
565         }
566         icr_hi = lapic->icr_hi & ~APIC_ID_MASK;
567         icr_lo = (lapic->icr_lo & APIC_ICRLO_RESV_MASK) | dest_type | 
568                  APIC_LEVEL_ASSERT | delivery_mode | vector;
569         lapic->icr_hi = icr_hi;
570         lapic->icr_lo = icr_lo;
571
572         return 0;
573 }
574
575 /*
576  * Interrupts must be hard-disabled by caller
577  */
578 void
579 single_apic_ipi(int cpu, int vector, int delivery_mode)
580 {
581         uint32_t  icr_lo;
582         uint32_t  icr_hi;
583         int64_t tsc;
584         int loops = 1;
585
586         if ((lapic->icr_lo & APIC_DELSTAT_MASK) != 0) {
587                 tsc = rdtsc();
588                 while ((lapic->icr_lo & APIC_DELSTAT_MASK) != 0) {
589                         cpu_pause();
590                         if ((int64_t)(rdtsc() - (tsc + tsc_frequency)) > 0) {
591                                 kprintf("single_apic_ipi stall cpu %d (sing)\n",
592                                         mycpuid);
593                                 tsc = rdtsc();
594                                 if (++loops > 30)
595                                         panic("apic stall");
596                         }
597                 }
598         }
599         icr_hi = lapic->icr_hi & ~APIC_ID_MASK;
600         icr_hi |= (CPUID_TO_APICID(cpu) << 24);
601
602         /* build ICR_LOW */
603         icr_lo = (lapic->icr_lo & APIC_ICRLO_RESV_MASK) |
604                  APIC_LEVEL_ASSERT | APIC_DEST_DESTFLD | delivery_mode | vector;
605
606         /* write APIC ICR */
607         lapic->icr_hi = icr_hi;
608         lapic->icr_lo = icr_lo;
609 }
610
611 #if 0   
612
613 /*
614  * Returns 0 if the apic is busy, 1 if we were able to queue the request.
615  *
616  * NOT WORKING YET!  The code as-is may end up not queueing an IPI at all
617  * to the target, and the scheduler does not 'poll' for IPI messages.
618  */
619 int
620 single_apic_ipi_passive(int cpu, int vector, int delivery_mode)
621 {
622         u_long  icr_lo;
623         u_long  icr_hi;
624         unsigned long rflags;
625
626         rflags = read_rflags();
627         cpu_disable_intr();
628         if ((lapic->icr_lo & APIC_DELSTAT_MASK) != 0) {
629                 write_rflags(rflags);
630                 return(0);
631         }
632         icr_hi = lapic->icr_hi & ~APIC_ID_MASK;
633         icr_hi |= (CPUID_TO_APICID(cpu) << 24);
634         lapic->icr_hi = icr_hi;
635
636         /* build IRC_LOW */
637         icr_lo = (lapic->icr_lo & APIC_RESV2_MASK) |
638                  APIC_DEST_DESTFLD | delivery_mode | vector;
639
640         /* write APIC ICR */
641         lapic->icr_lo = icr_lo;
642         write_rflags(rflags);
643
644         return(1);
645 }
646
647 #endif
648
649 /*
650  * Send APIC IPI 'vector' to 'target's via 'delivery_mode'.
651  *
652  * target is a bitmask of destination cpus.  Vector is any
653  * valid system INT vector.  Delivery mode may be either
654  * APIC_DELMODE_FIXED or APIC_DELMODE_LOWPRIO.
655  *
656  * Interrupts must be hard-disabled by caller
657  */
658 void
659 selected_apic_ipi(cpumask_t target, int vector, int delivery_mode)
660 {
661         while (CPUMASK_TESTNZERO(target)) {
662                 int n = BSFCPUMASK(target);
663                 CPUMASK_NANDBIT(target, n);
664                 single_apic_ipi(n, vector, delivery_mode);
665         }
666 }
667
668 /*
669  * Timer code, in development...
670  *  - suggested by rgrimes@gndrsh.aac.dev.com
671  */
672 int
673 get_apic_timer_frequency(void)
674 {
675         return(lapic_cputimer_intr.freq);
676 }
677
678 /*
679  * Load a 'downcount time' in uSeconds.
680  */
681 void
682 set_apic_timer(int us)
683 {
684         u_int count;
685
686         /*
687          * When we reach here, lapic timer's frequency
688          * must have been calculated as well as the
689          * divisor (lapic->dcr_timer is setup during the
690          * divisor calculation).
691          */
692         KKASSERT(lapic_cputimer_intr.freq != 0 &&
693                  lapic_timer_divisor_idx >= 0);
694
695         count = ((us * (int64_t)lapic_cputimer_intr.freq) + 999999) / 1000000;
696         lapic_timer_oneshot(count);
697 }
698
699
700 /*
701  * Read remaining time in timer, in microseconds (rounded up).
702  */
703 int
704 read_apic_timer(void)
705 {
706         uint64_t val;
707
708         val = lapic->ccr_timer;
709         if (val == 0)
710                 return 0;
711         KKASSERT(lapic_cputimer_intr.freq > 0);
712         val *= 1000000;
713         val += (lapic_cputimer_intr.freq - 1);
714         val /= lapic_cputimer_intr.freq;
715         if (val > 0x7fffffff)
716                 val = 0x7fffffff;
717         return val;
718 }
719
720
721 /*
722  * Spin-style delay, set delay time in uS, spin till it drains.
723  */
724 void
725 u_sleep(int count)
726 {
727         set_apic_timer(count);
728         while (read_apic_timer())
729                  /* spin */ ;
730 }
731
732 int
733 lapic_unused_apic_id(int start)
734 {
735         int i;
736
737         for (i = start; i < APICID_MAX; ++i) {
738                 if (APICID_TO_CPUID(i) == -1)
739                         return i;
740         }
741         return NAPICID;
742 }
743
744 void
745 lapic_map(vm_paddr_t lapic_addr)
746 {
747         lapic = pmap_mapdev_uncacheable(lapic_addr, sizeof(struct LAPIC));
748 }
749
750 static TAILQ_HEAD(, lapic_enumerator) lapic_enumerators =
751         TAILQ_HEAD_INITIALIZER(lapic_enumerators);
752
753 int
754 lapic_config(void)
755 {
756         struct lapic_enumerator *e;
757         int error, i, ap_max;
758
759         KKASSERT(lapic_enable);
760
761         for (i = 0; i < NAPICID; ++i)
762                 APICID_TO_CPUID(i) = -1;
763
764         TAILQ_FOREACH(e, &lapic_enumerators, lapic_link) {
765                 error = e->lapic_probe(e);
766                 if (!error)
767                         break;
768         }
769         if (e == NULL) {
770                 kprintf("LAPIC: Can't find LAPIC\n");
771                 return ENXIO;
772         }
773
774         error = e->lapic_enumerate(e);
775         if (error) {
776                 kprintf("LAPIC: enumeration failed\n");
777                 return ENXIO;
778         }
779
780         ap_max = MAXCPU - 1;
781         TUNABLE_INT_FETCH("hw.ap_max", &ap_max);
782         if (ap_max > MAXCPU - 1)
783                 ap_max = MAXCPU - 1;
784
785         if (naps > ap_max) {
786                 kprintf("LAPIC: Warning use only %d out of %d "
787                         "available APs\n",
788                         ap_max, naps);
789                 naps = ap_max;
790         }
791
792         return 0;
793 }
794
795 void
796 lapic_enumerator_register(struct lapic_enumerator *ne)
797 {
798         struct lapic_enumerator *e;
799
800         TAILQ_FOREACH(e, &lapic_enumerators, lapic_link) {
801                 if (e->lapic_prio < ne->lapic_prio) {
802                         TAILQ_INSERT_BEFORE(e, ne, lapic_link);
803                         return;
804                 }
805         }
806         TAILQ_INSERT_TAIL(&lapic_enumerators, ne, lapic_link);
807 }
808
809 void
810 lapic_set_cpuid(int cpu_id, int apic_id)
811 {
812         CPUID_TO_APICID(cpu_id) = apic_id;
813         APICID_TO_CPUID(apic_id) = cpu_id;
814 }
815
816 void
817 lapic_fixup_noioapic(void)
818 {
819         u_int   temp;
820
821         /* Only allowed on BSP */
822         KKASSERT(mycpuid == 0);
823         KKASSERT(!ioapic_enable);
824
825         temp = lapic->lvt_lint0;
826         temp &= ~APIC_LVT_MASKED;
827         lapic->lvt_lint0 = temp;
828
829         temp = lapic->lvt_lint1;
830         temp |= APIC_LVT_MASKED;
831         lapic->lvt_lint1 = temp;
832 }
833
834 static void
835 lapic_sysinit(void *dummy __unused)
836 {
837         if (lapic_enable) {
838                 int error;
839
840                 error = lapic_config();
841                 if (error)
842                         lapic_enable = 0;
843         }
844
845         if (lapic_enable) {
846                 /* Initialize BSP's local APIC */
847                 lapic_init(TRUE);
848         } else if (ioapic_enable) {
849                 ioapic_enable = 0;
850                 icu_reinit_noioapic();
851         }
852 }
853 SYSINIT(lapic, SI_BOOT2_LAPIC, SI_ORDER_FIRST, lapic_sysinit, NULL);