The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/x86/x86/local_apic.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: bd6d490920f74670a7371aadb387d4a1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.