1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*
  26  * Copyright (c) 2010, Intel Corporation.
  27  * All rights reserved.
  28  */
  29 
  30 #ifndef _SYS_APIC_APIC_H
  31 #define _SYS_APIC_APIC_H
  32 
  33 #include <sys/psm_types.h>
  34 #include <sys/avintr.h>
  35 #include <sys/pci.h>
  36 
  37 #ifdef  __cplusplus
  38 extern "C" {
  39 #endif
  40 
  41 #include <sys/psm_common.h>
  42 
  43 #define APIC_PCPLUSMP_NAME      "pcplusmp"
  44 #define APIC_APIX_NAME          "apix"
  45 
  46 #define APIC_IO_ADDR    0xfec00000
  47 #define APIC_LOCAL_ADDR 0xfee00000
  48 #define APIC_IO_MEMLEN  0xf
  49 #define APIC_LOCAL_MEMLEN       0xfffff
  50 
  51 /* Local Unit ID register */
  52 #define APIC_LID_REG            0x8
  53 
  54 /* I/o Unit Version Register */
  55 #define APIC_VERS_REG           0xc
  56 
  57 /* Task Priority register */
  58 #define APIC_TASK_REG           0x20
  59 
  60 /* EOI register */
  61 #define APIC_EOI_REG            0x2c
  62 
  63 /* Remote Read register         */
  64 #define APIC_REMOTE_READ        0x30
  65 
  66 /* Logical Destination register */
  67 #define APIC_DEST_REG           0x34
  68 
  69 /* Destination Format register */
  70 #define APIC_FORMAT_REG         0x38
  71 
  72 /* Spurious Interrupt Vector register */
  73 #define APIC_SPUR_INT_REG       0x3c
  74 
  75 /* Error Status Register */
  76 #define APIC_ERROR_STATUS       0xa0
  77 
  78 /* Interrupt Command registers */
  79 #define APIC_INT_CMD1           0xc0
  80 #define APIC_INT_CMD2           0xc4
  81 
  82 /* Local Interrupt Vector registers */
  83 #define APIC_CMCI_VECT          0xbc
  84 #define APIC_THERM_VECT         0xcc
  85 #define APIC_PCINT_VECT         0xd0
  86 #define APIC_INT_VECT0          0xd4
  87 #define APIC_INT_VECT1          0xd8
  88 #define APIC_ERR_VECT           0xdc
  89 
  90 /* IPL for performance counter interrupts */
  91 #define APIC_PCINT_IPL          0xe
  92 #define APIC_LVT_MASK           0x10000         /* Mask bit (16) in LVT */
  93 
  94 /* Initial Count register */
  95 #define APIC_INIT_COUNT         0xe0
  96 
  97 /* Current Count Register */
  98 #define APIC_CURR_COUNT         0xe4
  99 #define APIC_CURR_ADD           0x39    /* used for remote read command */
 100 #define CURR_COUNT_OFFSET       (sizeof (int32_t) * APIC_CURR_COUNT)
 101 
 102 /* Divider Configuration Register */
 103 #define APIC_DIVIDE_REG         0xf8
 104 
 105 /* Various mode for local APIC. Modes are mutually exclusive  */
 106 typedef enum apic_mode {
 107         APIC_IS_DISABLED = 0,
 108         APIC_MODE_NOTSET,
 109         LOCAL_APIC,
 110         LOCAL_X2APIC
 111 } apic_mode_t;
 112 
 113 /* x2APIC SELF IPI Register */
 114 #define X2APIC_SELF_IPI         0xFC
 115 
 116 /* General x2APIC constants used at various places */
 117 #define APIC_SVR_SUPPRESS_BROADCAST_EOI         0x1000
 118 #define APIC_DIRECTED_EOI_BIT                   0x1000000
 119 
 120 /* IRR register */
 121 #define APIC_IRR_REG            0x80
 122 
 123 /* ISR register */
 124 #define APIC_ISR_REG            0x40
 125 
 126 #define APIC_IO_REG             0x0
 127 #define APIC_IO_DATA            0x4
 128 #define APIC_IO_EOI             0x10
 129 
 130 /* Bit offset of APIC ID in LID_REG, INT_CMD and in DEST_REG */
 131 #define APIC_ID_BIT_OFFSET      24
 132 #define APIC_ICR_ID_BIT_OFFSET  24
 133 #define APIC_LDR_ID_BIT_OFFSET  24
 134 
 135 /*
 136  * Choose between flat and clustered models by writing the following to the
 137  * FORMAT_REG. 82489 DX documentation seemed to suggest that writing 0 will
 138  * disable logical destination mode.
 139  * Does not seem to be in the docs for local APICs on the processors.
 140  */
 141 #define APIC_FLAT_MODEL         0xFFFFFFFFUL
 142 #define APIC_CLUSTER_MODEL      0x0FFFFFFF
 143 
 144 /*
 145  * The commands which follow are window selectors written to APIC_IO_REG
 146  * before data can be read/written from/to APIC_IO_DATA
 147  */
 148 
 149 #define APIC_ID_CMD             0x0
 150 #define APIC_VERS_CMD           0x1
 151 #define APIC_RDT_CMD            0x10
 152 #define APIC_RDT_CMD2           0x11
 153 
 154 #define APIC_INTEGRATED_VERS    0x10    /* 0x10 & above indicates integrated */
 155 #define IOAPIC_VER_82489DX      0x01    /* Version ID: 82489DX External APIC */
 156 
 157 #define APIC_INT_SPURIOUS       -1
 158 
 159 #define APIC_IMCR_P1    0x22            /* int mode conf register port 1 */
 160 #define APIC_IMCR_P2    0x23            /* int mode conf register port 2 */
 161 #define APIC_IMCR_SELECT 0x70           /* select imcr by writing into P1 */
 162 #define APIC_IMCR_PIC   0x0             /* selects PIC mode (8259-> BSP) */
 163 #define APIC_IMCR_APIC  0x1             /* selects APIC mode (8259->APIC) */
 164 
 165 #define APIC_CT_VECT    0x4ac           /* conf table vector            */
 166 #define APIC_CT_SIZE    1024            /* conf table size              */
 167 
 168 #define APIC_ID         'MPAT'          /* conf table signature         */
 169 
 170 #define VENID_AMD               0x1022
 171 #define DEVID_8131_IOAPIC       0x7451
 172 #define DEVID_8132_IOAPIC       0x7459
 173 
 174 #define IOAPICS_NODE_NAME       "ioapics"
 175 #define IOAPICS_CHILD_NAME      "ioapic"
 176 #define IOAPICS_DEV_TYPE        "ioapic"
 177 #define IOAPICS_PROP_VENID      "vendor-id"
 178 #define IOAPICS_PROP_DEVID      "device-id"
 179 
 180 #define IS_CLASS_IOAPIC(b, s, p) \
 181         ((b) == PCI_CLASS_PERIPH && (s) == PCI_PERIPH_PIC &&    \
 182         ((p) == PCI_PERIPH_PIC_IF_IO_APIC ||                    \
 183         (p) == PCI_PERIPH_PIC_IF_IOX_APIC))
 184 
 185 /*
 186  * These macros are used in frequently called routines like
 187  * apic_intr_enter().
 188  */
 189 #define X2APIC_WRITE(reg, v) \
 190         wrmsr((REG_X2APIC_BASE_MSR + (reg >> 2)), v)
 191 
 192 #define LOCAL_APIC_WRITE_REG(reg, v) \
 193         apicadr[reg] = v
 194 
 195 /*
 196  * MP floating pointer structure defined in Intel MP Spec 1.1
 197  */
 198 struct apic_mpfps_hdr {
 199         uint32_t        mpfps_sig;      /* _MP_ (0x5F4D505F)            */
 200         uint32_t        mpfps_mpct_paddr; /* paddr of MP configuration tbl */
 201         uchar_t mpfps_length;           /* in paragraph (16-bytes units) */
 202         uchar_t mpfps_spec_rev;         /* version number of MP spec     */
 203         uchar_t mpfps_checksum;         /* checksum of complete structure */
 204         uchar_t mpfps_featinfo1;        /* mp feature info bytes 1       */
 205         uchar_t mpfps_featinfo2;        /* mp feature info bytes 2       */
 206         uchar_t mpfps_featinfo3;        /* mp feature info bytes 3       */
 207         uchar_t mpfps_featinfo4;        /* mp feature info bytes 4       */
 208         uchar_t mpfps_featinfo5;        /* mp feature info bytes 5       */
 209 };
 210 
 211 #define MPFPS_FEATINFO2_IMCRP           0x80    /* IMCRP presence bit   */
 212 
 213 #define APIC_MPS_OEM_ID_LEN             8
 214 #define APIC_MPS_PROD_ID_LEN            12
 215 
 216 struct apic_mp_cnf_hdr {
 217         uint_t  mpcnf_sig;
 218 
 219         uint_t  mpcnf_tbl_length:       16,
 220                 mpcnf_spec:             8,
 221                 mpcnf_cksum:            8;
 222 
 223         char    mpcnf_oem_str[APIC_MPS_OEM_ID_LEN];
 224 
 225         char    mpcnf_prod_str[APIC_MPS_PROD_ID_LEN];
 226 
 227         uint_t  mpcnf_oem_ptr;
 228 
 229         uint_t  mpcnf_oem_tbl_size:     16,
 230                 mpcnf_entry_cnt:        16;
 231 
 232         uint_t  mpcnf_local_apic;
 233 
 234         uint_t  mpcnf_resv;
 235 };
 236 
 237 struct apic_procent {
 238         uint_t  proc_entry:             8,
 239                 proc_apicid:            8,
 240                 proc_version:           8,
 241                 proc_cpuflags:          8;
 242 
 243         uint_t  proc_stepping:          4,
 244                 proc_model:             4,
 245                 proc_family:            4,
 246                 proc_type:              2,      /* undocumented feature */
 247                 proc_resv1:             18;
 248 
 249         uint_t  proc_feature;
 250 
 251         uint_t  proc_resv2;
 252 
 253         uint_t  proc_resv3;
 254 };
 255 
 256 /*
 257  * proc_cpuflags definitions
 258  */
 259 #define CPUFLAGS_EN     1       /* if not set, this processor is unusable */
 260 #define CPUFLAGS_BP     2       /* set if this is the bootstrap processor */
 261 
 262 
 263 struct apic_bus {
 264         uchar_t bus_entry;
 265         uchar_t bus_id;
 266         ushort_t        bus_str1;
 267         uint_t  bus_str2;
 268 };
 269 
 270 struct apic_io_entry {
 271         uint_t  io_entry:               8,
 272                 io_apicid:              8,
 273                 io_version:             8,
 274                 io_flags:               8;
 275 
 276         uint_t  io_apic_addr;
 277 };
 278 
 279 #define IOAPIC_FLAGS_EN         0x01    /* this I/O apic is enable or not */
 280 
 281 #define MAX_IO_APIC             32      /* maximum # of IOAPICs supported */
 282 
 283 struct apic_io_intr {
 284         uint_t  intr_entry:             8,
 285                 intr_type:              8,
 286                 intr_po:                2,
 287                 intr_el:                2,
 288                 intr_resv:              12;
 289 
 290         uint_t  intr_busid:             8,
 291                 intr_irq:               8,
 292                 intr_destid:            8,
 293                 intr_destintin:         8;
 294 };
 295 
 296 /*
 297  * intr_type definitions
 298  */
 299 #define IO_INTR_INT     0x00
 300 #define IO_INTR_NMI     0x01
 301 #define IO_INTR_SMI     0x02
 302 #define IO_INTR_EXTINT  0x03
 303 
 304 /*
 305  * destination APIC ID
 306  */
 307 #define INTR_ALL_APIC           0xff
 308 
 309 
 310 /* local vector table                                                   */
 311 #define AV_MASK         0x10000
 312 
 313 /* interrupt command register 32-63                                     */
 314 #define AV_TOALL        0x7fffffff
 315 #define AV_HIGH_ORDER   0x40000000
 316 #define AV_IM_OFF       0x40000000
 317 
 318 /* interrupt command register 0-31                                      */
 319 #define AV_DELIV_MODE   0x700
 320 
 321 #define AV_FIXED        0x000
 322 #define AV_LOPRI        0x100
 323 #define AV_SMI          0x200
 324 #define AV_REMOTE       0x300
 325 #define AV_NMI          0x400
 326 #define AV_RESET        0x500
 327 #define AV_STARTUP      0x600
 328 #define AV_EXTINT       0x700
 329 
 330 #define AV_PDEST        0x000
 331 #define AV_LDEST        0x800
 332 
 333 /* IO & Local APIC Bit Definitions */
 334 #define RDT_VECTOR(x)   ((uchar_t)((x) & 0xFF))
 335 #define AV_PENDING      0x1000
 336 #define AV_ACTIVE_LOW   0x2000          /* only for integrated APIC */
 337 #define AV_REMOTE_IRR   0x4000          /* IOAPIC RDT-specific */
 338 #define AV_LEVEL        0x8000
 339 #define AV_DEASSERT     AV_LEVEL
 340 #define AV_ASSERT       0xc000
 341 
 342 #define AV_READ_PENDING 0x10000
 343 #define AV_REMOTE_STATUS        0x20000 /* 1 = valid, 0 = invalid */
 344 
 345 #define AV_SH_SELF              0x40000 /* Short hand for self */
 346 #define AV_SH_ALL_INCSELF       0x80000 /* All processors */
 347 #define AV_SH_ALL_EXCSELF       0xc0000 /* All excluding self */
 348 /* spurious interrupt vector register                                   */
 349 #define AV_UNIT_ENABLE  0x100
 350 
 351 #define APIC_MAXVAL     0xffffffffUL
 352 #define APIC_TIME_MIN   0x5000
 353 #define APIC_TIME_COUNT 0x4000
 354 
 355 /*
 356  * Range of the low byte value in apic_tick before starting calibration
 357  */
 358 #define APIC_LB_MIN     0x60
 359 #define APIC_LB_MAX     0xe0
 360 
 361 #define APIC_MAX_VECTOR         255
 362 #define APIC_RESV_VECT          0x00
 363 #define APIC_RESV_IRQ           0xfe
 364 #define APIC_BASE_VECT          0x20    /* This will come in as interrupt 0 */
 365 #define APIC_AVAIL_VECTOR       (APIC_MAX_VECTOR+1-APIC_BASE_VECT)
 366 #define APIC_VECTOR_PER_IPL     0x10    /* # of vectors before PRI changes */
 367 #define APIC_VECTOR(ipl)        (apic_ipltopri[ipl] | APIC_RESV_VECT)
 368 #define APIC_VECTOR_MASK        0x0f
 369 #define APIC_HI_PRI_VECTS       2       /* vects reserved for hi pri reqs */
 370 #define APIC_IPL_MASK           0xf0
 371 #define APIC_IPL_SHIFT          4       /* >> to get ipl part of vector */
 372 #define APIC_FIRST_FREE_IRQ     0x10
 373 #define APIC_MAX_ISA_IRQ        15
 374 #define APIC_IPL0               0x0f    /* let IDLE_IPL be the lowest */
 375 #define APIC_IDLE_IPL           0x00
 376 
 377 #define APIC_MASK_ALL           0xf0    /* Mask all interrupts */
 378 
 379 /* spurious interrupt vector                                            */
 380 #define APIC_SPUR_INTR          0xFF
 381 
 382 /* special or reserve vectors */
 383 #define APIC_CHECK_RESERVE_VECTORS(v) \
 384         (((v) == T_FASTTRAP) || ((v) == APIC_SPUR_INTR) || \
 385         ((v) == T_SYSCALLINT) || ((v) == T_DTRACE_RET))
 386 
 387 /* cmos shutdown code for BIOS                                          */
 388 #define BIOS_SHUTDOWN           0x0a
 389 
 390 /* define the entry types for BIOS information tables as defined in PC+MP */
 391 #define APIC_CPU_ENTRY          0
 392 #define APIC_BUS_ENTRY          1
 393 #define APIC_IO_ENTRY           2
 394 #define APIC_IO_INTR_ENTRY      3
 395 #define APIC_LOCAL_INTR_ENTRY   4
 396 #define APIC_MPTBL_ADDR         (639 * 1024)
 397 /*
 398  * The MP Floating Point structure could be in 1st 1KB of EBDA or last KB
 399  * of system base memory or in ROM between 0xF0000 and 0xFFFFF
 400  */
 401 #define MPFPS_RAM_WIN_LEN       1024
 402 #define MPFPS_ROM_WIN_START     (uint32_t)0xf0000
 403 #define MPFPS_ROM_WIN_LEN       0x10000
 404 
 405 #define EISA_LEVEL_CNTL         0x4D0
 406 
 407 /* definitions for apic_irq_table */
 408 #define FREE_INDEX              (short)-1       /* empty slot */
 409 #define RESERVE_INDEX           (short)-2       /* ipi, softintr, clkintr */
 410 #define ACPI_INDEX              (short)-3       /* ACPI */
 411 #define MSI_INDEX               (short)-4       /* MSI */
 412 #define MSIX_INDEX              (short)-5       /* MSI-X */
 413 #define DEFAULT_INDEX           (short)0x7FFF
 414         /* biggest positive no. to avoid conflict with actual index */
 415 
 416 #define APIC_IS_MSI_OR_MSIX_INDEX(index) \
 417         ((index) == MSI_INDEX || (index) == MSIX_INDEX)
 418 
 419 /*
 420  * definitions for MSI Address
 421  */
 422 #define MSI_ADDR_HDR            APIC_LOCAL_ADDR
 423 #define MSI_ADDR_DEST_SHIFT     12      /* Destination CPU's apic id */
 424 #define MSI_ADDR_RH_FIXED       0x0     /* Redirection Hint Fixed */
 425 #define MSI_ADDR_RH_LOPRI       0x1     /* Redirection Hint Lowest priority */
 426 #define MSI_ADDR_RH_SHIFT       3
 427 #define MSI_ADDR_DM_PHYSICAL    0x0     /* Physical Destination Mode */
 428 #define MSI_ADDR_DM_LOGICAL     0x1     /* Logical Destination Mode */
 429 #define MSI_ADDR_DM_SHIFT       2
 430 
 431 /*
 432  * TM is either edge or level.
 433  */
 434 #define TRIGGER_MODE_EDGE               0x0     /* edge sensitive */
 435 #define TRIGGER_MODE_LEVEL              0x1     /* level sensitive */
 436 
 437 /*
 438  * definitions for MSI Data
 439  */
 440 #define MSI_DATA_DELIVERY_FIXED         0x0     /* Fixed delivery */
 441 #define MSI_DATA_DELIVERY_LOPRI         0x1     /* Lowest priority delivery */
 442 #define MSI_DATA_DELIVERY_SMI           0x2
 443 #define MSI_DATA_DELIVERY_NMI           0x4
 444 #define MSI_DATA_DELIVERY_INIT          0x5
 445 #define MSI_DATA_DELIVERY_EXTINT        0x7
 446 #define MSI_DATA_DELIVERY_SHIFT         8
 447 #define MSI_DATA_TM_EDGE                TRIGGER_MODE_EDGE
 448 #define MSI_DATA_TM_LEVEL               TRIGGER_MODE_LEVEL
 449 #define MSI_DATA_TM_SHIFT               15
 450 #define MSI_DATA_LEVEL_DEASSERT         0x0
 451 #define MSI_DATA_LEVEL_ASSERT           0x1     /* Edge always assert */
 452 #define MSI_DATA_LEVEL_SHIFT            14
 453 
 454 /*
 455  * use to define each irq setup by the apic
 456  */
 457 typedef struct  apic_irq {
 458         short   airq_mps_intr_index;    /* index into mps interrupt entries */
 459                                         /*  table */
 460         uchar_t airq_intin_no;
 461         uchar_t airq_ioapicindex;
 462         dev_info_t      *airq_dip; /* device corresponding to this interrupt */
 463         /*
 464          * IRQ could be shared (in H/W) in which case dip & major will be
 465          * for the one that was last added at this level. We cannot keep a
 466          * linked list as delspl does not tell us which device has just
 467          * been unloaded. For most servers where we are worried about
 468          * performance, interrupt should not be shared & should not be
 469          * a problem. This does not cause any correctness issue - dip is
 470          * used only as an optimisation to avoid going thru all the tables
 471          * in translate IRQ (which is always called twice due to brokenness
 472          * in the way IPLs are determined for devices). major is used only
 473          * to bind interrupts corresponding to the same device on the same
 474          * CPU. Not finding major will just cause it to be potentially bound
 475          * to another CPU.
 476          */
 477         major_t airq_major;     /* major number corresponding to the device */
 478         ushort_t airq_rdt_entry;        /* level, polarity & trig mode */
 479         uint32_t airq_cpu;              /* target CPU, non-reserved IRQ only */
 480         uint32_t airq_temp_cpu;   /* non-reserved IRQ only, for disable_intr */
 481         uchar_t airq_vector;            /* Vector chosen for this irq */
 482         uchar_t airq_share;             /* number of interrupts at this irq */
 483         uchar_t airq_share_id;          /* id to identify source from irqno */
 484         uchar_t airq_ipl;               /* The ipl at which this is handled */
 485         iflag_t airq_iflag;             /* interrupt flag */
 486         uchar_t airq_origirq;           /* original irq passed in */
 487         uint_t  airq_busy;              /* How frequently did clock find */
 488                                         /* us in this */
 489         struct apic_irq *airq_next;     /* chain of intpts sharing a vector */
 490         void            *airq_intrmap_private; /* intr remap private data */
 491 } apic_irq_t;
 492 
 493 #define IRQ_USER_BOUND  0x80000000 /* user requested bind if set in airq_cpu */
 494 #define IRQ_UNBOUND     (uint32_t)-1    /* set in airq_cpu and airq_temp_cpu */
 495 #define IRQ_UNINIT      (uint32_t)-2 /* in airq_temp_cpu till addspl called */
 496 
 497 /* Macros to help deal with shared interrupts */
 498 #define VIRTIRQ(irqno, share_id)        ((irqno) | ((share_id) << 8))
 499 #define IRQINDEX(irq)   ((irq) & 0xFF)      /* Mask to get irq from virtual irq */
 500 
 501 /*
 502  * We align apic_cpus_info at 64-byte cache line boundary. Please make sure we
 503  * adjust APIC_PADSZ as we add/modify any member of apic_cpus_info. We also
 504  * don't want the compiler to optimize apic_cpus_info.
 505  */
 506 #define APIC_PADSZ      15
 507 
 508 #pragma pack(1)
 509 typedef struct apic_cpus_info {
 510         uint32_t aci_local_id;
 511         uchar_t aci_local_ver;
 512         uchar_t aci_status;
 513         uchar_t aci_redistribute;       /* Selected for redistribution */
 514         uint_t  aci_busy;               /* Number of ticks we were in ISR */
 515         uint_t  aci_spur_cnt;           /* # of spurious intpts on this cpu */
 516         uint_t  aci_ISR_in_progress;    /* big enough to hold 1 << MAXIPL */
 517         uchar_t aci_curipl;             /* IPL of current ISR */
 518         uchar_t aci_current[MAXIPL];    /* Current IRQ at each IPL */
 519         uint32_t aci_bound;             /* # of user requested binds ? */
 520         uint32_t aci_temp_bound;        /* # of non user IRQ binds */
 521         uint32_t aci_processor_id;      /* Only used in ACPI mode. */
 522         uchar_t aci_idle;               /* The CPU is idle */
 523         /*
 524          * Fill to make sure each struct is in separate 64-byte cache line.
 525          */
 526         uchar_t aci_pad[APIC_PADSZ];    /* padding for 64-byte cache line */
 527 } apic_cpus_info_t;
 528 #pragma pack()
 529 
 530 #define APIC_CPU_ONLINE         0x1
 531 #define APIC_CPU_INTR_ENABLE    0x2
 532 #define APIC_CPU_FREE           0x4     /* APIC CPU slot is free */
 533 #define APIC_CPU_DIRTY          0x8     /* Slot was once used */
 534 #define APIC_CPU_SUSPEND        0x10
 535 
 536 /*
 537  * APIC ops to support various flavors of APIC like APIC and x2APIC.
 538  */
 539 typedef struct apic_regs_ops {
 540         uint64_t        (*apic_read)(uint32_t);
 541         void            (*apic_write)(uint32_t, uint64_t);
 542         int             (*apic_get_pri)(void);
 543         void            (*apic_write_task_reg)(uint64_t);
 544         void            (*apic_write_int_cmd)(uint32_t, uint32_t);
 545         void            (*apic_send_eoi)(uint32_t);
 546 } apic_reg_ops_t;
 547 
 548 /*
 549  * interrupt structure for ioapic and msi
 550  */
 551 typedef struct ioapic_rdt {
 552         uint32_t        ir_lo;
 553         uint32_t        ir_hi;
 554 } ioapic_rdt_t;
 555 
 556 typedef struct msi_regs {
 557         uint32_t        mr_data;
 558         uint64_t        mr_addr;
 559 }msi_regs_t;
 560 
 561 /*
 562  * APIC ops to support intel interrupt remapping
 563  */
 564 typedef struct apic_intrmap_ops {
 565         int     (*apic_intrmap_init)(int);
 566         void    (*apic_intrmap_enable)(int);
 567         void    (*apic_intrmap_alloc_entry)(void **, dev_info_t *, uint16_t,
 568                     int, uchar_t);
 569         void    (*apic_intrmap_map_entry)(void *, void *, uint16_t, int);
 570         void    (*apic_intrmap_free_entry)(void **);
 571         void    (*apic_intrmap_record_rdt)(void *, ioapic_rdt_t *);
 572         void    (*apic_intrmap_record_msi)(void *, msi_regs_t *);
 573 } apic_intrmap_ops_t;
 574 
 575 /*
 576  * Various poweroff methods and ports & bits for them
 577  */
 578 #define APIC_POWEROFF_NONE              0
 579 #define APIC_POWEROFF_VIA_RTC           1
 580 #define APIC_POWEROFF_VIA_ASPEN_BMC     2
 581 #define APIC_POWEROFF_VIA_SITKA_BMC     3
 582 
 583 /* For RTC */
 584 #define RTC_REGA                0x0a
 585 #define PFR_REG                 0x4a    /* extended control register */
 586 #define PAB_CBIT                0x08
 587 #define WF_FLAG                 0x02
 588 #define KS_FLAG                 0x01
 589 #define EXT_BANK                0x10
 590 
 591 /* For Aspen/Drake BMC */
 592 
 593 #define CC_SMS_GET_STATUS       0x40
 594 #define CC_SMS_WR_START         0x41
 595 #define CC_SMS_WR_NEXT          0x42
 596 #define CC_SMS_WR_END           0x43
 597 
 598 #define MISMIC_DATA_REGISTER    0x0ca9
 599 #define MISMIC_CNTL_REGISTER    0x0caa
 600 #define MISMIC_FLAG_REGISTER    0x0cab
 601 
 602 #define MISMIC_BUSY_MASK        0x01
 603 
 604 /* For Sitka/Cabrillo BMC */
 605 
 606 #define SMS_GET_STATUS          0x60
 607 #define SMS_WRITE_START         0x61
 608 #define SMS_WRITE_END           0x62
 609 
 610 #define SMS_DATA_REGISTER       0x0ca2
 611 #define SMS_STATUS_REGISTER     0x0ca3
 612 #define SMS_COMMAND_REGISTER    0x0ca3
 613 
 614 #define SMS_IBF_MASK            0x02
 615 #define SMS_STATE_MASK          0xc0
 616 
 617 #define SMS_IDLE_STATE          0x00
 618 #define SMS_READ_STATE          0x40
 619 #define SMS_WRITE_STATE         0x80
 620 #define SMS_ERROR_STATE         0xc0
 621 
 622 extern uint32_t ioapic_read(int ioapic_ix, uint32_t reg);
 623 extern void ioapic_write(int ioapic_ix, uint32_t reg, uint32_t value);
 624 extern void ioapic_write_eoi(int ioapic_ix, uint32_t value);
 625 
 626 /* Macros for reading/writing the IOAPIC RDT entries */
 627 #define READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, ipin) \
 628         ioapic_read(ioapic_ix, APIC_RDT_CMD + (2 * (ipin)))
 629 
 630 #define READ_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic_ix, ipin) \
 631         ioapic_read(ioapic_ix, APIC_RDT_CMD2 + (2 * (ipin)))
 632 
 633 #define WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, ipin, value) \
 634         ioapic_write(ioapic_ix, APIC_RDT_CMD + (2 * (ipin)), value)
 635 
 636 #define WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic_ix, ipin, value) \
 637         ioapic_write(ioapic_ix, APIC_RDT_CMD2 + (2 * (ipin)), value)
 638 
 639 /* Used by PSM_INTR_OP_GET_INTR to return device information. */
 640 typedef struct {
 641         uint16_t        avgi_req_flags; /* request flags - to kernel */
 642         uint8_t         avgi_num_devs;  /* # devs on this ino - from kernel */
 643         uint8_t         avgi_vector;    /* vector */
 644         uint32_t        avgi_cpu_id;    /* cpu of interrupt - from kernel */
 645         dev_info_t      **avgi_dip_list; /* kmem_alloc'ed list of dev_infos. */
 646                                         /* Contains num_devs elements. */
 647 } apic_get_intr_t;
 648 
 649 /* Used by PSM_INTR_OP_GET_TYPE to return platform information. */
 650 typedef struct {
 651         char            *avgi_type;     /*  platform type - from kernel */
 652         uint32_t        avgi_num_intr;  /*  max intr number - from kernel */
 653         uint32_t        avgi_num_cpu;   /*  max cpu number - from kernel */
 654 } apic_get_type_t;
 655 
 656 /* Masks for avgi_req_flags. */
 657 #define PSMGI_REQ_CPUID         0x1     /* Request CPU ID */
 658 #define PSMGI_REQ_NUM_DEVS      0x2     /* Request num of devices on vector */
 659 #define PSMGI_REQ_VECTOR        0x4
 660 #define PSMGI_REQ_GET_DEVS      0x8     /* Request device list */
 661 #define PSMGI_REQ_ALL           0xf     /* Request everything */
 662 
 663 /* Other flags */
 664 #define PSMGI_INTRBY_VEC        0       /* Vec passed.  xlate to IRQ needed */
 665 #define PSMGI_INTRBY_IRQ        0x8000  /* IRQ passed.  no xlate needed */
 666 #define PSMGI_INTRBY_DEFAULT    0x4000  /* PSM specific default value */
 667 #define PSMGI_INTRBY_FLAGS      0xc000  /* Mask for this flag */
 668 
 669 extern int      apic_verbose;
 670 
 671 /* Flag definitions for apic_verbose */
 672 #define APIC_VERBOSE_IOAPIC_FLAG                0x00000001
 673 #define APIC_VERBOSE_IRQ_FLAG                   0x00000002
 674 #define APIC_VERBOSE_POWEROFF_FLAG              0x00000004
 675 #define APIC_VERBOSE_POWEROFF_PAUSE_FLAG        0x00000008
 676 #define APIC_VERBOSE_INIT                       0x00000010
 677 #define APIC_VERBOSE_REBIND                     0x00000020
 678 #define APIC_VERBOSE_ALLOC                      0x00000040
 679 #define APIC_VERBOSE_IPI                        0x00000080
 680 #define APIC_VERBOSE_INTR                       0x00000100
 681 
 682 /* required test to wait until APIC command is sent on the bus */
 683 #define APIC_AV_PENDING_SET() \
 684         while (apic_reg_ops->apic_read(APIC_INT_CMD1) & AV_PENDING) \
 685                 apic_ret();
 686 
 687 #ifdef  DEBUG
 688 
 689 #define DENT            0x0001
 690 extern int      apic_debug;
 691 /*
 692  * set apic_restrict_vector to the # of vectors we want to allow per range
 693  * useful in testing shared interrupt logic by setting it to 2 or 3
 694  */
 695 extern int      apic_restrict_vector;
 696 
 697 #define APIC_DEBUG_MSGBUFSIZE   2048
 698 extern int      apic_debug_msgbuf[];
 699 extern int      apic_debug_msgbufindex;
 700 
 701 /*
 702  * Put "int" info into debug buffer. No MP consistency, but light weight.
 703  * Good enough for most debugging.
 704  */
 705 #define APIC_DEBUG_BUF_PUT(x) \
 706         apic_debug_msgbuf[apic_debug_msgbufindex++] = x; \
 707         if (apic_debug_msgbufindex >= (APIC_DEBUG_MSGBUFSIZE - NCPU)) \
 708                 apic_debug_msgbufindex = 0;
 709 
 710 #define APIC_VERBOSE(flag, fmt)                      \
 711         if (apic_verbose & APIC_VERBOSE_##flag) \
 712                 cmn_err fmt;
 713 
 714 #define APIC_VERBOSE_POWEROFF(fmt) \
 715         if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) \
 716                 prom_printf fmt;
 717 
 718 #else   /* DEBUG */
 719 
 720 #define APIC_VERBOSE(flag, fmt)
 721 #define APIC_VERBOSE_POWEROFF(fmt)
 722 
 723 #endif  /* DEBUG */
 724 
 725 #define APIC_VERBOSE_IOAPIC(fmt)        APIC_VERBOSE(IOAPIC_FLAG, fmt)
 726 #define APIC_VERBOSE_IRQ(fmt)           APIC_VERBOSE(IRQ_FLAG, fmt)
 727 
 728 extern int      apic_error;
 729 /* values which apic_error can take. Not catastrophic, but may help debug */
 730 #define APIC_ERR_BOOT_EOI               0x1
 731 #define APIC_ERR_GET_IPIVECT_FAIL       0x2
 732 #define APIC_ERR_INVALID_INDEX          0x4
 733 #define APIC_ERR_MARK_VECTOR_FAIL       0x8
 734 #define APIC_ERR_APIC_ERROR             0x40000000
 735 #define APIC_ERR_NMI                    0x80000000
 736 
 737 /*
 738  * ACPI definitions
 739  */
 740 /* _PIC method arguments */
 741 #define ACPI_PIC_MODE   0
 742 #define ACPI_APIC_MODE  1
 743 
 744 /* APIC error flags we care about */
 745 #define APIC_SEND_CS_ERROR      0x01
 746 #define APIC_RECV_CS_ERROR      0x02
 747 #define APIC_CS_ERRORS          (APIC_SEND_CS_ERROR|APIC_RECV_CS_ERROR)
 748 
 749 /* Maximum number of times to retry reprogramming at apic_intr_exit time */
 750 #define APIC_REPROGRAM_MAX_TRIES 10000
 751 
 752 /* Parameter to ioapic_init_intr(): Should ioapic ints be masked? */
 753 #define IOAPIC_MASK 1
 754 #define IOAPIC_NOMASK 0
 755 
 756 #define INTR_ROUND_ROBIN_WITH_AFFINITY  0
 757 #define INTR_ROUND_ROBIN                1
 758 #define INTR_LOWEST_PRIORITY            2
 759 
 760 struct ioapic_reprogram_data {
 761         boolean_t                       done;
 762         apic_irq_t                      *irqp;
 763         /* The CPU to which the int will be bound */
 764         int                             bindcpu;
 765         /* # times the reprogram timeout was called */
 766         unsigned                        tries;
 767 };
 768 
 769 /* The irq # is implicit in the array index: */
 770 extern struct ioapic_reprogram_data apic_reprogram_info[];
 771 
 772 extern void apic_intr_exit(int ipl, int irq);
 773 extern void x2apic_intr_exit(int ipl, int irq);
 774 extern int apic_probe_common();
 775 extern void apic_init_common();
 776 extern void ioapic_init_intr();
 777 extern void ioapic_disable_redirection();
 778 extern int apic_addspl_common(int irqno, int ipl, int min_ipl, int max_ipl);
 779 extern int apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl);
 780 extern void apic_cleanup_busy();
 781 extern void apic_intr_redistribute();
 782 extern uchar_t apic_xlate_vector(uchar_t vector);
 783 extern uchar_t apic_allocate_vector(int ipl, int irq, int pri);
 784 extern void apic_free_vector(uchar_t vector);
 785 extern int apic_allocate_irq(int irq);
 786 extern uint32_t apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid,
 787     uchar_t intin);
 788 extern int apic_rebind(apic_irq_t *irq_ptr, int bind_cpu,
 789     struct ioapic_reprogram_data *drep);
 790 extern int apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu);
 791 extern int apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type);
 792 extern int apic_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp,
 793     psm_intr_op_t intr_op, int *result);
 794 extern int apic_state(psm_state_request_t *);
 795 extern boolean_t apic_cpu_in_range(int cpu);
 796 extern int apic_check_msi_support();
 797 extern apic_irq_t *apic_find_irq(dev_info_t *dip, struct intrspec *ispec,
 798     int type);
 799 extern int apic_navail_vector(dev_info_t *dip, int pri);
 800 extern int apic_alloc_msi_vectors(dev_info_t *dip, int inum, int count,
 801     int pri, int behavior);
 802 extern int apic_alloc_msix_vectors(dev_info_t *dip, int inum, int count,
 803     int pri, int behavior);
 804 extern void  apic_free_vectors(dev_info_t *dip, int inum, int count, int pri,
 805     int type);
 806 extern int apic_get_vector_intr_info(int vecirq,
 807     apic_get_intr_t *intr_params_p);
 808 extern uchar_t apic_find_multi_vectors(int pri, int count);
 809 extern int apic_setup_io_intr(void *p, int irq, boolean_t deferred);
 810 extern uint32_t *mapin_apic(uint32_t addr, size_t len, int flags);
 811 extern uint32_t *mapin_ioapic(uint32_t addr, size_t len, int flags);
 812 extern void mapout_apic(caddr_t addr, size_t len);
 813 extern void mapout_ioapic(caddr_t addr, size_t len);
 814 extern uchar_t apic_modify_vector(uchar_t vector, int irq);
 815 extern void apic_pci_msi_unconfigure(dev_info_t *rdip, int type, int inum);
 816 extern void apic_pci_msi_disable_mode(dev_info_t *rdip, int type);
 817 extern void apic_pci_msi_enable_mode(dev_info_t *rdip, int type, int inum);
 818 extern void apic_pci_msi_enable_vector(apic_irq_t *, int type, int inum,
 819     int vector, int count, int target_apic_id);
 820 extern char *apic_get_apic_type();
 821 extern uint16_t apic_get_apic_version();
 822 extern void x2apic_send_ipi();
 823 extern void apic_ret();
 824 extern int apic_detect_x2apic();
 825 extern void apic_enable_x2apic();
 826 extern int apic_local_mode();
 827 extern void apic_change_eoi();
 828 extern void apic_send_EOI(uint32_t);
 829 extern void apic_send_directed_EOI(uint32_t);
 830 extern uint_t apic_calibrate(volatile uint32_t *, uint16_t *);
 831 
 832 extern volatile uint32_t *apicadr;      /* virtual addr of local APIC   */
 833 extern int apic_forceload;
 834 extern apic_cpus_info_t *apic_cpus;
 835 #ifdef _MACHDEP
 836 extern cpuset_t apic_cpumask;
 837 #endif
 838 extern uint_t apic_picinit_called;
 839 extern uchar_t apic_ipltopri[MAXIPL+1];
 840 extern uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1];
 841 extern int apic_max_device_irq;
 842 extern int apic_min_device_irq;
 843 extern apic_irq_t *apic_irq_table[APIC_MAX_VECTOR+1];
 844 extern volatile uint32_t *apicioadr[MAX_IO_APIC];
 845 extern uchar_t apic_io_id[MAX_IO_APIC];
 846 extern lock_t apic_ioapic_lock;
 847 extern uint32_t apic_physaddr[MAX_IO_APIC];
 848 extern kmutex_t airq_mutex;
 849 extern int apic_first_avail_irq;
 850 extern uchar_t apic_vectortoipl[APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL];
 851 extern int apic_imcrp;
 852 extern int apic_revector_pending;
 853 extern char apic_level_intr[APIC_MAX_VECTOR+1];
 854 extern uchar_t apic_resv_vector[MAXIPL+1];
 855 extern int apic_sample_factor_redistribution;
 856 extern int apic_int_busy_mark;
 857 extern int apic_int_free_mark;
 858 extern int apic_diff_for_redistribution;
 859 extern int apic_poweroff_method;
 860 extern int apic_enable_acpi;
 861 extern int apic_nproc;
 862 extern int apic_max_nproc;
 863 extern int apic_next_bind_cpu;
 864 extern int apic_redistribute_sample_interval;
 865 extern int apic_multi_msi_enable;
 866 extern int apic_sci_vect;
 867 extern int apic_hpet_vect;
 868 extern uchar_t apic_ipls[];
 869 extern apic_reg_ops_t *apic_reg_ops;
 870 extern apic_mode_t apic_mode;
 871 extern void x2apic_update_psm();
 872 extern void apic_change_ops();
 873 extern void apic_common_send_ipi(int, int);
 874 extern void apic_set_directed_EOI_handler();
 875 extern int apic_directed_EOI_supported();
 876 
 877 extern apic_intrmap_ops_t *apic_vt_ops;
 878 
 879 #ifdef  __cplusplus
 880 }
 881 #endif
 882 
 883 #endif  /* _SYS_APIC_APIC_H */