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