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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * PSMI 1.1 extensions are supported only in 2.6 and later versions. 30 * PSMI 1.2 extensions are supported only in 2.7 and later versions. 31 * PSMI 1.3 and 1.4 extensions are supported in Solaris 10. 32 * PSMI 1.5 extensions are supported in Solaris Nevada. 33 */ 34 #define PSMI_1_5 35 36 #include <sys/processor.h> 37 #include <sys/time.h> 38 #include <sys/psm.h> 39 #include <sys/smp_impldefs.h> 40 #include <sys/cram.h> 41 #include <sys/acpi/acpi.h> 42 #include <sys/acpica.h> 43 #include <sys/psm_common.h> 44 #include "apic.h" 45 #include <sys/pit.h> 46 #include <sys/ddi.h> 47 #include <sys/sunddi.h> 48 #include <sys/ddi_impldefs.h> 49 #include <sys/pci.h> 50 #include <sys/promif.h> 51 #include <sys/x86_archext.h> 52 #include <sys/cpc_impl.h> 53 #include <sys/uadmin.h> 54 #include <sys/panic.h> 55 #include <sys/debug.h> 56 #include <sys/archsystm.h> 57 #include <sys/trap.h> 58 #include <sys/machsystm.h> 59 #include <sys/cpuvar.h> 60 #include <sys/rm_platter.h> 61 #include <sys/privregs.h> 62 #include <sys/cyclic.h> 63 #include <sys/note.h> 64 #include <sys/pci_intr_lib.h> 65 66 /* 67 * Local Function Prototypes 68 */ 69 static void apic_init_intr(); 70 static void apic_ret(); 71 static int apic_handle_defconf(); 72 static int apic_parse_mpct(caddr_t mpct, int bypass); 73 static struct apic_mpfps_hdr *apic_find_fps_sig(caddr_t fptr, int size); 74 static int apic_checksum(caddr_t bptr, int len); 75 static int get_apic_cmd1(); 76 static int get_apic_pri(); 77 static int apic_find_bus_type(char *bus); 78 static int apic_find_bus(int busid); 79 static int apic_find_bus_id(int bustype); 80 static struct apic_io_intr *apic_find_io_intr(int irqno); 81 int apic_allocate_irq(int irq); 82 static int apic_find_free_irq(int start, int end); 83 static uchar_t apic_allocate_vector(int ipl, int irq, int pri); 84 static void apic_modify_vector(uchar_t vector, int irq); 85 static void apic_mark_vector(uchar_t oldvector, uchar_t newvector); 86 static uchar_t apic_xlate_vector(uchar_t oldvector); 87 static void apic_xlate_vector_free_timeout_handler(void *arg); 88 static void apic_free_vector(uchar_t vector); 89 static void apic_reprogram_timeout_handler(void *arg); 90 static int apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, 91 int new_bind_cpu, volatile int32_t *ioapic, int intin_no, int which_irq, 92 int iflag, boolean_t *restore_intrp); 93 static int apic_setup_io_intr(apic_irq_t *irqptr, int irq); 94 static int apic_setup_io_intr_deferred(apic_irq_t *irqptr, int irq); 95 static void apic_record_rdt_entry(apic_irq_t *irqptr, int irq); 96 static struct apic_io_intr *apic_find_io_intr_w_busid(int irqno, int busid); 97 static int apic_find_intin(uchar_t ioapic, uchar_t intin); 98 static int apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, 99 int child_ipin, struct apic_io_intr **intrp); 100 static int apic_setup_irq_table(dev_info_t *dip, int irqno, 101 struct apic_io_intr *intrp, struct intrspec *ispec, iflag_t *intr_flagp, 102 int type); 103 static int apic_setup_sci_irq_table(int irqno, uchar_t ipl, 104 iflag_t *intr_flagp); 105 static void apic_nmi_intr(caddr_t arg); 106 uchar_t apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, 107 uchar_t intin); 108 static int apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, int acquire_lock, 109 int when); 110 int apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu, int safe); 111 static void apic_intr_redistribute(); 112 static void apic_cleanup_busy(); 113 static void apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp); 114 int apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type); 115 116 /* ACPI support routines */ 117 static int acpi_probe(void); 118 static int apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, 119 int *pci_irqp, iflag_t *intr_flagp); 120 121 static int apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, 122 int ipin, int *pci_irqp, iflag_t *intr_flagp); 123 static uchar_t acpi_find_ioapic(int irq); 124 static int acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2); 125 126 /* 127 * standard MP entries 128 */ 129 static int apic_probe(); 130 static int apic_clkinit(); 131 static int apic_getclkirq(int ipl); 132 static uint_t apic_calibrate(volatile uint32_t *addr, 133 uint16_t *pit_ticks_adj); 134 static hrtime_t apic_gettime(); 135 static hrtime_t apic_gethrtime(); 136 static void apic_init(); 137 static void apic_picinit(void); 138 static void apic_cpu_start(processorid_t cpun, caddr_t rm_code); 139 static int apic_post_cpu_start(void); 140 static void apic_send_ipi(int cpun, int ipl); 141 static void apic_set_softintr(int softintr); 142 static void apic_set_idlecpu(processorid_t cpun); 143 static void apic_unset_idlecpu(processorid_t cpun); 144 static int apic_softlvl_to_irq(int ipl); 145 static int apic_intr_enter(int ipl, int *vect); 146 static void apic_intr_exit(int ipl, int vect); 147 static void apic_setspl(int ipl); 148 static int apic_addspl(int ipl, int vector, int min_ipl, int max_ipl); 149 static int apic_delspl(int ipl, int vector, int min_ipl, int max_ipl); 150 static void apic_shutdown(int cmd, int fcn); 151 static void apic_preshutdown(int cmd, int fcn); 152 static int apic_disable_intr(processorid_t cpun); 153 static void apic_enable_intr(processorid_t cpun); 154 static processorid_t apic_get_next_processorid(processorid_t cpun); 155 static int apic_get_ipivect(int ipl, int type); 156 static void apic_timer_reprogram(hrtime_t time); 157 static void apic_timer_enable(void); 158 static void apic_timer_disable(void); 159 static void apic_post_cyclic_setup(void *arg); 160 extern int apic_intr_ops(dev_info_t *, ddi_intr_handle_impl_t *, 161 psm_intr_op_t, int *); 162 163 static int apic_oneshot = 0; 164 int apic_oneshot_enable = 1; /* to allow disabling one-shot capability */ 165 166 /* 167 * These variables are frequently accessed in apic_intr_enter(), 168 * apic_intr_exit and apic_setspl, so group them together 169 */ 170 volatile uint32_t *apicadr = NULL; /* virtual addr of local APIC */ 171 int apic_setspl_delay = 1; /* apic_setspl - delay enable */ 172 int apic_clkvect; 173 174 /* ACPI SCI interrupt configuration; -1 if SCI not used */ 175 int apic_sci_vect = -1; 176 iflag_t apic_sci_flags; 177 178 /* vector at which error interrupts come in */ 179 int apic_errvect; 180 int apic_enable_error_intr = 1; 181 int apic_error_display_delay = 100; 182 183 /* vector at which performance counter overflow interrupts come in */ 184 int apic_cpcovf_vect; 185 int apic_enable_cpcovf_intr = 1; 186 187 /* Max wait time (in microsecs) for flags to clear in an RDT entry. */ 188 static int apic_max_usecs_clear_pending = 1000; 189 190 /* Amt of usecs to wait before checking if RDT flags have reset. */ 191 #define APIC_USECS_PER_WAIT_INTERVAL 100 192 193 /* Maximum number of times to retry reprogramming via the timeout */ 194 #define APIC_REPROGRAM_MAX_TIMEOUTS 10 195 196 /* timeout delay for IOAPIC delayed reprogramming */ 197 #define APIC_REPROGRAM_TIMEOUT_DELAY 5 /* microseconds */ 198 199 /* Parameter to apic_rebind(): Should reprogramming be done now or later? */ 200 #define DEFERRED 1 201 #define IMMEDIATE 0 202 203 /* 204 * number of bits per byte, from <sys/param.h> 205 */ 206 #define UCHAR_MAX ((1 << NBBY) - 1) 207 208 uchar_t apic_reserved_irqlist[MAX_ISA_IRQ + 1]; 209 210 /* 211 * The following vector assignments influence the value of ipltopri and 212 * vectortoipl. Note that vectors 0 - 0x1f are not used. We can program 213 * idle to 0 and IPL 0 to 0x10 to differentiate idle in case 214 * we care to do so in future. Note some IPLs which are rarely used 215 * will share the vector ranges and heavily used IPLs (5 and 6) have 216 * a wide range. 217 * IPL Vector range. as passed to intr_enter 218 * 0 none. 219 * 1,2,3 0x20-0x2f 0x0-0xf 220 * 4 0x30-0x3f 0x10-0x1f 221 * 5 0x40-0x5f 0x20-0x3f 222 * 6 0x60-0x7f 0x40-0x5f 223 * 7,8,9 0x80-0x8f 0x60-0x6f 224 * 10 0x90-0x9f 0x70-0x7f 225 * 11 0xa0-0xaf 0x80-0x8f 226 * ... ... 227 * 16 0xf0-0xff 0xd0-0xdf 228 */ 229 uchar_t apic_vectortoipl[APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL] = { 230 3, 4, 5, 5, 6, 6, 9, 10, 11, 12, 13, 14, 15, 16 231 }; 232 /* 233 * The ipl of an ISR at vector X is apic_vectortoipl[X<<4] 234 * NOTE that this is vector as passed into intr_enter which is 235 * programmed vector - 0x20 (APIC_BASE_VECT) 236 */ 237 238 uchar_t apic_ipltopri[MAXIPL + 1]; /* unix ipl to apic pri */ 239 /* The taskpri to be programmed into apic to mask given ipl */ 240 241 #if defined(__amd64) 242 uchar_t apic_cr8pri[MAXIPL + 1]; /* unix ipl to cr8 pri */ 243 #endif 244 245 /* 246 * Patchable global variables. 247 */ 248 int apic_forceload = 0; 249 250 #define INTR_ROUND_ROBIN_WITH_AFFINITY 0 251 #define INTR_ROUND_ROBIN 1 252 #define INTR_LOWEST_PRIORITY 2 253 254 int apic_intr_policy = INTR_ROUND_ROBIN_WITH_AFFINITY; 255 256 static int apic_next_bind_cpu = 1; /* For round robin assignment */ 257 /* start with cpu 1 */ 258 259 int apic_coarse_hrtime = 1; /* 0 - use accurate slow gethrtime() */ 260 /* 1 - use gettime() for performance */ 261 int apic_flat_model = 0; /* 0 - clustered. 1 - flat */ 262 int apic_enable_hwsoftint = 0; /* 0 - disable, 1 - enable */ 263 int apic_enable_bind_log = 1; /* 1 - display interrupt binding log */ 264 int apic_panic_on_nmi = 0; 265 int apic_panic_on_apic_error = 0; 266 267 int apic_verbose = 0; 268 269 /* Flag definitions for apic_verbose */ 270 #define APIC_VERBOSE_IOAPIC_FLAG 0x00000001 271 #define APIC_VERBOSE_IRQ_FLAG 0x00000002 272 #define APIC_VERBOSE_POWEROFF_FLAG 0x00000004 273 #define APIC_VERBOSE_POWEROFF_PAUSE_FLAG 0x00000008 274 275 276 #define APIC_VERBOSE_IOAPIC(fmt) \ 277 if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) \ 278 cmn_err fmt; 279 280 #define APIC_VERBOSE_IRQ(fmt) \ 281 if (apic_verbose & APIC_VERBOSE_IRQ_FLAG) \ 282 cmn_err fmt; 283 284 #define APIC_VERBOSE_POWEROFF(fmt) \ 285 if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) \ 286 prom_printf fmt; 287 288 289 /* Now the ones for Dynamic Interrupt distribution */ 290 int apic_enable_dynamic_migration = 0; 291 292 /* 293 * If enabled, the distribution works as follows: 294 * On every interrupt entry, the current ipl for the CPU is set in cpu_info 295 * and the irq corresponding to the ipl is also set in the aci_current array. 296 * interrupt exit and setspl (due to soft interrupts) will cause the current 297 * ipl to be be changed. This is cache friendly as these frequently used 298 * paths write into a per cpu structure. 299 * 300 * Sampling is done by checking the structures for all CPUs and incrementing 301 * the busy field of the irq (if any) executing on each CPU and the busy field 302 * of the corresponding CPU. 303 * In periodic mode this is done on every clock interrupt. 304 * In one-shot mode, this is done thru a cyclic with an interval of 305 * apic_redistribute_sample_interval (default 10 milli sec). 306 * 307 * Every apic_sample_factor_redistribution times we sample, we do computations 308 * to decide which interrupt needs to be migrated (see comments 309 * before apic_intr_redistribute(). 310 */ 311 312 /* 313 * Following 3 variables start as % and can be patched or set using an 314 * API to be defined in future. They will be scaled to 315 * sample_factor_redistribution which is in turn set to hertz+1 (in periodic 316 * mode), or 101 in one-shot mode to stagger it away from one sec processing 317 */ 318 319 int apic_int_busy_mark = 60; 320 int apic_int_free_mark = 20; 321 int apic_diff_for_redistribution = 10; 322 323 /* sampling interval for interrupt redistribution for dynamic migration */ 324 int apic_redistribute_sample_interval = NANOSEC / 100; /* 10 millisec */ 325 326 /* 327 * number of times we sample before deciding to redistribute interrupts 328 * for dynamic migration 329 */ 330 int apic_sample_factor_redistribution = 101; 331 332 /* timeout for xlate_vector, mark_vector */ 333 int apic_revector_timeout = 16 * 10000; /* 160 millisec */ 334 335 int apic_redist_cpu_skip = 0; 336 int apic_num_imbalance = 0; 337 int apic_num_rebind = 0; 338 339 int apic_nproc = 0; 340 int apic_defconf = 0; 341 int apic_irq_translate = 0; 342 int apic_spec_rev = 0; 343 int apic_imcrp = 0; 344 345 int apic_use_acpi = 1; /* 1 = use ACPI, 0 = don't use ACPI */ 346 int apic_use_acpi_madt_only = 0; /* 1=ONLY use MADT from ACPI */ 347 348 /* 349 * For interrupt link devices, if apic_unconditional_srs is set, an irq resource 350 * will be assigned (via _SRS). If it is not set, use the current 351 * irq setting (via _CRS), but only if that irq is in the set of possible 352 * irqs (returned by _PRS) for the device. 353 */ 354 int apic_unconditional_srs = 1; 355 356 /* 357 * For interrupt link devices, if apic_prefer_crs is set when we are 358 * assigning an IRQ resource to a device, prefer the current IRQ setting 359 * over other possible irq settings under same conditions. 360 */ 361 362 int apic_prefer_crs = 1; 363 364 365 /* minimum number of timer ticks to program to */ 366 int apic_min_timer_ticks = 1; 367 /* 368 * Local static data 369 */ 370 static struct psm_ops apic_ops = { 371 apic_probe, 372 373 apic_init, 374 apic_picinit, 375 apic_intr_enter, 376 apic_intr_exit, 377 apic_setspl, 378 apic_addspl, 379 apic_delspl, 380 apic_disable_intr, 381 apic_enable_intr, 382 apic_softlvl_to_irq, 383 apic_set_softintr, 384 385 apic_set_idlecpu, 386 apic_unset_idlecpu, 387 388 apic_clkinit, 389 apic_getclkirq, 390 (void (*)(void))NULL, /* psm_hrtimeinit */ 391 apic_gethrtime, 392 393 apic_get_next_processorid, 394 apic_cpu_start, 395 apic_post_cpu_start, 396 apic_shutdown, 397 apic_get_ipivect, 398 apic_send_ipi, 399 400 (int (*)(dev_info_t *, int))NULL, /* psm_translate_irq */ 401 (int (*)(todinfo_t *))NULL, /* psm_tod_get */ 402 (int (*)(todinfo_t *))NULL, /* psm_tod_set */ 403 (void (*)(int, char *))NULL, /* psm_notify_error */ 404 (void (*)(int))NULL, /* psm_notify_func */ 405 apic_timer_reprogram, 406 apic_timer_enable, 407 apic_timer_disable, 408 apic_post_cyclic_setup, 409 apic_preshutdown, 410 apic_intr_ops /* Advanced DDI Interrupt framework */ 411 }; 412 413 414 static struct psm_info apic_psm_info = { 415 PSM_INFO_VER01_5, /* version */ 416 PSM_OWN_EXCLUSIVE, /* ownership */ 417 (struct psm_ops *)&apic_ops, /* operation */ 418 "pcplusmp", /* machine name */ 419 "pcplusmp v1.4 compatible %I%", 420 }; 421 422 static void *apic_hdlp; 423 424 #ifdef DEBUG 425 #define DENT 0x0001 426 int apic_debug = 0; 427 /* 428 * set apic_restrict_vector to the # of vectors we want to allow per range 429 * useful in testing shared interrupt logic by setting it to 2 or 3 430 */ 431 int apic_restrict_vector = 0; 432 433 #define APIC_DEBUG_MSGBUFSIZE 2048 434 int apic_debug_msgbuf[APIC_DEBUG_MSGBUFSIZE]; 435 int apic_debug_msgbufindex = 0; 436 437 /* 438 * Put "int" info into debug buffer. No MP consistency, but light weight. 439 * Good enough for most debugging. 440 */ 441 #define APIC_DEBUG_BUF_PUT(x) \ 442 apic_debug_msgbuf[apic_debug_msgbufindex++] = x; \ 443 if (apic_debug_msgbufindex >= (APIC_DEBUG_MSGBUFSIZE - NCPU)) \ 444 apic_debug_msgbufindex = 0; 445 446 #endif /* DEBUG */ 447 448 apic_cpus_info_t *apic_cpus; 449 450 static cpuset_t apic_cpumask; 451 static uint_t apic_flag; 452 453 /* Flag to indicate that we need to shut down all processors */ 454 static uint_t apic_shutdown_processors; 455 456 uint_t apic_nsec_per_intr = 0; 457 458 /* 459 * apic_let_idle_redistribute can have the following values: 460 * 0 - If clock decremented it from 1 to 0, clock has to call redistribute. 461 * apic_redistribute_lock prevents multiple idle cpus from redistributing 462 */ 463 int apic_num_idle_redistributions = 0; 464 static int apic_let_idle_redistribute = 0; 465 static uint_t apic_nticks = 0; 466 static uint_t apic_skipped_redistribute = 0; 467 468 /* to gather intr data and redistribute */ 469 static void apic_redistribute_compute(void); 470 471 static uint_t last_count_read = 0; 472 static lock_t apic_gethrtime_lock; 473 volatile int apic_hrtime_stamp = 0; 474 volatile hrtime_t apic_nsec_since_boot = 0; 475 static uint_t apic_hertz_count, apic_nsec_per_tick; 476 static hrtime_t apic_nsec_max; 477 478 static hrtime_t apic_last_hrtime = 0; 479 int apic_hrtime_error = 0; 480 int apic_remote_hrterr = 0; 481 int apic_num_nmis = 0; 482 int apic_apic_error = 0; 483 int apic_num_apic_errors = 0; 484 int apic_num_cksum_errors = 0; 485 486 static uchar_t apic_io_id[MAX_IO_APIC]; 487 static uchar_t apic_io_ver[MAX_IO_APIC]; 488 static uchar_t apic_io_vectbase[MAX_IO_APIC]; 489 static uchar_t apic_io_vectend[MAX_IO_APIC]; 490 volatile int32_t *apicioadr[MAX_IO_APIC]; 491 492 /* 493 * First available slot to be used as IRQ index into the apic_irq_table 494 * for those interrupts (like MSI/X) that don't have a physical IRQ. 495 */ 496 int apic_first_avail_irq = APIC_FIRST_FREE_IRQ; 497 498 /* 499 * apic_ioapic_lock protects the ioapics (reg select), the status, temp_bound 500 * and bound elements of cpus_info and the temp_cpu element of irq_struct 501 */ 502 lock_t apic_ioapic_lock; 503 504 /* 505 * apic_ioapic_reprogram_lock prevents a CPU from exiting 506 * apic_intr_exit before IOAPIC reprogramming information 507 * is collected. 508 */ 509 static lock_t apic_ioapic_reprogram_lock; 510 static int apic_io_max = 0; /* no. of i/o apics enabled */ 511 512 static struct apic_io_intr *apic_io_intrp = 0; 513 static struct apic_bus *apic_busp; 514 515 uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1]; 516 static uchar_t apic_resv_vector[MAXIPL+1]; 517 518 static char apic_level_intr[APIC_MAX_VECTOR+1]; 519 static int apic_error = 0; 520 /* values which apic_error can take. Not catastrophic, but may help debug */ 521 #define APIC_ERR_BOOT_EOI 0x1 522 #define APIC_ERR_GET_IPIVECT_FAIL 0x2 523 #define APIC_ERR_INVALID_INDEX 0x4 524 #define APIC_ERR_MARK_VECTOR_FAIL 0x8 525 #define APIC_ERR_APIC_ERROR 0x40000000 526 #define APIC_ERR_NMI 0x80000000 527 528 static int apic_cmos_ssb_set = 0; 529 530 static uint32_t eisa_level_intr_mask = 0; 531 /* At least MSB will be set if EISA bus */ 532 533 static int apic_pci_bus_total = 0; 534 static uchar_t apic_single_pci_busid = 0; 535 536 537 /* 538 * airq_mutex protects additions to the apic_irq_table - the first 539 * pointer and any airq_nexts off of that one. It also protects 540 * apic_max_device_irq & apic_min_device_irq. It also guarantees 541 * that share_id is unique as new ids are generated only when new 542 * irq_t structs are linked in. Once linked in the structs are never 543 * deleted. temp_cpu & mps_intr_index field indicate if it is programmed 544 * or allocated. Note that there is a slight gap between allocating in 545 * apic_introp_xlate and programming in addspl. 546 */ 547 kmutex_t airq_mutex; 548 apic_irq_t *apic_irq_table[APIC_MAX_VECTOR+1]; 549 int apic_max_device_irq = 0; 550 int apic_min_device_irq = APIC_MAX_VECTOR; 551 552 /* use to make sure only one cpu handles the nmi */ 553 static lock_t apic_nmi_lock; 554 /* use to make sure only one cpu handles the error interrupt */ 555 static lock_t apic_error_lock; 556 557 /* 558 * Following declarations are for revectoring; used when ISRs at different 559 * IPLs share an irq. 560 */ 561 static lock_t apic_revector_lock; 562 static int apic_revector_pending = 0; 563 static uchar_t *apic_oldvec_to_newvec; 564 static uchar_t *apic_newvec_to_oldvec; 565 566 /* Ensures that the IOAPIC-reprogramming timeout is not reentrant */ 567 static kmutex_t apic_reprogram_timeout_mutex; 568 569 static struct ioapic_reprogram_data { 570 int valid; /* This entry is valid */ 571 int bindcpu; /* The CPU to which the int will be bound */ 572 unsigned timeouts; /* # times the reprogram timeout was called */ 573 } apic_reprogram_info[APIC_MAX_VECTOR+1]; 574 /* 575 * APIC_MAX_VECTOR + 1 is the maximum # of IRQs as well. apic_reprogram_info 576 * is indexed by IRQ number, NOT by vector number. 577 */ 578 579 580 /* 581 * The following added to identify a software poweroff method if available. 582 */ 583 584 static struct { 585 int poweroff_method; 586 char oem_id[APIC_MPS_OEM_ID_LEN + 1]; /* MAX + 1 for NULL */ 587 char prod_id[APIC_MPS_PROD_ID_LEN + 1]; /* MAX + 1 for NULL */ 588 } apic_mps_ids[] = { 589 { APIC_POWEROFF_VIA_RTC, "INTEL", "ALDER" }, /* 4300 */ 590 { APIC_POWEROFF_VIA_RTC, "NCR", "AMC" }, /* 4300 */ 591 { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "A450NX" }, /* 4400? */ 592 { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "AD450NX" }, /* 4400 */ 593 { APIC_POWEROFF_VIA_ASPEN_BMC, "INTEL", "AC450NX" }, /* 4400R */ 594 { APIC_POWEROFF_VIA_SITKA_BMC, "INTEL", "S450NX" }, /* S50 */ 595 { APIC_POWEROFF_VIA_SITKA_BMC, "INTEL", "SC450NX" } /* S50? */ 596 }; 597 598 int apic_poweroff_method = APIC_POWEROFF_NONE; 599 600 static struct { 601 uchar_t cntl; 602 uchar_t data; 603 } aspen_bmc[] = { 604 { CC_SMS_WR_START, 0x18 }, /* NetFn/LUN */ 605 { CC_SMS_WR_NEXT, 0x24 }, /* Cmd SET_WATCHDOG_TIMER */ 606 { CC_SMS_WR_NEXT, 0x84 }, /* DataByte 1: SMS/OS no log */ 607 { CC_SMS_WR_NEXT, 0x2 }, /* DataByte 2: Power Down */ 608 { CC_SMS_WR_NEXT, 0x0 }, /* DataByte 3: no pre-timeout */ 609 { CC_SMS_WR_NEXT, 0x0 }, /* DataByte 4: timer expir. */ 610 { CC_SMS_WR_NEXT, 0xa }, /* DataByte 5: init countdown */ 611 { CC_SMS_WR_END, 0x0 }, /* DataByte 6: init countdown */ 612 613 { CC_SMS_WR_START, 0x18 }, /* NetFn/LUN */ 614 { CC_SMS_WR_END, 0x22 } /* Cmd RESET_WATCHDOG_TIMER */ 615 }; 616 617 static struct { 618 int port; 619 uchar_t data; 620 } sitka_bmc[] = { 621 { SMS_COMMAND_REGISTER, SMS_WRITE_START }, 622 { SMS_DATA_REGISTER, 0x18 }, /* NetFn/LUN */ 623 { SMS_DATA_REGISTER, 0x24 }, /* Cmd SET_WATCHDOG_TIMER */ 624 { SMS_DATA_REGISTER, 0x84 }, /* DataByte 1: SMS/OS no log */ 625 { SMS_DATA_REGISTER, 0x2 }, /* DataByte 2: Power Down */ 626 { SMS_DATA_REGISTER, 0x0 }, /* DataByte 3: no pre-timeout */ 627 { SMS_DATA_REGISTER, 0x0 }, /* DataByte 4: timer expir. */ 628 { SMS_DATA_REGISTER, 0xa }, /* DataByte 5: init countdown */ 629 { SMS_COMMAND_REGISTER, SMS_WRITE_END }, 630 { SMS_DATA_REGISTER, 0x0 }, /* DataByte 6: init countdown */ 631 632 { SMS_COMMAND_REGISTER, SMS_WRITE_START }, 633 { SMS_DATA_REGISTER, 0x18 }, /* NetFn/LUN */ 634 { SMS_COMMAND_REGISTER, SMS_WRITE_END }, 635 { SMS_DATA_REGISTER, 0x22 } /* Cmd RESET_WATCHDOG_TIMER */ 636 }; 637 638 639 /* Patchable global variables. */ 640 int apic_kmdb_on_nmi = 0; /* 0 - no, 1 - yes enter kmdb */ 641 int apic_debug_mps_id = 0; /* 1 - print MPS ID strings */ 642 643 /* 644 * ACPI definitions 645 */ 646 /* _PIC method arguments */ 647 #define ACPI_PIC_MODE 0 648 #define ACPI_APIC_MODE 1 649 650 /* APIC error flags we care about */ 651 #define APIC_SEND_CS_ERROR 0x01 652 #define APIC_RECV_CS_ERROR 0x02 653 #define APIC_CS_ERRORS (APIC_SEND_CS_ERROR|APIC_RECV_CS_ERROR) 654 655 /* 656 * ACPI variables 657 */ 658 /* 1 = acpi is enabled & working, 0 = acpi is not enabled or not there */ 659 static int apic_enable_acpi = 0; 660 661 /* ACPI Multiple APIC Description Table ptr */ 662 static MULTIPLE_APIC_TABLE *acpi_mapic_dtp = NULL; 663 664 /* ACPI Interrupt Source Override Structure ptr */ 665 static MADT_INTERRUPT_OVERRIDE *acpi_isop = NULL; 666 static int acpi_iso_cnt = 0; 667 668 /* ACPI Non-maskable Interrupt Sources ptr */ 669 static MADT_NMI_SOURCE *acpi_nmi_sp = NULL; 670 static int acpi_nmi_scnt = 0; 671 static MADT_LOCAL_APIC_NMI *acpi_nmi_cp = NULL; 672 static int acpi_nmi_ccnt = 0; 673 674 /* 675 * extern declarations 676 */ 677 extern int intr_clear(void); 678 extern void intr_restore(uint_t); 679 #if defined(__amd64) 680 extern int intpri_use_cr8; 681 #endif /* __amd64 */ 682 683 extern int apic_pci_msi_enable_vector(dev_info_t *, int, int, 684 int, int, int); 685 extern apic_irq_t *apic_find_irq(dev_info_t *, struct intrspec *, int); 686 extern int apic_pci_msi_unconfigure(dev_info_t *, int, int); 687 extern int apic_pci_msi_disable_mode(dev_info_t *, int, int); 688 extern int apic_pci_msi_enable_mode(dev_info_t *, int, int); 689 690 /* 691 * This is the loadable module wrapper 692 */ 693 694 int 695 _init(void) 696 { 697 if (apic_coarse_hrtime) 698 apic_ops.psm_gethrtime = &apic_gettime; 699 return (psm_mod_init(&apic_hdlp, &apic_psm_info)); 700 } 701 702 int 703 _fini(void) 704 { 705 return (psm_mod_fini(&apic_hdlp, &apic_psm_info)); 706 } 707 708 int 709 _info(struct modinfo *modinfop) 710 { 711 return (psm_mod_info(&apic_hdlp, &apic_psm_info, modinfop)); 712 } 713 714 /* 715 * Auto-configuration routines 716 */ 717 718 /* 719 * Look at MPSpec 1.4 (Intel Order # 242016-005) for details of what we do here 720 * May work with 1.1 - but not guaranteed. 721 * According to the MP Spec, the MP floating pointer structure 722 * will be searched in the order described below: 723 * 1. In the first kilobyte of Extended BIOS Data Area (EBDA) 724 * 2. Within the last kilobyte of system base memory 725 * 3. In the BIOS ROM address space between 0F0000h and 0FFFFh 726 * Once we find the right signature with proper checksum, we call 727 * either handle_defconf or parse_mpct to get all info necessary for 728 * subsequent operations. 729 */ 730 static int 731 apic_probe() 732 { 733 uint32_t mpct_addr, ebda_start = 0, base_mem_end; 734 caddr_t biosdatap; 735 caddr_t mpct; 736 caddr_t fptr; 737 int i, mpct_size, mapsize, retval = PSM_FAILURE; 738 ushort_t ebda_seg, base_mem_size; 739 struct apic_mpfps_hdr *fpsp; 740 struct apic_mp_cnf_hdr *hdrp; 741 int bypass_cpu_and_ioapics_in_mptables; 742 int acpi_user_options; 743 744 if (apic_forceload < 0) 745 return (retval); 746 747 /* Allow override for MADT-only mode */ 748 acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 0, 749 "acpi-user-options", 0); 750 apic_use_acpi_madt_only = ((acpi_user_options & ACPI_OUSER_MADT) != 0); 751 752 /* Allow apic_use_acpi to override MADT-only mode */ 753 if (!apic_use_acpi) 754 apic_use_acpi_madt_only = 0; 755 756 retval = acpi_probe(); 757 758 /* 759 * mapin the bios data area 40:0 760 * 40:13h - two-byte location reports the base memory size 761 * 40:0Eh - two-byte location for the exact starting address of 762 * the EBDA segment for EISA 763 */ 764 biosdatap = psm_map_phys(0x400, 0x20, PROT_READ); 765 if (!biosdatap) 766 return (retval); 767 fpsp = (struct apic_mpfps_hdr *)NULL; 768 mapsize = MPFPS_RAM_WIN_LEN; 769 /*LINTED: pointer cast may result in improper alignment */ 770 ebda_seg = *((ushort_t *)(biosdatap+0xe)); 771 /* check the 1k of EBDA */ 772 if (ebda_seg) { 773 ebda_start = ((uint32_t)ebda_seg) << 4; 774 fptr = psm_map_phys(ebda_start, MPFPS_RAM_WIN_LEN, PROT_READ); 775 if (fptr) { 776 if (!(fpsp = 777 apic_find_fps_sig(fptr, MPFPS_RAM_WIN_LEN))) 778 psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN); 779 } 780 } 781 /* If not in EBDA, check the last k of system base memory */ 782 if (!fpsp) { 783 /*LINTED: pointer cast may result in improper alignment */ 784 base_mem_size = *((ushort_t *)(biosdatap + 0x13)); 785 786 if (base_mem_size > 512) 787 base_mem_end = 639 * 1024; 788 else 789 base_mem_end = 511 * 1024; 790 /* if ebda == last k of base mem, skip to check BIOS ROM */ 791 if (base_mem_end != ebda_start) { 792 793 fptr = psm_map_phys(base_mem_end, MPFPS_RAM_WIN_LEN, 794 PROT_READ); 795 796 if (fptr) { 797 if (!(fpsp = apic_find_fps_sig(fptr, 798 MPFPS_RAM_WIN_LEN))) 799 psm_unmap_phys(fptr, MPFPS_RAM_WIN_LEN); 800 } 801 } 802 } 803 psm_unmap_phys(biosdatap, 0x20); 804 805 /* If still cannot find it, check the BIOS ROM space */ 806 if (!fpsp) { 807 mapsize = MPFPS_ROM_WIN_LEN; 808 fptr = psm_map_phys(MPFPS_ROM_WIN_START, 809 MPFPS_ROM_WIN_LEN, PROT_READ); 810 if (fptr) { 811 if (!(fpsp = 812 apic_find_fps_sig(fptr, MPFPS_ROM_WIN_LEN))) { 813 psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); 814 return (retval); 815 } 816 } 817 } 818 819 if (apic_checksum((caddr_t)fpsp, fpsp->mpfps_length * 16) != 0) { 820 psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); 821 return (retval); 822 } 823 824 apic_spec_rev = fpsp->mpfps_spec_rev; 825 if ((apic_spec_rev != 04) && (apic_spec_rev != 01)) { 826 psm_unmap_phys(fptr, MPFPS_ROM_WIN_LEN); 827 return (retval); 828 } 829 830 /* check IMCR is present or not */ 831 apic_imcrp = fpsp->mpfps_featinfo2 & MPFPS_FEATINFO2_IMCRP; 832 833 /* check default configuration (dual CPUs) */ 834 if ((apic_defconf = fpsp->mpfps_featinfo1) != 0) { 835 psm_unmap_phys(fptr, mapsize); 836 return (apic_handle_defconf()); 837 } 838 839 /* MP Configuration Table */ 840 mpct_addr = (uint32_t)(fpsp->mpfps_mpct_paddr); 841 842 psm_unmap_phys(fptr, mapsize); /* unmap floating ptr struct */ 843 844 /* 845 * Map in enough memory for the MP Configuration Table Header. 846 * Use this table to read the total length of the BIOS data and 847 * map in all the info 848 */ 849 /*LINTED: pointer cast may result in improper alignment */ 850 hdrp = (struct apic_mp_cnf_hdr *)psm_map_phys(mpct_addr, 851 sizeof (struct apic_mp_cnf_hdr), PROT_READ); 852 if (!hdrp) 853 return (retval); 854 855 /* check mp configuration table signature PCMP */ 856 if (hdrp->mpcnf_sig != 0x504d4350) { 857 psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); 858 return (retval); 859 } 860 mpct_size = (int)hdrp->mpcnf_tbl_length; 861 862 apic_set_pwroff_method_from_mpcnfhdr(hdrp); 863 864 psm_unmap_phys((caddr_t)hdrp, sizeof (struct apic_mp_cnf_hdr)); 865 866 if ((retval == PSM_SUCCESS) && !apic_use_acpi_madt_only) { 867 /* This is an ACPI machine No need for further checks */ 868 return (retval); 869 } 870 871 /* 872 * Map in the entries for this machine, ie. Processor 873 * Entry Tables, Bus Entry Tables, etc. 874 * They are in fixed order following one another 875 */ 876 mpct = psm_map_phys(mpct_addr, mpct_size, PROT_READ); 877 if (!mpct) 878 return (retval); 879 880 if (apic_checksum(mpct, mpct_size) != 0) 881 goto apic_fail1; 882 883 884 /*LINTED: pointer cast may result in improper alignment */ 885 hdrp = (struct apic_mp_cnf_hdr *)mpct; 886 /*LINTED: pointer cast may result in improper alignment */ 887 apicadr = (uint32_t *)psm_map_phys((uint32_t)hdrp->mpcnf_local_apic, 888 APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); 889 if (!apicadr) 890 goto apic_fail1; 891 892 /* Parse all information in the tables */ 893 bypass_cpu_and_ioapics_in_mptables = (retval == PSM_SUCCESS); 894 if (apic_parse_mpct(mpct, bypass_cpu_and_ioapics_in_mptables) == 895 PSM_SUCCESS) 896 return (PSM_SUCCESS); 897 898 for (i = 0; i < apic_io_max; i++) 899 psm_unmap_phys((caddr_t)apicioadr[i], APIC_IO_MEMLEN); 900 if (apic_cpus) 901 kmem_free(apic_cpus, sizeof (*apic_cpus) * apic_nproc); 902 if (apicadr) 903 psm_unmap_phys((caddr_t)apicadr, APIC_LOCAL_MEMLEN); 904 apic_fail1: 905 psm_unmap_phys(mpct, mpct_size); 906 return (retval); 907 } 908 909 static void 910 apic_set_pwroff_method_from_mpcnfhdr(struct apic_mp_cnf_hdr *hdrp) 911 { 912 int i; 913 914 for (i = 0; i < (sizeof (apic_mps_ids) / sizeof (apic_mps_ids[0])); 915 i++) { 916 if ((strncmp(hdrp->mpcnf_oem_str, apic_mps_ids[i].oem_id, 917 strlen(apic_mps_ids[i].oem_id)) == 0) && 918 (strncmp(hdrp->mpcnf_prod_str, apic_mps_ids[i].prod_id, 919 strlen(apic_mps_ids[i].prod_id)) == 0)) { 920 921 apic_poweroff_method = apic_mps_ids[i].poweroff_method; 922 break; 923 } 924 } 925 926 if (apic_debug_mps_id != 0) { 927 cmn_err(CE_CONT, "pcplusmp: MPS OEM ID = '%c%c%c%c%c%c%c%c'" 928 "Product ID = '%c%c%c%c%c%c%c%c%c%c%c%c'\n", 929 hdrp->mpcnf_oem_str[0], 930 hdrp->mpcnf_oem_str[1], 931 hdrp->mpcnf_oem_str[2], 932 hdrp->mpcnf_oem_str[3], 933 hdrp->mpcnf_oem_str[4], 934 hdrp->mpcnf_oem_str[5], 935 hdrp->mpcnf_oem_str[6], 936 hdrp->mpcnf_oem_str[7], 937 hdrp->mpcnf_prod_str[0], 938 hdrp->mpcnf_prod_str[1], 939 hdrp->mpcnf_prod_str[2], 940 hdrp->mpcnf_prod_str[3], 941 hdrp->mpcnf_prod_str[4], 942 hdrp->mpcnf_prod_str[5], 943 hdrp->mpcnf_prod_str[6], 944 hdrp->mpcnf_prod_str[7], 945 hdrp->mpcnf_prod_str[8], 946 hdrp->mpcnf_prod_str[9], 947 hdrp->mpcnf_prod_str[10], 948 hdrp->mpcnf_prod_str[11]); 949 } 950 } 951 952 static int 953 acpi_probe(void) 954 { 955 int i, id, intmax, ver, index, rv; 956 int acpi_verboseflags = 0; 957 int madt_seen, madt_size; 958 APIC_HEADER *ap; 959 MADT_PROCESSOR_APIC *mpa; 960 MADT_IO_APIC *mia; 961 MADT_IO_SAPIC *misa; 962 MADT_INTERRUPT_OVERRIDE *mio; 963 MADT_NMI_SOURCE *mns; 964 MADT_INTERRUPT_SOURCE *mis; 965 MADT_LOCAL_APIC_NMI *mlan; 966 MADT_ADDRESS_OVERRIDE *mao; 967 ACPI_OBJECT_LIST arglist; 968 ACPI_OBJECT arg; 969 int sci; 970 iflag_t sci_flags; 971 volatile int32_t *ioapic; 972 char local_ids[NCPU]; 973 char proc_ids[NCPU]; 974 uchar_t hid; 975 976 if (!apic_use_acpi) 977 return (PSM_FAILURE); 978 979 if (AcpiGetFirmwareTable(APIC_SIG, 1, ACPI_LOGICAL_ADDRESSING, 980 (ACPI_TABLE_HEADER **) &acpi_mapic_dtp) != AE_OK) 981 return (PSM_FAILURE); 982 983 apicadr = (uint32_t *)psm_map_phys( 984 (uint32_t)acpi_mapic_dtp->LocalApicAddress, 985 APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); 986 if (!apicadr) 987 return (PSM_FAILURE); 988 989 id = apicadr[APIC_LID_REG]; 990 local_ids[0] = (uchar_t)(((uint_t)id) >> 24); 991 apic_nproc = index = 1; 992 CPUSET_ONLY(apic_cpumask, 0); 993 apic_io_max = 0; 994 995 ap = (APIC_HEADER *) (acpi_mapic_dtp + 1); 996 madt_size = acpi_mapic_dtp->Length; 997 madt_seen = sizeof (*acpi_mapic_dtp); 998 999 while (madt_seen < madt_size) { 1000 switch (ap->Type) { 1001 case APIC_PROCESSOR: 1002 mpa = (MADT_PROCESSOR_APIC *) ap; 1003 if (mpa->ProcessorEnabled) { 1004 if (mpa->LocalApicId == local_ids[0]) 1005 proc_ids[0] = mpa->ProcessorId; 1006 else if (apic_nproc < NCPU) { 1007 local_ids[index] = mpa->LocalApicId; 1008 proc_ids[index] = mpa->ProcessorId; 1009 CPUSET_ADD(apic_cpumask, index); 1010 index++; 1011 apic_nproc++; 1012 } else 1013 cmn_err(CE_WARN, "pcplusmp: exceeded " 1014 "maximum no. of CPUs (= %d)", NCPU); 1015 } 1016 break; 1017 1018 case APIC_IO: 1019 mia = (MADT_IO_APIC *) ap; 1020 if (apic_io_max < MAX_IO_APIC) { 1021 apic_io_id[apic_io_max] = mia->IoApicId; 1022 apic_io_vectbase[apic_io_max] = 1023 mia->Interrupt; 1024 ioapic = apicioadr[apic_io_max] = 1025 (int32_t *)psm_map_phys( 1026 (uint32_t)mia->Address, 1027 APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); 1028 if (!ioapic) 1029 goto cleanup; 1030 apic_io_max++; 1031 } 1032 break; 1033 1034 case APIC_XRUPT_OVERRIDE: 1035 mio = (MADT_INTERRUPT_OVERRIDE *) ap; 1036 if (acpi_isop == NULL) 1037 acpi_isop = mio; 1038 acpi_iso_cnt++; 1039 break; 1040 1041 case APIC_NMI: 1042 /* UNIMPLEMENTED */ 1043 mns = (MADT_NMI_SOURCE *) ap; 1044 if (acpi_nmi_sp == NULL) 1045 acpi_nmi_sp = mns; 1046 acpi_nmi_scnt++; 1047 1048 cmn_err(CE_NOTE, "!apic: nmi source: %d %d %d\n", 1049 mns->Interrupt, mns->Polarity, 1050 mns->TriggerMode); 1051 break; 1052 1053 case APIC_LOCAL_NMI: 1054 /* UNIMPLEMENTED */ 1055 mlan = (MADT_LOCAL_APIC_NMI *) ap; 1056 if (acpi_nmi_cp == NULL) 1057 acpi_nmi_cp = mlan; 1058 acpi_nmi_ccnt++; 1059 1060 cmn_err(CE_NOTE, "!apic: local nmi: %d %d %d %d\n", 1061 mlan->ProcessorId, mlan->Polarity, 1062 mlan->TriggerMode, mlan->Lint); 1063 break; 1064 1065 case APIC_ADDRESS_OVERRIDE: 1066 /* UNIMPLEMENTED */ 1067 mao = (MADT_ADDRESS_OVERRIDE *) ap; 1068 cmn_err(CE_NOTE, "!apic: address override: %lx\n", 1069 (long)mao->Address); 1070 break; 1071 1072 case APIC_IO_SAPIC: 1073 /* UNIMPLEMENTED */ 1074 misa = (MADT_IO_SAPIC *) ap; 1075 1076 cmn_err(CE_NOTE, "!apic: io sapic: %d %d %lx\n", 1077 misa->IoSapicId, misa->InterruptBase, 1078 (long)misa->Address); 1079 break; 1080 1081 case APIC_XRUPT_SOURCE: 1082 /* UNIMPLEMENTED */ 1083 mis = (MADT_INTERRUPT_SOURCE *) ap; 1084 1085 cmn_err(CE_NOTE, 1086 "!apic: irq source: %d %d %d %d %d %d %d\n", 1087 mis->ProcessorId, mis->ProcessorEid, 1088 mis->Interrupt, mis->Polarity, 1089 mis->TriggerMode, mis->InterruptType, 1090 mis->IoSapicVector); 1091 break; 1092 case APIC_RESERVED: 1093 default: 1094 break; /* ignore unknown items as per ACPI spec */ 1095 } 1096 1097 /* advance to next entry */ 1098 madt_seen += ap->Length; 1099 ap = (APIC_HEADER *)(((char *)ap) + ap->Length); 1100 } 1101 1102 if ((apic_cpus = kmem_zalloc(sizeof (*apic_cpus) * apic_nproc, 1103 KM_NOSLEEP)) == NULL) 1104 goto cleanup; 1105 1106 /* 1107 * ACPI doesn't provide the local apic ver, get it directly from the 1108 * local apic 1109 */ 1110 ver = apicadr[APIC_VERS_REG]; 1111 for (i = 0; i < apic_nproc; i++) { 1112 apic_cpus[i].aci_local_id = local_ids[i]; 1113 apic_cpus[i].aci_local_ver = (uchar_t)(ver & 0xFF); 1114 } 1115 for (i = 0; i < apic_io_max; i++) { 1116 ioapic = apicioadr[i]; 1117 1118 /* 1119 * need to check Sitka on the following acpi problem 1120 * On the Sitka, the ioapic's apic_id field isn't reporting 1121 * the actual io apic id. We have reported this problem 1122 * to Intel. Until they fix the problem, we will get the 1123 * actual id directly from the ioapic. 1124 */ 1125 ioapic[APIC_IO_REG] = APIC_ID_CMD; 1126 id = ioapic[APIC_IO_DATA]; 1127 hid = (uchar_t)(((uint_t)id) >> 24); 1128 1129 if (hid != apic_io_id[i]) { 1130 if (apic_io_id[i] == 0) 1131 apic_io_id[i] = hid; 1132 else { /* set ioapic id to whatever reported by ACPI */ 1133 id = ((int32_t)apic_io_id[i]) << 24; 1134 ioapic[APIC_IO_REG] = APIC_ID_CMD; 1135 ioapic[APIC_IO_DATA] = id; 1136 } 1137 } 1138 ioapic[APIC_IO_REG] = APIC_VERS_CMD; 1139 ver = ioapic[APIC_IO_DATA]; 1140 apic_io_ver[i] = (uchar_t)(ver & 0xff); 1141 intmax = (ver >> 16) & 0xff; 1142 apic_io_vectend[i] = apic_io_vectbase[i] + intmax; 1143 if (apic_first_avail_irq <= apic_io_vectend[i]) 1144 apic_first_avail_irq = apic_io_vectend[i] + 1; 1145 } 1146 1147 1148 /* 1149 * Process SCI configuration here 1150 * An error may be returned here if 1151 * acpi-user-options specifies legacy mode 1152 * (no SCI, no ACPI mode) 1153 */ 1154 if (acpica_get_sci(&sci, &sci_flags) != AE_OK) 1155 sci = -1; 1156 1157 /* 1158 * Now call acpi_init() to generate namespaces 1159 * If this fails, we don't attempt to use ACPI 1160 * even if we were able to get a MADT above 1161 */ 1162 if (acpica_init() != AE_OK) 1163 goto cleanup; 1164 1165 /* 1166 * Squirrel away the SCI and flags for later on 1167 * in apic_picinit() when we're ready 1168 */ 1169 apic_sci_vect = sci; 1170 apic_sci_flags = sci_flags; 1171 1172 if (apic_verbose & APIC_VERBOSE_IRQ_FLAG) 1173 acpi_verboseflags |= PSM_VERBOSE_IRQ_FLAG; 1174 1175 if (apic_verbose & APIC_VERBOSE_POWEROFF_FLAG) 1176 acpi_verboseflags |= PSM_VERBOSE_POWEROFF_FLAG; 1177 1178 if (apic_verbose & APIC_VERBOSE_POWEROFF_PAUSE_FLAG) 1179 acpi_verboseflags |= PSM_VERBOSE_POWEROFF_PAUSE_FLAG; 1180 1181 if (acpi_psm_init(apic_psm_info.p_mach_idstring, acpi_verboseflags) == 1182 ACPI_PSM_FAILURE) 1183 goto cleanup; 1184 1185 /* Enable ACPI APIC interrupt routing */ 1186 arglist.Count = 1; 1187 arglist.Pointer = &arg; 1188 arg.Type = ACPI_TYPE_INTEGER; 1189 arg.Integer.Value = ACPI_APIC_MODE; /* 1 */ 1190 rv = AcpiEvaluateObject(NULL, "\\_PIC", &arglist, NULL); 1191 if (rv == AE_OK) { 1192 build_reserved_irqlist((uchar_t *)apic_reserved_irqlist); 1193 apic_enable_acpi = 1; 1194 if (apic_use_acpi_madt_only) { 1195 cmn_err(CE_CONT, 1196 "?Using ACPI for CPU/IOAPIC information ONLY\n"); 1197 } 1198 return (PSM_SUCCESS); 1199 } 1200 /* if setting APIC mode failed above, we fall through to cleanup */ 1201 1202 cleanup: 1203 if (apicadr != NULL) { 1204 psm_unmap_phys((caddr_t)apicadr, APIC_LOCAL_MEMLEN); 1205 apicadr = NULL; 1206 } 1207 apic_nproc = 0; 1208 for (i = 0; i < apic_io_max; i++) { 1209 psm_unmap_phys((caddr_t)apicioadr[i], APIC_IO_MEMLEN); 1210 apicioadr[i] = NULL; 1211 } 1212 apic_io_max = 0; 1213 acpi_isop = NULL; 1214 acpi_iso_cnt = 0; 1215 acpi_nmi_sp = NULL; 1216 acpi_nmi_scnt = 0; 1217 acpi_nmi_cp = NULL; 1218 acpi_nmi_ccnt = 0; 1219 return (PSM_FAILURE); 1220 } 1221 1222 /* 1223 * Handle default configuration. Fill in reqd global variables & tables 1224 * Fill all details as MP table does not give any more info 1225 */ 1226 static int 1227 apic_handle_defconf() 1228 { 1229 uint_t lid; 1230 1231 /*LINTED: pointer cast may result in improper alignment */ 1232 apicioadr[0] = (int32_t *)psm_map_phys(APIC_IO_ADDR, 1233 APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); 1234 /*LINTED: pointer cast may result in improper alignment */ 1235 apicadr = (uint32_t *)psm_map_phys(APIC_LOCAL_ADDR, 1236 APIC_LOCAL_MEMLEN, PROT_READ | PROT_WRITE); 1237 apic_cpus = (apic_cpus_info_t *) 1238 kmem_zalloc(sizeof (*apic_cpus) * 2, KM_NOSLEEP); 1239 if ((!apicadr) || (!apicioadr[0]) || (!apic_cpus)) 1240 goto apic_handle_defconf_fail; 1241 CPUSET_ONLY(apic_cpumask, 0); 1242 CPUSET_ADD(apic_cpumask, 1); 1243 apic_nproc = 2; 1244 lid = apicadr[APIC_LID_REG]; 1245 apic_cpus[0].aci_local_id = (uchar_t)(lid >> APIC_ID_BIT_OFFSET); 1246 /* 1247 * According to the PC+MP spec 1.1, the local ids 1248 * for the default configuration has to be 0 or 1 1249 */ 1250 if (apic_cpus[0].aci_local_id == 1) 1251 apic_cpus[1].aci_local_id = 0; 1252 else if (apic_cpus[0].aci_local_id == 0) 1253 apic_cpus[1].aci_local_id = 1; 1254 else 1255 goto apic_handle_defconf_fail; 1256 1257 apic_io_id[0] = 2; 1258 apic_io_max = 1; 1259 if (apic_defconf >= 5) { 1260 apic_cpus[0].aci_local_ver = APIC_INTEGRATED_VERS; 1261 apic_cpus[1].aci_local_ver = APIC_INTEGRATED_VERS; 1262 apic_io_ver[0] = APIC_INTEGRATED_VERS; 1263 } else { 1264 apic_cpus[0].aci_local_ver = 0; /* 82489 DX */ 1265 apic_cpus[1].aci_local_ver = 0; 1266 apic_io_ver[0] = 0; 1267 } 1268 if (apic_defconf == 2 || apic_defconf == 3 || apic_defconf == 6) 1269 eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) | 1270 inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1); 1271 return (PSM_SUCCESS); 1272 1273 apic_handle_defconf_fail: 1274 if (apic_cpus) 1275 kmem_free(apic_cpus, sizeof (*apic_cpus) * 2); 1276 if (apicadr) 1277 psm_unmap_phys((caddr_t)apicadr, APIC_LOCAL_MEMLEN); 1278 if (apicioadr[0]) 1279 psm_unmap_phys((caddr_t)apicioadr[0], APIC_IO_MEMLEN); 1280 return (PSM_FAILURE); 1281 } 1282 1283 /* Parse the entries in MP configuration table and collect info that we need */ 1284 static int 1285 apic_parse_mpct(caddr_t mpct, int bypass_cpus_and_ioapics) 1286 { 1287 struct apic_procent *procp; 1288 struct apic_bus *busp; 1289 struct apic_io_entry *ioapicp; 1290 struct apic_io_intr *intrp; 1291 volatile int32_t *ioapic; 1292 uint_t lid; 1293 int id; 1294 uchar_t hid; 1295 1296 /*LINTED: pointer cast may result in improper alignment */ 1297 procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr)); 1298 1299 /* No need to count cpu entries if we won't use them */ 1300 if (!bypass_cpus_and_ioapics) { 1301 1302 /* Find max # of CPUS and allocate structure accordingly */ 1303 apic_nproc = 0; 1304 CPUSET_ZERO(apic_cpumask); 1305 while (procp->proc_entry == APIC_CPU_ENTRY) { 1306 if (procp->proc_cpuflags & CPUFLAGS_EN) { 1307 if (apic_nproc < NCPU) 1308 CPUSET_ADD(apic_cpumask, apic_nproc); 1309 apic_nproc++; 1310 } 1311 procp++; 1312 } 1313 if (apic_nproc > NCPU) 1314 cmn_err(CE_WARN, "pcplusmp: exceeded " 1315 "maximum no. of CPUs (= %d)", NCPU); 1316 if (!apic_nproc || !(apic_cpus = (apic_cpus_info_t *) 1317 kmem_zalloc(sizeof (*apic_cpus)*apic_nproc, KM_NOSLEEP))) 1318 return (PSM_FAILURE); 1319 } 1320 1321 /*LINTED: pointer cast may result in improper alignment */ 1322 procp = (struct apic_procent *)(mpct + sizeof (struct apic_mp_cnf_hdr)); 1323 1324 /* 1325 * start with index 1 as 0 needs to be filled in with Boot CPU, but 1326 * if we're bypassing this information, it has already been filled 1327 * in by acpi_probe(), so don't overwrite it. 1328 */ 1329 if (!bypass_cpus_and_ioapics) 1330 apic_nproc = 1; 1331 1332 while (procp->proc_entry == APIC_CPU_ENTRY) { 1333 /* check whether the cpu exists or not */ 1334 if (!bypass_cpus_and_ioapics && 1335 procp->proc_cpuflags & CPUFLAGS_EN) { 1336 if (procp->proc_cpuflags & CPUFLAGS_BP) { /* Boot CPU */ 1337 lid = apicadr[APIC_LID_REG]; 1338 apic_cpus[0].aci_local_id = procp->proc_apicid; 1339 if (apic_cpus[0].aci_local_id != 1340 (uchar_t)(lid >> APIC_ID_BIT_OFFSET)) { 1341 return (PSM_FAILURE); 1342 } 1343 apic_cpus[0].aci_local_ver = 1344 procp->proc_version; 1345 } else { 1346 1347 apic_cpus[apic_nproc].aci_local_id = 1348 procp->proc_apicid; 1349 apic_cpus[apic_nproc].aci_local_ver = 1350 procp->proc_version; 1351 apic_nproc++; 1352 1353 } 1354 } 1355 procp++; 1356 } 1357 1358 /* 1359 * Save start of bus entries for later use. 1360 * Get EISA level cntrl if EISA bus is present. 1361 * Also get the CPI bus id for single CPI bus case 1362 */ 1363 apic_busp = busp = (struct apic_bus *)procp; 1364 while (busp->bus_entry == APIC_BUS_ENTRY) { 1365 lid = apic_find_bus_type((char *)&busp->bus_str1); 1366 if (lid == BUS_EISA) { 1367 eisa_level_intr_mask = (inb(EISA_LEVEL_CNTL + 1) << 8) | 1368 inb(EISA_LEVEL_CNTL) | ((uint_t)INT32_MAX + 1); 1369 } else if (lid == BUS_PCI) { 1370 /* 1371 * apic_single_pci_busid will be used only if 1372 * apic_pic_bus_total is equal to 1 1373 */ 1374 apic_pci_bus_total++; 1375 apic_single_pci_busid = busp->bus_id; 1376 } 1377 busp++; 1378 } 1379 1380 ioapicp = (struct apic_io_entry *)busp; 1381 1382 if (!bypass_cpus_and_ioapics) 1383 apic_io_max = 0; 1384 do { 1385 if (!bypass_cpus_and_ioapics && apic_io_max < MAX_IO_APIC) { 1386 if (ioapicp->io_flags & IOAPIC_FLAGS_EN) { 1387 apic_io_id[apic_io_max] = ioapicp->io_apicid; 1388 apic_io_ver[apic_io_max] = ioapicp->io_version; 1389 /*LINTED: pointer cast may result in improper alignment */ 1390 apicioadr[apic_io_max] = 1391 (int32_t *)psm_map_phys( 1392 (uint32_t)ioapicp->io_apic_addr, 1393 APIC_IO_MEMLEN, PROT_READ | PROT_WRITE); 1394 1395 if (!apicioadr[apic_io_max]) 1396 return (PSM_FAILURE); 1397 1398 ioapic = apicioadr[apic_io_max]; 1399 ioapic[APIC_IO_REG] = APIC_ID_CMD; 1400 id = ioapic[APIC_IO_DATA]; 1401 hid = (uchar_t)(((uint_t)id) >> 24); 1402 1403 if (hid != apic_io_id[apic_io_max]) { 1404 if (apic_io_id[apic_io_max] == 0) 1405 apic_io_id[apic_io_max] = hid; 1406 else { 1407 /* 1408 * set ioapic id to whatever 1409 * reported by MPS 1410 * 1411 * may not need to set index 1412 * again ??? 1413 * take it out and try 1414 */ 1415 1416 id = ((int32_t) 1417 apic_io_id[apic_io_max]) << 1418 24; 1419 1420 ioapic[APIC_IO_REG] = 1421 APIC_ID_CMD; 1422 1423 ioapic[APIC_IO_DATA] = id; 1424 1425 } 1426 } 1427 apic_io_max++; 1428 } 1429 } 1430 ioapicp++; 1431 } while (ioapicp->io_entry == APIC_IO_ENTRY); 1432 1433 apic_io_intrp = (struct apic_io_intr *)ioapicp; 1434 1435 intrp = apic_io_intrp; 1436 while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { 1437 if ((intrp->intr_irq > APIC_MAX_ISA_IRQ) || 1438 (apic_find_bus(intrp->intr_busid) == BUS_PCI)) { 1439 apic_irq_translate = 1; 1440 break; 1441 } 1442 intrp++; 1443 } 1444 1445 return (PSM_SUCCESS); 1446 } 1447 1448 boolean_t 1449 apic_cpu_in_range(int cpu) 1450 { 1451 return ((cpu & ~IRQ_USER_BOUND) < apic_nproc); 1452 } 1453 1454 static struct apic_mpfps_hdr * 1455 apic_find_fps_sig(caddr_t cptr, int len) 1456 { 1457 int i; 1458 1459 /* Look for the pattern "_MP_" */ 1460 for (i = 0; i < len; i += 16) { 1461 if ((*(cptr+i) == '_') && 1462 (*(cptr+i+1) == 'M') && 1463 (*(cptr+i+2) == 'P') && 1464 (*(cptr+i+3) == '_')) 1465 /*LINTED: pointer cast may result in improper alignment */ 1466 return ((struct apic_mpfps_hdr *)(cptr + i)); 1467 } 1468 return (NULL); 1469 } 1470 1471 static int 1472 apic_checksum(caddr_t bptr, int len) 1473 { 1474 int i; 1475 uchar_t cksum; 1476 1477 cksum = 0; 1478 for (i = 0; i < len; i++) 1479 cksum += *bptr++; 1480 return ((int)cksum); 1481 } 1482 1483 1484 /* 1485 * Initialise vector->ipl and ipl->pri arrays. level_intr and irqtable 1486 * are also set to NULL. vector->irq is set to a value which cannot map 1487 * to a real irq to show that it is free. 1488 */ 1489 void 1490 apic_init() 1491 { 1492 int i; 1493 int *iptr; 1494 1495 int j = 1; 1496 apic_ipltopri[0] = APIC_VECTOR_PER_IPL; /* leave 0 for idle */ 1497 for (i = 0; i < (APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL); i++) { 1498 if ((i < ((APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL) - 1)) && 1499 (apic_vectortoipl[i + 1] == apic_vectortoipl[i])) 1500 /* get to highest vector at the same ipl */ 1501 continue; 1502 for (; j <= apic_vectortoipl[i]; j++) { 1503 apic_ipltopri[j] = (i << APIC_IPL_SHIFT) + 1504 APIC_BASE_VECT; 1505 } 1506 } 1507 for (; j < MAXIPL + 1; j++) 1508 /* fill up any empty ipltopri slots */ 1509 apic_ipltopri[j] = (i << APIC_IPL_SHIFT) + APIC_BASE_VECT; 1510 1511 /* cpu 0 is always up */ 1512 apic_cpus[0].aci_status = APIC_CPU_ONLINE | APIC_CPU_INTR_ENABLE; 1513 1514 iptr = (int *)&apic_irq_table[0]; 1515 for (i = 0; i <= APIC_MAX_VECTOR; i++) { 1516 apic_level_intr[i] = 0; 1517 *iptr++ = NULL; 1518 apic_vector_to_irq[i] = APIC_RESV_IRQ; 1519 apic_reprogram_info[i].valid = 0; 1520 apic_reprogram_info[i].bindcpu = 0; 1521 apic_reprogram_info[i].timeouts = 0; 1522 } 1523 1524 /* 1525 * Allocate a dummy irq table entry for the reserved entry. 1526 * This takes care of the race between removing an irq and 1527 * clock detecting a CPU in that irq during interrupt load 1528 * sampling. 1529 */ 1530 apic_irq_table[APIC_RESV_IRQ] = 1531 kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); 1532 1533 mutex_init(&airq_mutex, NULL, MUTEX_DEFAULT, NULL); 1534 mutex_init(&apic_reprogram_timeout_mutex, NULL, MUTEX_DEFAULT, NULL); 1535 #if defined(__amd64) 1536 /* 1537 * Make cpu-specific interrupt info point to cr8pri vector 1538 */ 1539 for (i = 0; i <= MAXIPL; i++) 1540 apic_cr8pri[i] = apic_ipltopri[i] >> APIC_IPL_SHIFT; 1541 CPU->cpu_pri_data = apic_cr8pri; 1542 intpri_use_cr8 = 1; 1543 #endif /* __amd64 */ 1544 } 1545 1546 /* 1547 * handler for APIC Error interrupt. Just print a warning and continue 1548 */ 1549 static int 1550 apic_error_intr() 1551 { 1552 uint_t error0, error1, error; 1553 uint_t i; 1554 1555 /* 1556 * We need to write before read as per 7.4.17 of system prog manual. 1557 * We do both and or the results to be safe 1558 */ 1559 error0 = apicadr[APIC_ERROR_STATUS]; 1560 apicadr[APIC_ERROR_STATUS] = 0; 1561 error1 = apicadr[APIC_ERROR_STATUS]; 1562 error = error0 | error1; 1563 1564 /* 1565 * Clear the APIC error status (do this on all cpus that enter here) 1566 * (two writes are required due to the semantics of accessing the 1567 * error status register.) 1568 */ 1569 apicadr[APIC_ERROR_STATUS] = 0; 1570 apicadr[APIC_ERROR_STATUS] = 0; 1571 1572 /* 1573 * Prevent more than 1 CPU from handling error interrupt causing 1574 * double printing (interleave of characters from multiple 1575 * CPU's when using prom_printf) 1576 */ 1577 if (lock_try(&apic_error_lock) == 0) 1578 return (error ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED); 1579 if (error) { 1580 #if DEBUG 1581 if (apic_debug) 1582 debug_enter("pcplusmp: APIC Error interrupt received"); 1583 #endif /* DEBUG */ 1584 if (apic_panic_on_apic_error) 1585 cmn_err(CE_PANIC, 1586 "APIC Error interrupt on CPU %d. Status = %x\n", 1587 psm_get_cpu_id(), error); 1588 else { 1589 if ((error & ~APIC_CS_ERRORS) == 0) { 1590 /* cksum error only */ 1591 apic_error |= APIC_ERR_APIC_ERROR; 1592 apic_apic_error |= error; 1593 apic_num_apic_errors++; 1594 apic_num_cksum_errors++; 1595 } else { 1596 /* 1597 * prom_printf is the best shot we have of 1598 * something which is problem free from 1599 * high level/NMI type of interrupts 1600 */ 1601 prom_printf("APIC Error interrupt on CPU %d. " 1602 "Status 0 = %x, Status 1 = %x\n", 1603 psm_get_cpu_id(), error0, error1); 1604 apic_error |= APIC_ERR_APIC_ERROR; 1605 apic_apic_error |= error; 1606 apic_num_apic_errors++; 1607 for (i = 0; i < apic_error_display_delay; i++) { 1608 tenmicrosec(); 1609 } 1610 /* 1611 * provide more delay next time limited to 1612 * roughly 1 clock tick time 1613 */ 1614 if (apic_error_display_delay < 500) 1615 apic_error_display_delay *= 2; 1616 } 1617 } 1618 lock_clear(&apic_error_lock); 1619 return (DDI_INTR_CLAIMED); 1620 } else { 1621 lock_clear(&apic_error_lock); 1622 return (DDI_INTR_UNCLAIMED); 1623 } 1624 /* NOTREACHED */ 1625 } 1626 1627 /* 1628 * Turn off the mask bit in the performance counter Local Vector Table entry. 1629 */ 1630 static void 1631 apic_cpcovf_mask_clear(void) 1632 { 1633 apicadr[APIC_PCINT_VECT] &= ~APIC_LVT_MASK; 1634 } 1635 1636 static void 1637 apic_init_intr() 1638 { 1639 processorid_t cpun = psm_get_cpu_id(); 1640 1641 #if defined(__amd64) 1642 setcr8((ulong_t)(APIC_MASK_ALL >> APIC_IPL_SHIFT)); 1643 #else 1644 apicadr[APIC_TASK_REG] = APIC_MASK_ALL; 1645 #endif 1646 1647 if (apic_flat_model) 1648 apicadr[APIC_FORMAT_REG] = APIC_FLAT_MODEL; 1649 else 1650 apicadr[APIC_FORMAT_REG] = APIC_CLUSTER_MODEL; 1651 apicadr[APIC_DEST_REG] = AV_HIGH_ORDER >> cpun; 1652 1653 /* need to enable APIC before unmasking NMI */ 1654 apicadr[APIC_SPUR_INT_REG] = AV_UNIT_ENABLE | APIC_SPUR_INTR; 1655 1656 apicadr[APIC_LOCAL_TIMER] = AV_MASK; 1657 apicadr[APIC_INT_VECT0] = AV_MASK; /* local intr reg 0 */ 1658 apicadr[APIC_INT_VECT1] = AV_NMI; /* enable NMI */ 1659 1660 if (apic_cpus[cpun].aci_local_ver < APIC_INTEGRATED_VERS) 1661 return; 1662 1663 /* Enable performance counter overflow interrupt */ 1664 1665 if ((x86_feature & X86_MSR) != X86_MSR) 1666 apic_enable_cpcovf_intr = 0; 1667 if (apic_enable_cpcovf_intr) { 1668 if (apic_cpcovf_vect == 0) { 1669 int ipl = APIC_PCINT_IPL; 1670 int irq = apic_get_ipivect(ipl, -1); 1671 1672 ASSERT(irq != -1); 1673 apic_cpcovf_vect = apic_irq_table[irq]->airq_vector; 1674 ASSERT(apic_cpcovf_vect); 1675 (void) add_avintr(NULL, ipl, 1676 (avfunc)kcpc_hw_overflow_intr, 1677 "apic pcint", irq, NULL, NULL, NULL, NULL); 1678 kcpc_hw_overflow_intr_installed = 1; 1679 kcpc_hw_enable_cpc_intr = apic_cpcovf_mask_clear; 1680 } 1681 apicadr[APIC_PCINT_VECT] = apic_cpcovf_vect; 1682 } 1683 1684 /* Enable error interrupt */ 1685 1686 if (apic_enable_error_intr) { 1687 if (apic_errvect == 0) { 1688 int ipl = 0xf; /* get highest priority intr */ 1689 int irq = apic_get_ipivect(ipl, -1); 1690 1691 ASSERT(irq != -1); 1692 apic_errvect = apic_irq_table[irq]->airq_vector; 1693 ASSERT(apic_errvect); 1694 /* 1695 * Not PSMI compliant, but we are going to merge 1696 * with ON anyway 1697 */ 1698 (void) add_avintr((void *)NULL, ipl, 1699 (avfunc)apic_error_intr, "apic error intr", 1700 irq, NULL, NULL, NULL, NULL); 1701 } 1702 apicadr[APIC_ERR_VECT] = apic_errvect; 1703 apicadr[APIC_ERROR_STATUS] = 0; 1704 apicadr[APIC_ERROR_STATUS] = 0; 1705 } 1706 } 1707 1708 static void 1709 apic_disable_local_apic() 1710 { 1711 apicadr[APIC_TASK_REG] = APIC_MASK_ALL; 1712 apicadr[APIC_LOCAL_TIMER] = AV_MASK; 1713 apicadr[APIC_INT_VECT0] = AV_MASK; /* local intr reg 0 */ 1714 apicadr[APIC_INT_VECT1] = AV_MASK; /* disable NMI */ 1715 apicadr[APIC_ERR_VECT] = AV_MASK; /* and error interrupt */ 1716 apicadr[APIC_PCINT_VECT] = AV_MASK; /* and perf counter intr */ 1717 apicadr[APIC_SPUR_INT_REG] = APIC_SPUR_INTR; 1718 } 1719 1720 static void 1721 apic_picinit(void) 1722 { 1723 int i, j; 1724 uint_t isr; 1725 volatile int32_t *ioapic; 1726 apic_irq_t *irqptr; 1727 struct intrspec ispec; 1728 1729 /* 1730 * On UniSys Model 6520, the BIOS leaves vector 0x20 isr 1731 * bit on without clearing it with EOI. Since softint 1732 * uses vector 0x20 to interrupt itself, so softint will 1733 * not work on this machine. In order to fix this problem 1734 * a check is made to verify all the isr bits are clear. 1735 * If not, EOIs are issued to clear the bits. 1736 */ 1737 for (i = 7; i >= 1; i--) { 1738 if ((isr = apicadr[APIC_ISR_REG + (i * 4)]) != 0) 1739 for (j = 0; ((j < 32) && (isr != 0)); j++) 1740 if (isr & (1 << j)) { 1741 apicadr[APIC_EOI_REG] = 0; 1742 isr &= ~(1 << j); 1743 apic_error |= APIC_ERR_BOOT_EOI; 1744 } 1745 } 1746 1747 /* set a flag so we know we have run apic_picinit() */ 1748 apic_flag = 1; 1749 LOCK_INIT_CLEAR(&apic_gethrtime_lock); 1750 LOCK_INIT_CLEAR(&apic_ioapic_lock); 1751 LOCK_INIT_CLEAR(&apic_revector_lock); 1752 LOCK_INIT_CLEAR(&apic_ioapic_reprogram_lock); 1753 LOCK_INIT_CLEAR(&apic_error_lock); 1754 1755 picsetup(); /* initialise the 8259 */ 1756 1757 /* add nmi handler - least priority nmi handler */ 1758 LOCK_INIT_CLEAR(&apic_nmi_lock); 1759 1760 if (!psm_add_nmintr(0, (avfunc) apic_nmi_intr, 1761 "pcplusmp NMI handler", (caddr_t)NULL)) 1762 cmn_err(CE_WARN, "pcplusmp: Unable to add nmi handler"); 1763 1764 apic_init_intr(); 1765 1766 /* enable apic mode if imcr present */ 1767 if (apic_imcrp) { 1768 outb(APIC_IMCR_P1, (uchar_t)APIC_IMCR_SELECT); 1769 outb(APIC_IMCR_P2, (uchar_t)APIC_IMCR_APIC); 1770 } 1771 1772 /* mask interrupt vectors */ 1773 for (j = 0; j < apic_io_max; j++) { 1774 int intin_max; 1775 ioapic = apicioadr[j]; 1776 ioapic[APIC_IO_REG] = APIC_VERS_CMD; 1777 /* Bits 23-16 define the maximum redirection entries */ 1778 intin_max = (ioapic[APIC_IO_DATA] >> 16) & 0xff; 1779 for (i = 0; i < intin_max; i++) { 1780 ioapic[APIC_IO_REG] = APIC_RDT_CMD + 2 * i; 1781 ioapic[APIC_IO_DATA] = AV_MASK; 1782 } 1783 } 1784 1785 /* 1786 * Hack alert: deal with ACPI SCI interrupt chicken/egg here 1787 */ 1788 if (apic_sci_vect > 0) { 1789 /* 1790 * acpica has already done add_avintr(); we just 1791 * to finish the job by mimicing translate_irq() 1792 * 1793 * Fake up an intrspec and setup the tables 1794 */ 1795 ispec.intrspec_vec = apic_sci_vect; 1796 ispec.intrspec_pri = SCI_IPL; 1797 1798 if (apic_setup_irq_table(NULL, apic_sci_vect, NULL, 1799 &ispec, &apic_sci_flags, DDI_INTR_TYPE_FIXED) < 0) { 1800 cmn_err(CE_WARN, "!apic: SCI setup failed"); 1801 return; 1802 } 1803 irqptr = apic_irq_table[apic_sci_vect]; 1804 1805 /* Program I/O APIC */ 1806 (void) apic_setup_io_intr(irqptr, apic_sci_vect); 1807 1808 irqptr->airq_share++; 1809 } 1810 } 1811 1812 1813 static void 1814 apic_cpu_start(processorid_t cpun, caddr_t rm_code) 1815 { 1816 int loop_count; 1817 uint32_t vector; 1818 uint_t cpu_id, iflag; 1819 1820 cpu_id = apic_cpus[cpun].aci_local_id; 1821 1822 apic_cmos_ssb_set = 1; 1823 1824 /* 1825 * Interrupts on BSP cpu will be disabled during these startup 1826 * steps in order to avoid unwanted side effects from 1827 * executing interrupt handlers on a problematic BIOS. 1828 */ 1829 1830 iflag = intr_clear(); 1831 outb(CMOS_ADDR, SSB); 1832 outb(CMOS_DATA, BIOS_SHUTDOWN); 1833 1834 while (get_apic_cmd1() & AV_PENDING) 1835 apic_ret(); 1836 1837 /* for integrated - make sure there is one INIT IPI in buffer */ 1838 /* for external - it will wake up the cpu */ 1839 apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET; 1840 apicadr[APIC_INT_CMD1] = AV_ASSERT | AV_RESET; 1841 1842 /* If only 1 CPU is installed, PENDING bit will not go low */ 1843 for (loop_count = 0x1000; loop_count; loop_count--) 1844 if (get_apic_cmd1() & AV_PENDING) 1845 apic_ret(); 1846 else 1847 break; 1848 1849 apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET; 1850 apicadr[APIC_INT_CMD1] = AV_DEASSERT | AV_RESET; 1851 1852 drv_usecwait(20000); /* 20 milli sec */ 1853 1854 if (apic_cpus[cpun].aci_local_ver >= APIC_INTEGRATED_VERS) { 1855 /* integrated apic */ 1856 1857 rm_code = (caddr_t)(uintptr_t)rm_platter_pa; 1858 vector = (rm_platter_pa >> MMU_PAGESHIFT) & 1859 (APIC_VECTOR_MASK | APIC_IPL_MASK); 1860 1861 /* to offset the INIT IPI queue up in the buffer */ 1862 apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET; 1863 apicadr[APIC_INT_CMD1] = vector | AV_STARTUP; 1864 1865 drv_usecwait(200); /* 20 micro sec */ 1866 1867 apicadr[APIC_INT_CMD2] = cpu_id << APIC_ICR_ID_BIT_OFFSET; 1868 apicadr[APIC_INT_CMD1] = vector | AV_STARTUP; 1869 1870 drv_usecwait(200); /* 20 micro sec */ 1871 } 1872 intr_restore(iflag); 1873 } 1874 1875 1876 #ifdef DEBUG 1877 int apic_break_on_cpu = 9; 1878 int apic_stretch_interrupts = 0; 1879 int apic_stretch_ISR = 1 << 3; /* IPL of 3 matches nothing now */ 1880 1881 void 1882 apic_break() 1883 { 1884 } 1885 #endif /* DEBUG */ 1886 1887 /* 1888 * platform_intr_enter 1889 * 1890 * Called at the beginning of the interrupt service routine to 1891 * mask all level equal to and below the interrupt priority 1892 * of the interrupting vector. An EOI should be given to 1893 * the interrupt controller to enable other HW interrupts. 1894 * 1895 * Return -1 for spurious interrupts 1896 * 1897 */ 1898 /*ARGSUSED*/ 1899 static int 1900 apic_intr_enter(int ipl, int *vectorp) 1901 { 1902 uchar_t vector; 1903 int nipl; 1904 int irq, iflag; 1905 apic_cpus_info_t *cpu_infop; 1906 1907 /* 1908 * The real vector programmed in APIC is *vectorp + 0x20 1909 * But, cmnint code subtracts 0x20 before pushing it. 1910 * Hence APIC_BASE_VECT is 0x20. 1911 */ 1912 1913 vector = (uchar_t)*vectorp; 1914 1915 /* if interrupted by the clock, increment apic_nsec_since_boot */ 1916 if (vector == apic_clkvect) { 1917 if (!apic_oneshot) { 1918 /* NOTE: this is not MT aware */ 1919 apic_hrtime_stamp++; 1920 apic_nsec_since_boot += apic_nsec_per_intr; 1921 apic_hrtime_stamp++; 1922 last_count_read = apic_hertz_count; 1923 apic_redistribute_compute(); 1924 } 1925 1926 /* We will avoid all the book keeping overhead for clock */ 1927 nipl = apic_vectortoipl[vector >> APIC_IPL_SHIFT]; 1928 #if defined(__amd64) 1929 setcr8((ulong_t)apic_cr8pri[nipl]); 1930 #else 1931 apicadr[APIC_TASK_REG] = apic_ipltopri[nipl]; 1932 #endif 1933 *vectorp = apic_vector_to_irq[vector + APIC_BASE_VECT]; 1934 apicadr[APIC_EOI_REG] = 0; 1935 return (nipl); 1936 } 1937 1938 cpu_infop = &apic_cpus[psm_get_cpu_id()]; 1939 1940 if (vector == (APIC_SPUR_INTR - APIC_BASE_VECT)) { 1941 cpu_infop->aci_spur_cnt++; 1942 return (APIC_INT_SPURIOUS); 1943 } 1944 1945 /* Check if the vector we got is really what we need */ 1946 if (apic_revector_pending) { 1947 /* 1948 * Disable interrupts for the duration of 1949 * the vector translation to prevent a self-race for 1950 * the apic_revector_lock. This cannot be done 1951 * in apic_xlate_vector because it is recursive and 1952 * we want the vector translation to be atomic with 1953 * respect to other (higher-priority) interrupts. 1954 */ 1955 iflag = intr_clear(); 1956 vector = apic_xlate_vector(vector + APIC_BASE_VECT) - 1957 APIC_BASE_VECT; 1958 intr_restore(iflag); 1959 } 1960 1961 nipl = apic_vectortoipl[vector >> APIC_IPL_SHIFT]; 1962 *vectorp = irq = apic_vector_to_irq[vector + APIC_BASE_VECT]; 1963 1964 #if defined(__amd64) 1965 setcr8((ulong_t)apic_cr8pri[nipl]); 1966 #else 1967 apicadr[APIC_TASK_REG] = apic_ipltopri[nipl]; 1968 #endif 1969 1970 cpu_infop->aci_current[nipl] = (uchar_t)irq; 1971 cpu_infop->aci_curipl = (uchar_t)nipl; 1972 cpu_infop->aci_ISR_in_progress |= 1 << nipl; 1973 1974 /* 1975 * apic_level_intr could have been assimilated into the irq struct. 1976 * but, having it as a character array is more efficient in terms of 1977 * cache usage. So, we leave it as is. 1978 */ 1979 if (!apic_level_intr[irq]) 1980 apicadr[APIC_EOI_REG] = 0; 1981 1982 #ifdef DEBUG 1983 APIC_DEBUG_BUF_PUT(vector); 1984 APIC_DEBUG_BUF_PUT(irq); 1985 APIC_DEBUG_BUF_PUT(nipl); 1986 APIC_DEBUG_BUF_PUT(psm_get_cpu_id()); 1987 if ((apic_stretch_interrupts) && (apic_stretch_ISR & (1 << nipl))) 1988 drv_usecwait(apic_stretch_interrupts); 1989 1990 if (apic_break_on_cpu == psm_get_cpu_id()) 1991 apic_break(); 1992 #endif /* DEBUG */ 1993 return (nipl); 1994 } 1995 1996 static void 1997 apic_intr_exit(int prev_ipl, int irq) 1998 { 1999 apic_cpus_info_t *cpu_infop; 2000 2001 #if defined(__amd64) 2002 setcr8((ulong_t)apic_cr8pri[prev_ipl]); 2003 #else 2004 apicadr[APIC_TASK_REG] = apic_ipltopri[prev_ipl]; 2005 #endif 2006 2007 cpu_infop = &apic_cpus[psm_get_cpu_id()]; 2008 if (apic_level_intr[irq]) 2009 apicadr[APIC_EOI_REG] = 0; 2010 2011 cpu_infop->aci_curipl = (uchar_t)prev_ipl; 2012 /* ISR above current pri could not be in progress */ 2013 cpu_infop->aci_ISR_in_progress &= (2 << prev_ipl) - 1; 2014 } 2015 2016 /* 2017 * Mask all interrupts below or equal to the given IPL 2018 */ 2019 static void 2020 apic_setspl(int ipl) 2021 { 2022 2023 #if defined(__amd64) 2024 setcr8((ulong_t)apic_cr8pri[ipl]); 2025 #else 2026 apicadr[APIC_TASK_REG] = apic_ipltopri[ipl]; 2027 #endif 2028 2029 /* interrupts at ipl above this cannot be in progress */ 2030 apic_cpus[psm_get_cpu_id()].aci_ISR_in_progress &= (2 << ipl) - 1; 2031 /* 2032 * this is a patch fix for the ALR QSMP P5 machine, so that interrupts 2033 * have enough time to come in before the priority is raised again 2034 * during the idle() loop. 2035 */ 2036 if (apic_setspl_delay) 2037 (void) get_apic_pri(); 2038 } 2039 2040 /* 2041 * trigger a software interrupt at the given IPL 2042 */ 2043 static void 2044 apic_set_softintr(int ipl) 2045 { 2046 int vector; 2047 uint_t flag; 2048 2049 vector = apic_resv_vector[ipl]; 2050 2051 flag = intr_clear(); 2052 2053 while (get_apic_cmd1() & AV_PENDING) 2054 apic_ret(); 2055 2056 /* generate interrupt at vector on itself only */ 2057 apicadr[APIC_INT_CMD1] = AV_SH_SELF | vector; 2058 2059 intr_restore(flag); 2060 } 2061 2062 /* 2063 * generates an interprocessor interrupt to another CPU 2064 */ 2065 static void 2066 apic_send_ipi(int cpun, int ipl) 2067 { 2068 int vector; 2069 uint_t flag; 2070 2071 vector = apic_resv_vector[ipl]; 2072 2073 flag = intr_clear(); 2074 2075 while (get_apic_cmd1() & AV_PENDING) 2076 apic_ret(); 2077 2078 apicadr[APIC_INT_CMD2] = 2079 apic_cpus[cpun].aci_local_id << APIC_ICR_ID_BIT_OFFSET; 2080 apicadr[APIC_INT_CMD1] = vector; 2081 2082 intr_restore(flag); 2083 } 2084 2085 2086 /*ARGSUSED*/ 2087 static void 2088 apic_set_idlecpu(processorid_t cpun) 2089 { 2090 } 2091 2092 /*ARGSUSED*/ 2093 static void 2094 apic_unset_idlecpu(processorid_t cpun) 2095 { 2096 } 2097 2098 2099 static void 2100 apic_ret() 2101 { 2102 } 2103 2104 static int 2105 get_apic_cmd1() 2106 { 2107 return (apicadr[APIC_INT_CMD1]); 2108 } 2109 2110 static int 2111 get_apic_pri() 2112 { 2113 #if defined(__amd64) 2114 return ((int)getcr8()); 2115 #else 2116 return (apicadr[APIC_TASK_REG]); 2117 #endif 2118 } 2119 2120 /* 2121 * If apic_coarse_time == 1, then apic_gettime() is used instead of 2122 * apic_gethrtime(). This is used for performance instead of accuracy. 2123 */ 2124 2125 static hrtime_t 2126 apic_gettime() 2127 { 2128 int old_hrtime_stamp; 2129 hrtime_t temp; 2130 2131 /* 2132 * In one-shot mode, we do not keep time, so if anyone 2133 * calls psm_gettime() directly, we vector over to 2134 * gethrtime(). 2135 * one-shot mode MUST NOT be enabled if this psm is the source of 2136 * hrtime. 2137 */ 2138 2139 if (apic_oneshot) 2140 return (gethrtime()); 2141 2142 2143 gettime_again: 2144 while ((old_hrtime_stamp = apic_hrtime_stamp) & 1) 2145 apic_ret(); 2146 2147 temp = apic_nsec_since_boot; 2148 2149 if (apic_hrtime_stamp != old_hrtime_stamp) { /* got an interrupt */ 2150 goto gettime_again; 2151 } 2152 return (temp); 2153 } 2154 2155 /* 2156 * Here we return the number of nanoseconds since booting. Note every 2157 * clock interrupt increments apic_nsec_since_boot by the appropriate 2158 * amount. 2159 */ 2160 static hrtime_t 2161 apic_gethrtime() 2162 { 2163 int curr_timeval, countval, elapsed_ticks, oflags; 2164 int old_hrtime_stamp, status; 2165 hrtime_t temp; 2166 uchar_t cpun; 2167 2168 2169 /* 2170 * In one-shot mode, we do not keep time, so if anyone 2171 * calls psm_gethrtime() directly, we vector over to 2172 * gethrtime(). 2173 * one-shot mode MUST NOT be enabled if this psm is the source of 2174 * hrtime. 2175 */ 2176 2177 if (apic_oneshot) 2178 return (gethrtime()); 2179 2180 oflags = intr_clear(); /* prevent migration */ 2181 2182 cpun = (uchar_t)((uint_t)apicadr[APIC_LID_REG] >> APIC_ID_BIT_OFFSET); 2183 2184 lock_set(&apic_gethrtime_lock); 2185 2186 gethrtime_again: 2187 while ((old_hrtime_stamp = apic_hrtime_stamp) & 1) 2188 apic_ret(); 2189 2190 /* 2191 * Check to see which CPU we are on. Note the time is kept on 2192 * the local APIC of CPU 0. If on CPU 0, simply read the current 2193 * counter. If on another CPU, issue a remote read command to CPU 0. 2194 */ 2195 if (cpun == apic_cpus[0].aci_local_id) { 2196 countval = apicadr[APIC_CURR_COUNT]; 2197 } else { 2198 while (get_apic_cmd1() & AV_PENDING) 2199 apic_ret(); 2200 2201 apicadr[APIC_INT_CMD2] = 2202 apic_cpus[0].aci_local_id << APIC_ICR_ID_BIT_OFFSET; 2203 apicadr[APIC_INT_CMD1] = APIC_CURR_ADD|AV_REMOTE; 2204 2205 while ((status = get_apic_cmd1()) & AV_READ_PENDING) 2206 apic_ret(); 2207 2208 if (status & AV_REMOTE_STATUS) /* 1 = valid */ 2209 countval = apicadr[APIC_REMOTE_READ]; 2210 else { /* 0 = invalid */ 2211 apic_remote_hrterr++; 2212 /* 2213 * return last hrtime right now, will need more 2214 * testing if change to retry 2215 */ 2216 temp = apic_last_hrtime; 2217 2218 lock_clear(&apic_gethrtime_lock); 2219 2220 intr_restore(oflags); 2221 2222 return (temp); 2223 } 2224 } 2225 if (countval > last_count_read) 2226 countval = 0; 2227 else 2228 last_count_read = countval; 2229 2230 elapsed_ticks = apic_hertz_count - countval; 2231 2232 curr_timeval = elapsed_ticks * apic_nsec_per_tick; 2233 temp = apic_nsec_since_boot + curr_timeval; 2234 2235 if (apic_hrtime_stamp != old_hrtime_stamp) { /* got an interrupt */ 2236 /* we might have clobbered last_count_read. Restore it */ 2237 last_count_read = apic_hertz_count; 2238 goto gethrtime_again; 2239 } 2240 2241 if (temp < apic_last_hrtime) { 2242 /* return last hrtime if error occurs */ 2243 apic_hrtime_error++; 2244 temp = apic_last_hrtime; 2245 } 2246 else 2247 apic_last_hrtime = temp; 2248 2249 lock_clear(&apic_gethrtime_lock); 2250 intr_restore(oflags); 2251 2252 return (temp); 2253 } 2254 2255 /* apic NMI handler */ 2256 /*ARGSUSED*/ 2257 static void 2258 apic_nmi_intr(caddr_t arg) 2259 { 2260 if (apic_shutdown_processors) { 2261 apic_disable_local_apic(); 2262 return; 2263 } 2264 2265 if (lock_try(&apic_nmi_lock)) { 2266 if (apic_kmdb_on_nmi) { 2267 if (psm_debugger() == 0) { 2268 cmn_err(CE_PANIC, 2269 "NMI detected, kmdb is not available."); 2270 } else { 2271 debug_enter("\nNMI detected, entering kmdb.\n"); 2272 } 2273 } else { 2274 if (apic_panic_on_nmi) { 2275 /* Keep panic from entering kmdb. */ 2276 nopanicdebug = 1; 2277 cmn_err(CE_PANIC, "pcplusmp: NMI received"); 2278 } else { 2279 /* 2280 * prom_printf is the best shot we have 2281 * of something which is problem free from 2282 * high level/NMI type of interrupts 2283 */ 2284 prom_printf("pcplusmp: NMI received\n"); 2285 apic_error |= APIC_ERR_NMI; 2286 apic_num_nmis++; 2287 } 2288 } 2289 lock_clear(&apic_nmi_lock); 2290 } 2291 } 2292 2293 /* 2294 * Add mask bits to disable interrupt vector from happening 2295 * at or above IPL. In addition, it should remove mask bits 2296 * to enable interrupt vectors below the given IPL. 2297 * 2298 * Both add and delspl are complicated by the fact that different interrupts 2299 * may share IRQs. This can happen in two ways. 2300 * 1. The same H/W line is shared by more than 1 device 2301 * 1a. with interrupts at different IPLs 2302 * 1b. with interrupts at same IPL 2303 * 2. We ran out of vectors at a given IPL and started sharing vectors. 2304 * 1b and 2 should be handled gracefully, except for the fact some ISRs 2305 * will get called often when no interrupt is pending for the device. 2306 * For 1a, we just hope that the machine blows up with the person who 2307 * set it up that way!. In the meantime, we handle it at the higher IPL. 2308 */ 2309 /*ARGSUSED*/ 2310 static int 2311 apic_addspl(int irqno, int ipl, int min_ipl, int max_ipl) 2312 { 2313 uchar_t vector; 2314 int iflag; 2315 apic_irq_t *irqptr, *irqheadptr; 2316 int irqindex; 2317 2318 ASSERT(max_ipl <= UCHAR_MAX); 2319 irqindex = IRQINDEX(irqno); 2320 2321 if ((irqindex == -1) || (!apic_irq_table[irqindex])) 2322 return (PSM_FAILURE); 2323 2324 irqptr = irqheadptr = apic_irq_table[irqindex]; 2325 2326 DDI_INTR_IMPLDBG((CE_CONT, "apic_addspl: dip=0x%p type=%d irqno=0x%x " 2327 "vector=0x%x\n", (void *)irqptr->airq_dip, 2328 irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); 2329 2330 while (irqptr) { 2331 if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) 2332 break; 2333 irqptr = irqptr->airq_next; 2334 } 2335 irqptr->airq_share++; 2336 2337 /* return if it is not hardware interrupt */ 2338 if (irqptr->airq_mps_intr_index == RESERVE_INDEX) 2339 return (PSM_SUCCESS); 2340 2341 /* Or if there are more interupts at a higher IPL */ 2342 if (ipl != max_ipl) 2343 return (PSM_SUCCESS); 2344 2345 /* 2346 * if apic_picinit() has not been called yet, just return. 2347 * At the end of apic_picinit(), we will call setup_io_intr(). 2348 */ 2349 2350 if (!apic_flag) 2351 return (PSM_SUCCESS); 2352 2353 iflag = intr_clear(); 2354 2355 /* 2356 * Upgrade vector if max_ipl is not earlier ipl. If we cannot allocate, 2357 * return failure. Not very elegant, but then we hope the 2358 * machine will blow up with ... 2359 */ 2360 if (irqptr->airq_ipl != max_ipl) { 2361 vector = apic_allocate_vector(max_ipl, irqindex, 1); 2362 if (vector == 0) { 2363 intr_restore(iflag); 2364 irqptr->airq_share--; 2365 return (PSM_FAILURE); 2366 } 2367 irqptr = irqheadptr; 2368 apic_mark_vector(irqptr->airq_vector, vector); 2369 while (irqptr) { 2370 irqptr->airq_vector = vector; 2371 irqptr->airq_ipl = (uchar_t)max_ipl; 2372 /* 2373 * reprogram irq being added and every one else 2374 * who is not in the UNINIT state 2375 */ 2376 if ((VIRTIRQ(irqindex, irqptr->airq_share_id) == 2377 irqno) || (irqptr->airq_temp_cpu != IRQ_UNINIT)) { 2378 apic_record_rdt_entry(irqptr, irqindex); 2379 (void) apic_setup_io_intr(irqptr, irqindex); 2380 } 2381 irqptr = irqptr->airq_next; 2382 } 2383 intr_restore(iflag); 2384 return (PSM_SUCCESS); 2385 } 2386 2387 ASSERT(irqptr); 2388 (void) apic_setup_io_intr(irqptr, irqindex); 2389 intr_restore(iflag); 2390 return (PSM_SUCCESS); 2391 } 2392 2393 /* 2394 * Recompute mask bits for the given interrupt vector. 2395 * If there is no interrupt servicing routine for this 2396 * vector, this function should disable interrupt vector 2397 * from happening at all IPLs. If there are still 2398 * handlers using the given vector, this function should 2399 * disable the given vector from happening below the lowest 2400 * IPL of the remaining hadlers. 2401 */ 2402 /*ARGSUSED*/ 2403 static int 2404 apic_delspl(int irqno, int ipl, int min_ipl, int max_ipl) 2405 { 2406 uchar_t vector, bind_cpu; 2407 int iflag, intin, irqindex; 2408 volatile int32_t *ioapic; 2409 apic_irq_t *irqptr, *irqheadptr; 2410 2411 irqindex = IRQINDEX(irqno); 2412 irqptr = irqheadptr = apic_irq_table[irqindex]; 2413 2414 DDI_INTR_IMPLDBG((CE_CONT, "apic_delspl: dip=0x%p type=%d irqno=0x%x " 2415 "vector=0x%x\n", (void *)irqptr->airq_dip, 2416 irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); 2417 2418 while (irqptr) { 2419 if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) 2420 break; 2421 irqptr = irqptr->airq_next; 2422 } 2423 ASSERT(irqptr); 2424 2425 irqptr->airq_share--; 2426 2427 if (ipl < max_ipl) 2428 return (PSM_SUCCESS); 2429 2430 /* return if it is not hardware interrupt */ 2431 if (irqptr->airq_mps_intr_index == RESERVE_INDEX) 2432 return (PSM_SUCCESS); 2433 2434 if (!apic_flag) { 2435 /* 2436 * Clear irq_struct. If two devices shared an intpt 2437 * line & 1 unloaded before picinit, we are hosed. But, then 2438 * we hope the machine will ... 2439 */ 2440 irqptr->airq_mps_intr_index = FREE_INDEX; 2441 irqptr->airq_temp_cpu = IRQ_UNINIT; 2442 apic_free_vector(irqptr->airq_vector); 2443 return (PSM_SUCCESS); 2444 } 2445 /* 2446 * Downgrade vector to new max_ipl if needed.If we cannot allocate, 2447 * use old IPL. Not very elegant, but then we hope ... 2448 */ 2449 if ((irqptr->airq_ipl != max_ipl) && (max_ipl != PSM_INVALID_IPL)) { 2450 apic_irq_t *irqp; 2451 if (vector = apic_allocate_vector(max_ipl, irqno, 1)) { 2452 apic_mark_vector(irqheadptr->airq_vector, vector); 2453 irqp = irqheadptr; 2454 while (irqp) { 2455 irqp->airq_vector = vector; 2456 irqp->airq_ipl = (uchar_t)max_ipl; 2457 if (irqp->airq_temp_cpu != IRQ_UNINIT) { 2458 apic_record_rdt_entry(irqp, irqindex); 2459 (void) apic_setup_io_intr(irqp, 2460 irqindex); 2461 } 2462 irqp = irqp->airq_next; 2463 } 2464 } 2465 } 2466 2467 if (irqptr->airq_share) 2468 return (PSM_SUCCESS); 2469 2470 ioapic = apicioadr[irqptr->airq_ioapicindex]; 2471 intin = irqptr->airq_intin_no; 2472 iflag = intr_clear(); 2473 lock_set(&apic_ioapic_lock); 2474 ioapic[APIC_IO_REG] = APIC_RDT_CMD + 2 * intin; 2475 ioapic[APIC_IO_DATA] = AV_MASK; 2476 2477 /* Disable the MSI/X vector */ 2478 if (APIC_IS_MSI_OR_MSIX_INDEX(irqptr->airq_mps_intr_index)) { 2479 int type = (irqptr->airq_mps_intr_index == MSI_INDEX) ? 2480 DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; 2481 2482 /* 2483 * Make sure we only disable on the last 2484 * of the multi-MSI support 2485 */ 2486 if (i_ddi_intr_get_current_nintrs(irqptr->airq_dip) == 1) { 2487 (void) apic_pci_msi_unconfigure(irqptr->airq_dip, 2488 type, irqptr->airq_ioapicindex); 2489 (void) apic_pci_msi_disable_mode(irqptr->airq_dip, 2490 type, irqptr->airq_ioapicindex); 2491 } 2492 } 2493 2494 if (max_ipl == PSM_INVALID_IPL) { 2495 ASSERT(irqheadptr == irqptr); 2496 bind_cpu = irqptr->airq_temp_cpu; 2497 if (((uchar_t)bind_cpu != IRQ_UNBOUND) && 2498 ((uchar_t)bind_cpu != IRQ_UNINIT)) { 2499 ASSERT((bind_cpu & ~IRQ_USER_BOUND) < apic_nproc); 2500 if (bind_cpu & IRQ_USER_BOUND) { 2501 /* If hardbound, temp_cpu == cpu */ 2502 bind_cpu &= ~IRQ_USER_BOUND; 2503 apic_cpus[bind_cpu].aci_bound--; 2504 } else 2505 apic_cpus[bind_cpu].aci_temp_bound--; 2506 } 2507 lock_clear(&apic_ioapic_lock); 2508 intr_restore(iflag); 2509 irqptr->airq_temp_cpu = IRQ_UNINIT; 2510 irqptr->airq_mps_intr_index = FREE_INDEX; 2511 apic_free_vector(irqptr->airq_vector); 2512 return (PSM_SUCCESS); 2513 } 2514 lock_clear(&apic_ioapic_lock); 2515 intr_restore(iflag); 2516 2517 mutex_enter(&airq_mutex); 2518 if ((irqptr == apic_irq_table[irqindex])) { 2519 apic_irq_t *oldirqptr; 2520 /* Move valid irq entry to the head */ 2521 irqheadptr = oldirqptr = irqptr; 2522 irqptr = irqptr->airq_next; 2523 ASSERT(irqptr); 2524 while (irqptr) { 2525 if (irqptr->airq_mps_intr_index != FREE_INDEX) 2526 break; 2527 oldirqptr = irqptr; 2528 irqptr = irqptr->airq_next; 2529 } 2530 /* remove all invalid ones from the beginning */ 2531 apic_irq_table[irqindex] = irqptr; 2532 /* 2533 * and link them back after the head. The invalid ones 2534 * begin with irqheadptr and end at oldirqptr 2535 */ 2536 oldirqptr->airq_next = irqptr->airq_next; 2537 irqptr->airq_next = irqheadptr; 2538 } 2539 mutex_exit(&airq_mutex); 2540 2541 irqptr->airq_temp_cpu = IRQ_UNINIT; 2542 irqptr->airq_mps_intr_index = FREE_INDEX; 2543 return (PSM_SUCCESS); 2544 } 2545 2546 /* 2547 * Return HW interrupt number corresponding to the given IPL 2548 */ 2549 /*ARGSUSED*/ 2550 static int 2551 apic_softlvl_to_irq(int ipl) 2552 { 2553 /* 2554 * Do not use apic to trigger soft interrupt. 2555 * It will cause the system to hang when 2 hardware interrupts 2556 * at the same priority with the softint are already accepted 2557 * by the apic. Cause the AV_PENDING bit will not be cleared 2558 * until one of the hardware interrupt is eoi'ed. If we need 2559 * to send an ipi at this time, we will end up looping forever 2560 * to wait for the AV_PENDING bit to clear. 2561 */ 2562 return (PSM_SV_SOFTWARE); 2563 } 2564 2565 static int 2566 apic_post_cpu_start() 2567 { 2568 int i, cpun; 2569 apic_irq_t *irq_ptr; 2570 2571 apic_init_intr(); 2572 2573 /* 2574 * since some systems don't enable the internal cache on the non-boot 2575 * cpus, so we have to enable them here 2576 */ 2577 setcr0(getcr0() & ~(0x60000000)); 2578 2579 while (get_apic_cmd1() & AV_PENDING) 2580 apic_ret(); 2581 2582 cpun = psm_get_cpu_id(); 2583 apic_cpus[cpun].aci_status = APIC_CPU_ONLINE | APIC_CPU_INTR_ENABLE; 2584 2585 for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { 2586 irq_ptr = apic_irq_table[i]; 2587 if ((irq_ptr == NULL) || 2588 ((irq_ptr->airq_cpu & ~IRQ_USER_BOUND) != cpun)) 2589 continue; 2590 2591 while (irq_ptr) { 2592 if (irq_ptr->airq_temp_cpu != IRQ_UNINIT) 2593 (void) apic_rebind(irq_ptr, cpun, 1, IMMEDIATE); 2594 irq_ptr = irq_ptr->airq_next; 2595 } 2596 } 2597 2598 return (PSM_SUCCESS); 2599 } 2600 2601 processorid_t 2602 apic_get_next_processorid(processorid_t cpu_id) 2603 { 2604 2605 int i; 2606 2607 if (cpu_id == -1) 2608 return ((processorid_t)0); 2609 2610 for (i = cpu_id + 1; i < NCPU; i++) { 2611 if (CPU_IN_SET(apic_cpumask, i)) 2612 return (i); 2613 } 2614 2615 return ((processorid_t)-1); 2616 } 2617 2618 2619 /* 2620 * type == -1 indicates it is an internal request. Do not change 2621 * resv_vector for these requests 2622 */ 2623 static int 2624 apic_get_ipivect(int ipl, int type) 2625 { 2626 uchar_t vector; 2627 int irq; 2628 2629 if (irq = apic_allocate_irq(APIC_VECTOR(ipl))) { 2630 if (vector = apic_allocate_vector(ipl, irq, 1)) { 2631 apic_irq_table[irq]->airq_mps_intr_index = 2632 RESERVE_INDEX; 2633 apic_irq_table[irq]->airq_vector = vector; 2634 if (type != -1) { 2635 apic_resv_vector[ipl] = vector; 2636 } 2637 return (irq); 2638 } 2639 } 2640 apic_error |= APIC_ERR_GET_IPIVECT_FAIL; 2641 return (-1); /* shouldn't happen */ 2642 } 2643 2644 static int 2645 apic_getclkirq(int ipl) 2646 { 2647 int irq; 2648 2649 if ((irq = apic_get_ipivect(ipl, -1)) == -1) 2650 return (-1); 2651 /* 2652 * Note the vector in apic_clkvect for per clock handling. 2653 */ 2654 apic_clkvect = apic_irq_table[irq]->airq_vector - APIC_BASE_VECT; 2655 APIC_VERBOSE_IOAPIC((CE_NOTE, "get_clkirq: vector = %x\n", 2656 apic_clkvect)); 2657 return (irq); 2658 } 2659 2660 /* 2661 * Return the number of APIC clock ticks elapsed for 8245 to decrement 2662 * (APIC_TIME_COUNT + pit_ticks_adj) ticks. 2663 */ 2664 static uint_t 2665 apic_calibrate(volatile uint32_t *addr, uint16_t *pit_ticks_adj) 2666 { 2667 uint8_t pit_tick_lo; 2668 uint16_t pit_tick, target_pit_tick; 2669 uint32_t start_apic_tick, end_apic_tick; 2670 int iflag; 2671 2672 addr += APIC_CURR_COUNT; 2673 2674 iflag = intr_clear(); 2675 2676 do { 2677 pit_tick_lo = inb(PITCTR0_PORT); 2678 pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo; 2679 } while (pit_tick < APIC_TIME_MIN || 2680 pit_tick_lo <= APIC_LB_MIN || pit_tick_lo >= APIC_LB_MAX); 2681 2682 /* 2683 * Wait for the 8254 to decrement by 5 ticks to ensure 2684 * we didn't start in the middle of a tick. 2685 * Compare with 0x10 for the wrap around case. 2686 */ 2687 target_pit_tick = pit_tick - 5; 2688 do { 2689 pit_tick_lo = inb(PITCTR0_PORT); 2690 pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo; 2691 } while (pit_tick > target_pit_tick || pit_tick_lo < 0x10); 2692 2693 start_apic_tick = *addr; 2694 2695 /* 2696 * Wait for the 8254 to decrement by 2697 * (APIC_TIME_COUNT + pit_ticks_adj) ticks 2698 */ 2699 target_pit_tick = pit_tick - APIC_TIME_COUNT; 2700 do { 2701 pit_tick_lo = inb(PITCTR0_PORT); 2702 pit_tick = (inb(PITCTR0_PORT) << 8) | pit_tick_lo; 2703 } while (pit_tick > target_pit_tick || pit_tick_lo < 0x10); 2704 2705 end_apic_tick = *addr; 2706 2707 *pit_ticks_adj = target_pit_tick - pit_tick; 2708 2709 intr_restore(iflag); 2710 2711 return (start_apic_tick - end_apic_tick); 2712 } 2713 2714 /* 2715 * Initialise the APIC timer on the local APIC of CPU 0 to the desired 2716 * frequency. Note at this stage in the boot sequence, the boot processor 2717 * is the only active processor. 2718 * hertz value of 0 indicates a one-shot mode request. In this case 2719 * the function returns the resolution (in nanoseconds) for the hardware 2720 * timer interrupt. If one-shot mode capability is not available, 2721 * the return value will be 0. apic_enable_oneshot is a global switch 2722 * for disabling the functionality. 2723 * A non-zero positive value for hertz indicates a periodic mode request. 2724 * In this case the hardware will be programmed to generate clock interrupts 2725 * at hertz frequency and returns the resolution of interrupts in 2726 * nanosecond. 2727 */ 2728 2729 static int 2730 apic_clkinit(int hertz) 2731 { 2732 2733 uint_t apic_ticks = 0; 2734 uint_t pit_time; 2735 int ret; 2736 uint16_t pit_ticks_adj; 2737 static int firsttime = 1; 2738 2739 if (firsttime) { 2740 /* first time calibrate */ 2741 2742 apicadr[APIC_DIVIDE_REG] = 0x0; 2743 apicadr[APIC_INIT_COUNT] = APIC_MAXVAL; 2744 2745 /* set periodic interrupt based on CLKIN */ 2746 apicadr[APIC_LOCAL_TIMER] = 2747 (apic_clkvect + APIC_BASE_VECT) | AV_TIME; 2748 tenmicrosec(); 2749 2750 apic_ticks = apic_calibrate(apicadr, &pit_ticks_adj); 2751 2752 apicadr[APIC_LOCAL_TIMER] = 2753 (apic_clkvect + APIC_BASE_VECT) | AV_MASK; 2754 /* 2755 * pit time is the amount of real time (in nanoseconds ) it took 2756 * the 8254 to decrement (APIC_TIME_COUNT + pit_ticks_adj) ticks 2757 */ 2758 pit_time = ((longlong_t)(APIC_TIME_COUNT + 2759 pit_ticks_adj) * NANOSEC) / PIT_HZ; 2760 2761 /* 2762 * Determine the number of nanoseconds per APIC clock tick 2763 * and then determine how many APIC ticks to interrupt at the 2764 * desired frequency 2765 */ 2766 apic_nsec_per_tick = pit_time / apic_ticks; 2767 if (apic_nsec_per_tick == 0) 2768 apic_nsec_per_tick = 1; 2769 2770 /* the interval timer initial count is 32 bit max */ 2771 apic_nsec_max = (hrtime_t)apic_nsec_per_tick * APIC_MAXVAL; 2772 firsttime = 0; 2773 } 2774 2775 if (hertz != 0) { 2776 /* periodic */ 2777 apic_nsec_per_intr = NANOSEC / hertz; 2778 apic_hertz_count = (longlong_t)apic_nsec_per_intr / 2779 apic_nsec_per_tick; 2780 apic_sample_factor_redistribution = hertz + 1; 2781 } 2782 2783 apic_int_busy_mark = (apic_int_busy_mark * 2784 apic_sample_factor_redistribution) / 100; 2785 apic_int_free_mark = (apic_int_free_mark * 2786 apic_sample_factor_redistribution) / 100; 2787 apic_diff_for_redistribution = (apic_diff_for_redistribution * 2788 apic_sample_factor_redistribution) / 100; 2789 2790 if (hertz == 0) { 2791 /* requested one_shot */ 2792 if (!apic_oneshot_enable) 2793 return (0); 2794 apic_oneshot = 1; 2795 ret = (int)apic_nsec_per_tick; 2796 } else { 2797 /* program the local APIC to interrupt at the given frequency */ 2798 apicadr[APIC_INIT_COUNT] = apic_hertz_count; 2799 apicadr[APIC_LOCAL_TIMER] = 2800 (apic_clkvect + APIC_BASE_VECT) | AV_TIME; 2801 apic_oneshot = 0; 2802 ret = NANOSEC / hertz; 2803 } 2804 2805 return (ret); 2806 2807 } 2808 2809 /* 2810 * apic_preshutdown: 2811 * Called early in shutdown whilst we can still access filesystems to do 2812 * things like loading modules which will be required to complete shutdown 2813 * after filesystems are all unmounted. 2814 */ 2815 static void 2816 apic_preshutdown(int cmd, int fcn) 2817 { 2818 APIC_VERBOSE_POWEROFF(("apic_preshutdown(%d,%d); m=%d a=%d\n", 2819 cmd, fcn, apic_poweroff_method, apic_enable_acpi)); 2820 2821 if ((cmd != A_SHUTDOWN) || (fcn != AD_POWEROFF)) { 2822 return; 2823 } 2824 } 2825 2826 static void 2827 apic_shutdown(int cmd, int fcn) 2828 { 2829 int iflag, restarts, attempts; 2830 int i, j; 2831 volatile int32_t *ioapic; 2832 uchar_t byte; 2833 2834 /* Send NMI to all CPUs except self to do per processor shutdown */ 2835 iflag = intr_clear(); 2836 while (get_apic_cmd1() & AV_PENDING) 2837 apic_ret(); 2838 apic_shutdown_processors = 1; 2839 apicadr[APIC_INT_CMD1] = AV_NMI | AV_LEVEL | AV_SH_ALL_EXCSELF; 2840 2841 /* restore cmos shutdown byte before reboot */ 2842 if (apic_cmos_ssb_set) { 2843 outb(CMOS_ADDR, SSB); 2844 outb(CMOS_DATA, 0); 2845 } 2846 /* Disable the I/O APIC redirection entries */ 2847 for (j = 0; j < apic_io_max; j++) { 2848 int intin_max; 2849 ioapic = apicioadr[j]; 2850 ioapic[APIC_IO_REG] = APIC_VERS_CMD; 2851 /* Bits 23-16 define the maximum redirection entries */ 2852 intin_max = (ioapic[APIC_IO_DATA] >> 16) & 0xff; 2853 for (i = 0; i < intin_max; i++) { 2854 ioapic[APIC_IO_REG] = APIC_RDT_CMD + 2 * i; 2855 ioapic[APIC_IO_DATA] = AV_MASK; 2856 } 2857 } 2858 2859 /* disable apic mode if imcr present */ 2860 if (apic_imcrp) { 2861 outb(APIC_IMCR_P1, (uchar_t)APIC_IMCR_SELECT); 2862 outb(APIC_IMCR_P2, (uchar_t)APIC_IMCR_PIC); 2863 } 2864 2865 apic_disable_local_apic(); 2866 2867 intr_restore(iflag); 2868 2869 if ((cmd != A_SHUTDOWN) || (fcn != AD_POWEROFF)) { 2870 return; 2871 } 2872 2873 switch (apic_poweroff_method) { 2874 case APIC_POWEROFF_VIA_RTC: 2875 2876 /* select the extended NVRAM bank in the RTC */ 2877 outb(CMOS_ADDR, RTC_REGA); 2878 byte = inb(CMOS_DATA); 2879 outb(CMOS_DATA, (byte | EXT_BANK)); 2880 2881 outb(CMOS_ADDR, PFR_REG); 2882 2883 /* for Predator must toggle the PAB bit */ 2884 byte = inb(CMOS_DATA); 2885 2886 /* 2887 * clear power active bar, wakeup alarm and 2888 * kickstart 2889 */ 2890 byte &= ~(PAB_CBIT | WF_FLAG | KS_FLAG); 2891 outb(CMOS_DATA, byte); 2892 2893 /* delay before next write */ 2894 drv_usecwait(1000); 2895 2896 /* for S40 the following would suffice */ 2897 byte = inb(CMOS_DATA); 2898 2899 /* power active bar control bit */ 2900 byte |= PAB_CBIT; 2901 outb(CMOS_DATA, byte); 2902 2903 break; 2904 2905 case APIC_POWEROFF_VIA_ASPEN_BMC: 2906 restarts = 0; 2907 restart_aspen_bmc: 2908 if (++restarts == 3) 2909 break; 2910 attempts = 0; 2911 do { 2912 byte = inb(MISMIC_FLAG_REGISTER); 2913 byte &= MISMIC_BUSY_MASK; 2914 if (byte != 0) { 2915 drv_usecwait(1000); 2916 if (attempts >= 3) 2917 goto restart_aspen_bmc; 2918 ++attempts; 2919 } 2920 } while (byte != 0); 2921 outb(MISMIC_CNTL_REGISTER, CC_SMS_GET_STATUS); 2922 byte = inb(MISMIC_FLAG_REGISTER); 2923 byte |= 0x1; 2924 outb(MISMIC_FLAG_REGISTER, byte); 2925 i = 0; 2926 for (; i < (sizeof (aspen_bmc)/sizeof (aspen_bmc[0])); 2927 i++) { 2928 attempts = 0; 2929 do { 2930 byte = inb(MISMIC_FLAG_REGISTER); 2931 byte &= MISMIC_BUSY_MASK; 2932 if (byte != 0) { 2933 drv_usecwait(1000); 2934 if (attempts >= 3) 2935 goto restart_aspen_bmc; 2936 ++attempts; 2937 } 2938 } while (byte != 0); 2939 outb(MISMIC_CNTL_REGISTER, aspen_bmc[i].cntl); 2940 outb(MISMIC_DATA_REGISTER, aspen_bmc[i].data); 2941 byte = inb(MISMIC_FLAG_REGISTER); 2942 byte |= 0x1; 2943 outb(MISMIC_FLAG_REGISTER, byte); 2944 } 2945 break; 2946 2947 case APIC_POWEROFF_VIA_SITKA_BMC: 2948 restarts = 0; 2949 restart_sitka_bmc: 2950 if (++restarts == 3) 2951 break; 2952 attempts = 0; 2953 do { 2954 byte = inb(SMS_STATUS_REGISTER); 2955 byte &= SMS_STATE_MASK; 2956 if ((byte == SMS_READ_STATE) || 2957 (byte == SMS_WRITE_STATE)) { 2958 drv_usecwait(1000); 2959 if (attempts >= 3) 2960 goto restart_sitka_bmc; 2961 ++attempts; 2962 } 2963 } while ((byte == SMS_READ_STATE) || 2964 (byte == SMS_WRITE_STATE)); 2965 outb(SMS_COMMAND_REGISTER, SMS_GET_STATUS); 2966 i = 0; 2967 for (; i < (sizeof (sitka_bmc)/sizeof (sitka_bmc[0])); 2968 i++) { 2969 attempts = 0; 2970 do { 2971 byte = inb(SMS_STATUS_REGISTER); 2972 byte &= SMS_IBF_MASK; 2973 if (byte != 0) { 2974 drv_usecwait(1000); 2975 if (attempts >= 3) 2976 goto restart_sitka_bmc; 2977 ++attempts; 2978 } 2979 } while (byte != 0); 2980 outb(sitka_bmc[i].port, sitka_bmc[i].data); 2981 } 2982 break; 2983 2984 case APIC_POWEROFF_NONE: 2985 2986 /* If no APIC direct method, we will try using ACPI */ 2987 if (apic_enable_acpi) { 2988 if (acpi_poweroff() == 1) 2989 return; 2990 } else 2991 return; 2992 2993 break; 2994 } 2995 /* 2996 * Wait a limited time here for power to go off. 2997 * If the power does not go off, then there was a 2998 * problem and we should continue to the halt which 2999 * prints a message for the user to press a key to 3000 * reboot. 3001 */ 3002 drv_usecwait(7000000); /* wait seven seconds */ 3003 3004 } 3005 3006 /* 3007 * Try and disable all interrupts. We just assign interrupts to other 3008 * processors based on policy. If any were bound by user request, we 3009 * let them continue and return failure. We do not bother to check 3010 * for cache affinity while rebinding. 3011 */ 3012 3013 static int 3014 apic_disable_intr(processorid_t cpun) 3015 { 3016 int bind_cpu = 0, i, hardbound = 0, iflag; 3017 apic_irq_t *irq_ptr; 3018 3019 iflag = intr_clear(); 3020 lock_set(&apic_ioapic_lock); 3021 apic_cpus[cpun].aci_status &= ~APIC_CPU_INTR_ENABLE; 3022 lock_clear(&apic_ioapic_lock); 3023 intr_restore(iflag); 3024 apic_cpus[cpun].aci_curipl = 0; 3025 i = apic_min_device_irq; 3026 for (; i <= apic_max_device_irq; i++) { 3027 /* 3028 * If there are bound interrupts on this cpu, then 3029 * rebind them to other processors. 3030 */ 3031 if ((irq_ptr = apic_irq_table[i]) != NULL) { 3032 ASSERT((irq_ptr->airq_temp_cpu == IRQ_UNBOUND) || 3033 (irq_ptr->airq_temp_cpu == IRQ_UNINIT) || 3034 ((irq_ptr->airq_temp_cpu & ~IRQ_USER_BOUND) < 3035 apic_nproc)); 3036 3037 if (irq_ptr->airq_temp_cpu == (cpun | IRQ_USER_BOUND)) { 3038 hardbound = 1; 3039 continue; 3040 } 3041 3042 if (irq_ptr->airq_temp_cpu == cpun) { 3043 do { 3044 apic_next_bind_cpu += 2; 3045 bind_cpu = apic_next_bind_cpu / 2; 3046 if (bind_cpu >= apic_nproc) { 3047 apic_next_bind_cpu = 1; 3048 bind_cpu = 0; 3049 3050 } 3051 } while (apic_rebind_all(irq_ptr, bind_cpu, 1)); 3052 } 3053 } 3054 } 3055 if (hardbound) { 3056 cmn_err(CE_WARN, "Could not disable interrupts on %d" 3057 "due to user bound interrupts", cpun); 3058 return (PSM_FAILURE); 3059 } 3060 else 3061 return (PSM_SUCCESS); 3062 } 3063 3064 static void 3065 apic_enable_intr(processorid_t cpun) 3066 { 3067 int i, iflag; 3068 apic_irq_t *irq_ptr; 3069 3070 iflag = intr_clear(); 3071 lock_set(&apic_ioapic_lock); 3072 apic_cpus[cpun].aci_status |= APIC_CPU_INTR_ENABLE; 3073 lock_clear(&apic_ioapic_lock); 3074 intr_restore(iflag); 3075 3076 i = apic_min_device_irq; 3077 for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { 3078 if ((irq_ptr = apic_irq_table[i]) != NULL) { 3079 if ((irq_ptr->airq_cpu & ~IRQ_USER_BOUND) == cpun) { 3080 (void) apic_rebind_all(irq_ptr, 3081 irq_ptr->airq_cpu, 1); 3082 } 3083 } 3084 } 3085 } 3086 3087 /* 3088 * apic_introp_xlate() replaces apic_translate_irq() and is 3089 * called only from apic_intr_ops(). With the new ADII framework, 3090 * the priority can no longer be retrived through i_ddi_get_intrspec(). 3091 * It has to be passed in from the caller. 3092 */ 3093 int 3094 apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type) 3095 { 3096 char dev_type[16]; 3097 int dev_len, pci_irq, newirq, bustype, devid, busid, i; 3098 int irqno = ispec->intrspec_vec; 3099 ddi_acc_handle_t cfg_handle; 3100 uchar_t ipin; 3101 struct apic_io_intr *intrp; 3102 iflag_t intr_flag; 3103 APIC_HEADER *hp; 3104 MADT_INTERRUPT_OVERRIDE *isop; 3105 apic_irq_t *airqp; 3106 int is_pciex = 0; 3107 int is_pci = 0; 3108 3109 DDI_INTR_IMPLDBG((CE_CONT, "apic_introp_xlate: dip=0x%p name=%s " 3110 "type=%d irqno=0x%x\n", (void *)dip, ddi_get_name(dip), type, 3111 irqno)); 3112 3113 dev_len = sizeof (dev_type); 3114 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(dip), 3115 DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, 3116 &dev_len) == DDI_PROP_SUCCESS) { 3117 is_pci = (strcmp(dev_type, "pci") == 0); 3118 is_pciex = (strcmp(dev_type, "pciex") == 0); 3119 } 3120 3121 if (DDI_INTR_IS_MSI_OR_MSIX(type)) { 3122 if ((airqp = apic_find_irq(dip, ispec, type)) != NULL) { 3123 airqp->airq_iflag.bustype = 3124 is_pciex ? BUS_PCIE : BUS_PCI; 3125 return (apic_vector_to_irq[airqp->airq_vector]); 3126 } 3127 return (apic_setup_irq_table(dip, irqno, NULL, ispec, 3128 NULL, type)); 3129 } 3130 3131 bustype = 0; 3132 3133 /* check if we have already translated this irq */ 3134 mutex_enter(&airq_mutex); 3135 newirq = apic_min_device_irq; 3136 for (; newirq <= apic_max_device_irq; newirq++) { 3137 airqp = apic_irq_table[newirq]; 3138 while (airqp) { 3139 if ((airqp->airq_dip == dip) && 3140 (airqp->airq_origirq == irqno) && 3141 (airqp->airq_mps_intr_index != FREE_INDEX)) { 3142 3143 mutex_exit(&airq_mutex); 3144 return (VIRTIRQ(newirq, airqp->airq_share_id)); 3145 } 3146 airqp = airqp->airq_next; 3147 } 3148 } 3149 mutex_exit(&airq_mutex); 3150 3151 if (apic_defconf) 3152 goto defconf; 3153 3154 if ((dip == NULL) || (!apic_irq_translate && !apic_enable_acpi)) 3155 goto nonpci; 3156 3157 if (is_pci || is_pciex) { 3158 /* pci device */ 3159 if (acpica_get_bdf(dip, &busid, &devid, NULL) != 0) 3160 goto nonpci; 3161 if (busid == 0 && apic_pci_bus_total == 1) 3162 busid = (int)apic_single_pci_busid; 3163 3164 if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS) 3165 goto nonpci; 3166 ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA; 3167 pci_config_teardown(&cfg_handle); 3168 if (apic_enable_acpi && !apic_use_acpi_madt_only) { 3169 if (apic_acpi_translate_pci_irq(dip, busid, devid, 3170 ipin, &pci_irq, &intr_flag) != ACPI_PSM_SUCCESS) 3171 goto nonpci; 3172 3173 intr_flag.bustype = is_pciex ? BUS_PCIE : BUS_PCI; 3174 if ((newirq = apic_setup_irq_table(dip, pci_irq, NULL, 3175 ispec, &intr_flag, type)) == -1) 3176 goto nonpci; 3177 return (newirq); 3178 } else { 3179 pci_irq = ((devid & 0x1f) << 2) | (ipin & 0x3); 3180 if ((intrp = apic_find_io_intr_w_busid(pci_irq, busid)) 3181 == NULL) { 3182 if ((pci_irq = apic_handle_pci_pci_bridge(dip, 3183 devid, ipin, &intrp)) == -1) 3184 goto nonpci; 3185 } 3186 if ((newirq = apic_setup_irq_table(dip, pci_irq, intrp, 3187 ispec, NULL, type)) == -1) 3188 goto nonpci; 3189 return (newirq); 3190 } 3191 } else if (strcmp(dev_type, "isa") == 0) 3192 bustype = BUS_ISA; 3193 else if (strcmp(dev_type, "eisa") == 0) 3194 bustype = BUS_EISA; 3195 3196 nonpci: 3197 if (apic_enable_acpi && !apic_use_acpi_madt_only) { 3198 /* search iso entries first */ 3199 if (acpi_iso_cnt != 0) { 3200 hp = (APIC_HEADER *)acpi_isop; 3201 i = 0; 3202 while (i < acpi_iso_cnt) { 3203 if (hp->Type == APIC_XRUPT_OVERRIDE) { 3204 isop = (MADT_INTERRUPT_OVERRIDE *)hp; 3205 if (isop->Bus == 0 && 3206 isop->Source == irqno) { 3207 newirq = isop->Interrupt; 3208 intr_flag.intr_po = 3209 isop->Polarity; 3210 intr_flag.intr_el = 3211 isop->TriggerMode; 3212 intr_flag.bustype = BUS_ISA; 3213 3214 return (apic_setup_irq_table( 3215 dip, newirq, NULL, ispec, 3216 &intr_flag, type)); 3217 3218 } 3219 i++; 3220 } 3221 hp = (APIC_HEADER *)(((char *)hp) + 3222 hp->Length); 3223 } 3224 } 3225 intr_flag.intr_po = INTR_PO_ACTIVE_HIGH; 3226 intr_flag.intr_el = INTR_EL_EDGE; 3227 intr_flag.bustype = BUS_ISA; 3228 return (apic_setup_irq_table(dip, irqno, NULL, ispec, 3229 &intr_flag, type)); 3230 } else { 3231 if (bustype == 0) 3232 bustype = eisa_level_intr_mask ? BUS_EISA : BUS_ISA; 3233 for (i = 0; i < 2; i++) { 3234 if (((busid = apic_find_bus_id(bustype)) != -1) && 3235 ((intrp = apic_find_io_intr_w_busid(irqno, busid)) 3236 != NULL)) { 3237 if ((newirq = apic_setup_irq_table(dip, irqno, 3238 intrp, ispec, NULL, type)) != -1) { 3239 return (newirq); 3240 } 3241 goto defconf; 3242 } 3243 bustype = (bustype == BUS_EISA) ? BUS_ISA : BUS_EISA; 3244 } 3245 } 3246 3247 /* MPS default configuration */ 3248 defconf: 3249 newirq = apic_setup_irq_table(dip, irqno, NULL, ispec, NULL, type); 3250 if (newirq == -1) 3251 return (newirq); 3252 ASSERT(IRQINDEX(newirq) == irqno); 3253 ASSERT(apic_irq_table[irqno]); 3254 return (newirq); 3255 } 3256 3257 3258 3259 3260 3261 3262 /* 3263 * On machines with PCI-PCI bridges, a device behind a PCI-PCI bridge 3264 * needs special handling. We may need to chase up the device tree, 3265 * using the PCI-PCI Bridge specification's "rotating IPIN assumptions", 3266 * to find the IPIN at the root bus that relates to the IPIN on the 3267 * subsidiary bus (for ACPI or MP). We may, however, have an entry 3268 * in the MP table or the ACPI namespace for this device itself. 3269 * We handle both cases in the search below. 3270 */ 3271 /* this is the non-acpi version */ 3272 static int 3273 apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, int child_ipin, 3274 struct apic_io_intr **intrp) 3275 { 3276 dev_info_t *dipp, *dip; 3277 int pci_irq; 3278 ddi_acc_handle_t cfg_handle; 3279 int bridge_devno, bridge_bus; 3280 int ipin; 3281 3282 dip = idip; 3283 3284 /*CONSTCOND*/ 3285 while (1) { 3286 if ((dipp = ddi_get_parent(dip)) == (dev_info_t *)NULL) 3287 return (-1); 3288 if ((pci_config_setup(dipp, &cfg_handle) == DDI_SUCCESS) && 3289 (pci_config_get8(cfg_handle, PCI_CONF_BASCLASS) == 3290 PCI_CLASS_BRIDGE) && (pci_config_get8(cfg_handle, 3291 PCI_CONF_SUBCLASS) == PCI_BRIDGE_PCI)) { 3292 pci_config_teardown(&cfg_handle); 3293 if (acpica_get_bdf(dipp, &bridge_bus, &bridge_devno, 3294 NULL) != 0) 3295 return (-1); 3296 /* 3297 * This is the rotating scheme that Compaq is using 3298 * and documented in the pci to pci spec. Also, if 3299 * the pci to pci bridge is behind another pci to 3300 * pci bridge, then it need to keep transversing 3301 * up until an interrupt entry is found or reach 3302 * the top of the tree 3303 */ 3304 ipin = (child_devno + child_ipin) % PCI_INTD; 3305 if (bridge_bus == 0 && apic_pci_bus_total == 1) 3306 bridge_bus = (int)apic_single_pci_busid; 3307 pci_irq = ((bridge_devno & 0x1f) << 2) | 3308 (ipin & 0x3); 3309 if ((*intrp = apic_find_io_intr_w_busid(pci_irq, 3310 bridge_bus)) != NULL) { 3311 return (pci_irq); 3312 } 3313 dip = dipp; 3314 child_devno = bridge_devno; 3315 child_ipin = ipin; 3316 } else 3317 return (-1); 3318 } 3319 /*LINTED: function will not fall off the bottom */ 3320 } 3321 3322 3323 3324 3325 static uchar_t 3326 acpi_find_ioapic(int irq) 3327 { 3328 int i; 3329 3330 for (i = 0; i < apic_io_max; i++) { 3331 if (irq >= apic_io_vectbase[i] && irq <= apic_io_vectend[i]) 3332 return (i); 3333 } 3334 return (0xFF); /* shouldn't happen */ 3335 } 3336 3337 /* 3338 * See if two irqs are compatible for sharing a vector. 3339 * Currently we only support sharing of PCI devices. 3340 */ 3341 static int 3342 acpi_intr_compatible(iflag_t iflag1, iflag_t iflag2) 3343 { 3344 uint_t level1, po1; 3345 uint_t level2, po2; 3346 3347 /* Assume active high by default */ 3348 po1 = 0; 3349 po2 = 0; 3350 3351 if (iflag1.bustype != iflag2.bustype || iflag1.bustype != BUS_PCI) 3352 return (0); 3353 3354 if (iflag1.intr_el == INTR_EL_CONFORM) 3355 level1 = AV_LEVEL; 3356 else 3357 level1 = (iflag1.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0; 3358 3359 if (level1 && ((iflag1.intr_po == INTR_PO_ACTIVE_LOW) || 3360 (iflag1.intr_po == INTR_PO_CONFORM))) 3361 po1 = AV_ACTIVE_LOW; 3362 3363 if (iflag2.intr_el == INTR_EL_CONFORM) 3364 level2 = AV_LEVEL; 3365 else 3366 level2 = (iflag2.intr_el == INTR_EL_LEVEL) ? AV_LEVEL : 0; 3367 3368 if (level2 && ((iflag2.intr_po == INTR_PO_ACTIVE_LOW) || 3369 (iflag2.intr_po == INTR_PO_CONFORM))) 3370 po2 = AV_ACTIVE_LOW; 3371 3372 if ((level1 == level2) && (po1 == po2)) 3373 return (1); 3374 3375 return (0); 3376 } 3377 3378 /* 3379 * Attempt to share vector with someone else 3380 */ 3381 static int 3382 apic_share_vector(int irqno, iflag_t *intr_flagp, short intr_index, int ipl, 3383 uchar_t ioapicindex, uchar_t ipin, apic_irq_t **irqptrp) 3384 { 3385 #ifdef DEBUG 3386 apic_irq_t *tmpirqp = NULL; 3387 #endif /* DEBUG */ 3388 apic_irq_t *irqptr, dummyirq; 3389 int newirq, chosen_irq = -1, share = 127; 3390 int lowest, highest, i; 3391 uchar_t share_id; 3392 3393 DDI_INTR_IMPLDBG((CE_CONT, "apic_share_vector: irqno=0x%x " 3394 "intr_index=0x%x ipl=0x%x\n", irqno, intr_index, ipl)); 3395 3396 highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; 3397 lowest = apic_ipltopri[ipl-1] + APIC_VECTOR_PER_IPL; 3398 3399 if (highest < lowest) /* Both ipl and ipl-1 map to same pri */ 3400 lowest -= APIC_VECTOR_PER_IPL; 3401 dummyirq.airq_mps_intr_index = intr_index; 3402 dummyirq.airq_ioapicindex = ioapicindex; 3403 dummyirq.airq_intin_no = ipin; 3404 if (intr_flagp) 3405 dummyirq.airq_iflag = *intr_flagp; 3406 apic_record_rdt_entry(&dummyirq, irqno); 3407 for (i = lowest; i <= highest; i++) { 3408 newirq = apic_vector_to_irq[i]; 3409 if (newirq == APIC_RESV_IRQ) 3410 continue; 3411 irqptr = apic_irq_table[newirq]; 3412 3413 if ((dummyirq.airq_rdt_entry & 0xFF00) != 3414 (irqptr->airq_rdt_entry & 0xFF00)) 3415 /* not compatible */ 3416 continue; 3417 3418 if (irqptr->airq_share < share) { 3419 share = irqptr->airq_share; 3420 chosen_irq = newirq; 3421 } 3422 } 3423 if (chosen_irq != -1) { 3424 /* 3425 * Assign a share id which is free or which is larger 3426 * than the largest one. 3427 */ 3428 share_id = 1; 3429 mutex_enter(&airq_mutex); 3430 irqptr = apic_irq_table[chosen_irq]; 3431 while (irqptr) { 3432 if (irqptr->airq_mps_intr_index == FREE_INDEX) { 3433 share_id = irqptr->airq_share_id; 3434 break; 3435 } 3436 if (share_id <= irqptr->airq_share_id) 3437 share_id = irqptr->airq_share_id + 1; 3438 #ifdef DEBUG 3439 tmpirqp = irqptr; 3440 #endif /* DEBUG */ 3441 irqptr = irqptr->airq_next; 3442 } 3443 if (!irqptr) { 3444 irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); 3445 irqptr->airq_temp_cpu = IRQ_UNINIT; 3446 irqptr->airq_next = 3447 apic_irq_table[chosen_irq]->airq_next; 3448 apic_irq_table[chosen_irq]->airq_next = irqptr; 3449 #ifdef DEBUG 3450 tmpirqp = apic_irq_table[chosen_irq]; 3451 #endif /* DEBUG */ 3452 } 3453 irqptr->airq_mps_intr_index = intr_index; 3454 irqptr->airq_ioapicindex = ioapicindex; 3455 irqptr->airq_intin_no = ipin; 3456 if (intr_flagp) 3457 irqptr->airq_iflag = *intr_flagp; 3458 irqptr->airq_vector = apic_irq_table[chosen_irq]->airq_vector; 3459 irqptr->airq_share_id = share_id; 3460 apic_record_rdt_entry(irqptr, irqno); 3461 *irqptrp = irqptr; 3462 #ifdef DEBUG 3463 /* shuffle the pointers to test apic_delspl path */ 3464 if (tmpirqp) { 3465 tmpirqp->airq_next = irqptr->airq_next; 3466 irqptr->airq_next = apic_irq_table[chosen_irq]; 3467 apic_irq_table[chosen_irq] = irqptr; 3468 } 3469 #endif /* DEBUG */ 3470 mutex_exit(&airq_mutex); 3471 return (VIRTIRQ(chosen_irq, share_id)); 3472 } 3473 return (-1); 3474 } 3475 3476 /* 3477 * 3478 */ 3479 static int 3480 apic_setup_irq_table(dev_info_t *dip, int irqno, struct apic_io_intr *intrp, 3481 struct intrspec *ispec, iflag_t *intr_flagp, int type) 3482 { 3483 int origirq = ispec->intrspec_vec; 3484 uchar_t ipl = ispec->intrspec_pri; 3485 int newirq, intr_index; 3486 uchar_t ipin, ioapic, ioapicindex, vector; 3487 apic_irq_t *irqptr; 3488 major_t major; 3489 dev_info_t *sdip; 3490 3491 DDI_INTR_IMPLDBG((CE_CONT, "apic_setup_irq_table: dip=0x%p type=%d " 3492 "irqno=0x%x origirq=0x%x\n", (void *)dip, type, irqno, origirq)); 3493 3494 ASSERT(ispec != NULL); 3495 3496 major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; 3497 3498 if (DDI_INTR_IS_MSI_OR_MSIX(type)) { 3499 /* MSI/X doesn't need to setup ioapic stuffs */ 3500 ioapicindex = 0xff; 3501 ioapic = 0xff; 3502 ipin = (uchar_t)0xff; 3503 intr_index = (type == DDI_INTR_TYPE_MSI) ? MSI_INDEX : 3504 MSIX_INDEX; 3505 mutex_enter(&airq_mutex); 3506 if ((irqno = apic_allocate_irq(apic_first_avail_irq)) == -1) { 3507 mutex_exit(&airq_mutex); 3508 /* need an irq for MSI/X to index into autovect[] */ 3509 cmn_err(CE_WARN, "No interrupt irq: %s instance %d", 3510 ddi_get_name(dip), ddi_get_instance(dip)); 3511 return (-1); 3512 } 3513 mutex_exit(&airq_mutex); 3514 3515 } else if (intrp != NULL) { 3516 intr_index = (int)(intrp - apic_io_intrp); 3517 ioapic = intrp->intr_destid; 3518 ipin = intrp->intr_destintin; 3519 /* Find ioapicindex. If destid was ALL, we will exit with 0. */ 3520 for (ioapicindex = apic_io_max - 1; ioapicindex; ioapicindex--) 3521 if (apic_io_id[ioapicindex] == ioapic) 3522 break; 3523 ASSERT((ioapic == apic_io_id[ioapicindex]) || 3524 (ioapic == INTR_ALL_APIC)); 3525 3526 /* check whether this intin# has been used by another irqno */ 3527 if ((newirq = apic_find_intin(ioapicindex, ipin)) != -1) { 3528 return (newirq); 3529 } 3530 3531 } else if (intr_flagp != NULL) { 3532 /* ACPI case */ 3533 intr_index = ACPI_INDEX; 3534 ioapicindex = acpi_find_ioapic(irqno); 3535 ASSERT(ioapicindex != 0xFF); 3536 ioapic = apic_io_id[ioapicindex]; 3537 ipin = irqno - apic_io_vectbase[ioapicindex]; 3538 if (apic_irq_table[irqno] && 3539 apic_irq_table[irqno]->airq_mps_intr_index == ACPI_INDEX) { 3540 ASSERT(apic_irq_table[irqno]->airq_intin_no == ipin && 3541 apic_irq_table[irqno]->airq_ioapicindex == 3542 ioapicindex); 3543 return (irqno); 3544 } 3545 3546 } else { 3547 /* default configuration */ 3548 ioapicindex = 0; 3549 ioapic = apic_io_id[ioapicindex]; 3550 ipin = (uchar_t)irqno; 3551 intr_index = DEFAULT_INDEX; 3552 } 3553 3554 if (ispec == NULL) { 3555 APIC_VERBOSE_IOAPIC((CE_WARN, "No intrspec for irqno = %x\n", 3556 irqno)); 3557 } else if ((vector = apic_allocate_vector(ipl, irqno, 0)) == 0) { 3558 if ((newirq = apic_share_vector(irqno, intr_flagp, intr_index, 3559 ipl, ioapicindex, ipin, &irqptr)) != -1) { 3560 irqptr->airq_ipl = ipl; 3561 irqptr->airq_origirq = (uchar_t)origirq; 3562 irqptr->airq_dip = dip; 3563 irqptr->airq_major = major; 3564 sdip = apic_irq_table[IRQINDEX(newirq)]->airq_dip; 3565 /* This is OK to do really */ 3566 if (sdip == NULL) { 3567 cmn_err(CE_WARN, "Sharing vectors: %s" 3568 " instance %d and SCI", 3569 ddi_get_name(dip), ddi_get_instance(dip)); 3570 } else { 3571 cmn_err(CE_WARN, "Sharing vectors: %s" 3572 " instance %d and %s instance %d", 3573 ddi_get_name(sdip), ddi_get_instance(sdip), 3574 ddi_get_name(dip), ddi_get_instance(dip)); 3575 } 3576 return (newirq); 3577 } 3578 /* try high priority allocation now that share has failed */ 3579 if ((vector = apic_allocate_vector(ipl, irqno, 1)) == 0) { 3580 cmn_err(CE_WARN, "No interrupt vector: %s instance %d", 3581 ddi_get_name(dip), ddi_get_instance(dip)); 3582 return (-1); 3583 } 3584 } 3585 3586 mutex_enter(&airq_mutex); 3587 if (apic_irq_table[irqno] == NULL) { 3588 irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); 3589 irqptr->airq_temp_cpu = IRQ_UNINIT; 3590 apic_irq_table[irqno] = irqptr; 3591 } else { 3592 irqptr = apic_irq_table[irqno]; 3593 if (irqptr->airq_mps_intr_index != FREE_INDEX) { 3594 /* 3595 * The slot is used by another irqno, so allocate 3596 * a free irqno for this interrupt 3597 */ 3598 newirq = apic_allocate_irq(apic_first_avail_irq); 3599 if (newirq == -1) { 3600 mutex_exit(&airq_mutex); 3601 return (-1); 3602 } 3603 irqno = newirq; 3604 irqptr = apic_irq_table[irqno]; 3605 if (irqptr == NULL) { 3606 irqptr = kmem_zalloc(sizeof (apic_irq_t), 3607 KM_SLEEP); 3608 irqptr->airq_temp_cpu = IRQ_UNINIT; 3609 apic_irq_table[irqno] = irqptr; 3610 } 3611 apic_modify_vector(vector, newirq); 3612 } 3613 } 3614 apic_max_device_irq = max(irqno, apic_max_device_irq); 3615 apic_min_device_irq = min(irqno, apic_min_device_irq); 3616 mutex_exit(&airq_mutex); 3617 irqptr->airq_ioapicindex = ioapicindex; 3618 irqptr->airq_intin_no = ipin; 3619 irqptr->airq_ipl = ipl; 3620 irqptr->airq_vector = vector; 3621 irqptr->airq_origirq = (uchar_t)origirq; 3622 irqptr->airq_share_id = 0; 3623 irqptr->airq_mps_intr_index = (short)intr_index; 3624 irqptr->airq_dip = dip; 3625 irqptr->airq_major = major; 3626 irqptr->airq_cpu = apic_bind_intr(dip, irqno, ioapic, ipin); 3627 if (intr_flagp) 3628 irqptr->airq_iflag = *intr_flagp; 3629 3630 if (!DDI_INTR_IS_MSI_OR_MSIX(type)) { 3631 /* setup I/O APIC entry for non-MSI/X interrupts */ 3632 apic_record_rdt_entry(irqptr, irqno); 3633 } 3634 return (irqno); 3635 } 3636 3637 /* 3638 * return the cpu to which this intr should be bound. 3639 * Check properties or any other mechanism to see if user wants it 3640 * bound to a specific CPU. If so, return the cpu id with high bit set. 3641 * If not, use the policy to choose a cpu and return the id. 3642 */ 3643 uchar_t 3644 apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, uchar_t intin) 3645 { 3646 int instance, instno, prop_len, bind_cpu, count; 3647 uint_t i, rc; 3648 uchar_t cpu; 3649 major_t major; 3650 char *name, *drv_name, *prop_val, *cptr; 3651 char prop_name[32]; 3652 3653 3654 if (apic_intr_policy == INTR_LOWEST_PRIORITY) 3655 return (IRQ_UNBOUND); 3656 3657 drv_name = NULL; 3658 rc = DDI_PROP_NOT_FOUND; 3659 major = (major_t)-1; 3660 if (dip != NULL) { 3661 name = ddi_get_name(dip); 3662 major = ddi_name_to_major(name); 3663 drv_name = ddi_major_to_name(major); 3664 instance = ddi_get_instance(dip); 3665 if (apic_intr_policy == INTR_ROUND_ROBIN_WITH_AFFINITY) { 3666 i = apic_min_device_irq; 3667 for (; i <= apic_max_device_irq; i++) { 3668 3669 if ((i == irq) || (apic_irq_table[i] == NULL) || 3670 (apic_irq_table[i]->airq_mps_intr_index 3671 == FREE_INDEX)) 3672 continue; 3673 3674 if ((apic_irq_table[i]->airq_major == major) && 3675 (!(apic_irq_table[i]->airq_cpu & 3676 IRQ_USER_BOUND))) { 3677 3678 cpu = apic_irq_table[i]->airq_cpu; 3679 3680 cmn_err(CE_CONT, 3681 "!pcplusmp: %s (%s) instance #%d " 3682 "vector 0x%x ioapic 0x%x " 3683 "intin 0x%x is bound to cpu %d\n", 3684 name, drv_name, instance, irq, 3685 ioapicid, intin, cpu); 3686 return (cpu); 3687 } 3688 } 3689 } 3690 /* 3691 * search for "drvname"_intpt_bind_cpus property first, the 3692 * syntax of the property should be "a[,b,c,...]" where 3693 * instance 0 binds to cpu a, instance 1 binds to cpu b, 3694 * instance 3 binds to cpu c... 3695 * ddi_getlongprop() will search /option first, then / 3696 * if "drvname"_intpt_bind_cpus doesn't exist, then find 3697 * intpt_bind_cpus property. The syntax is the same, and 3698 * it applies to all the devices if its "drvname" specific 3699 * property doesn't exist 3700 */ 3701 (void) strcpy(prop_name, drv_name); 3702 (void) strcat(prop_name, "_intpt_bind_cpus"); 3703 rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, prop_name, 3704 (caddr_t)&prop_val, &prop_len); 3705 if (rc != DDI_PROP_SUCCESS) { 3706 rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, 3707 "intpt_bind_cpus", (caddr_t)&prop_val, &prop_len); 3708 } 3709 } 3710 if (rc == DDI_PROP_SUCCESS) { 3711 for (i = count = 0; i < (prop_len - 1); i++) 3712 if (prop_val[i] == ',') 3713 count++; 3714 if (prop_val[i-1] != ',') 3715 count++; 3716 /* 3717 * if somehow the binding instances defined in the 3718 * property are not enough for this instno., then 3719 * reuse the pattern for the next instance until 3720 * it reaches the requested instno 3721 */ 3722 instno = instance % count; 3723 i = 0; 3724 cptr = prop_val; 3725 while (i < instno) 3726 if (*cptr++ == ',') 3727 i++; 3728 bind_cpu = stoi(&cptr); 3729 kmem_free(prop_val, prop_len); 3730 /* if specific cpu is bogus, then default to cpu 0 */ 3731 if (bind_cpu >= apic_nproc) { 3732 cmn_err(CE_WARN, "pcplusmp: %s=%s: CPU %d not present", 3733 prop_name, prop_val, bind_cpu); 3734 bind_cpu = 0; 3735 } else { 3736 /* indicate that we are bound at user request */ 3737 bind_cpu |= IRQ_USER_BOUND; 3738 } 3739 /* 3740 * no need to check apic_cpus[].aci_status, if specific cpu is 3741 * not up, then post_cpu_start will handle it. 3742 */ 3743 } else { 3744 bind_cpu = apic_next_bind_cpu++; 3745 if (bind_cpu >= apic_nproc) { 3746 apic_next_bind_cpu = 1; 3747 bind_cpu = 0; 3748 } 3749 } 3750 if (drv_name != NULL) 3751 cmn_err(CE_CONT, "!pcplusmp: %s (%s) instance %d " 3752 "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", 3753 name, drv_name, instance, 3754 irq, ioapicid, intin, bind_cpu & ~IRQ_USER_BOUND); 3755 else 3756 cmn_err(CE_CONT, "!pcplusmp: " 3757 "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", 3758 irq, ioapicid, intin, bind_cpu & ~IRQ_USER_BOUND); 3759 3760 return ((uchar_t)bind_cpu); 3761 } 3762 3763 static struct apic_io_intr * 3764 apic_find_io_intr_w_busid(int irqno, int busid) 3765 { 3766 struct apic_io_intr *intrp; 3767 3768 /* 3769 * It can have more than 1 entry with same source bus IRQ, 3770 * but unique with the source bus id 3771 */ 3772 intrp = apic_io_intrp; 3773 if (intrp != NULL) { 3774 while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { 3775 if (intrp->intr_irq == irqno && 3776 intrp->intr_busid == busid && 3777 intrp->intr_type == IO_INTR_INT) 3778 return (intrp); 3779 intrp++; 3780 } 3781 } 3782 APIC_VERBOSE_IOAPIC((CE_NOTE, "Did not find io intr for irqno:" 3783 "busid %x:%x\n", irqno, busid)); 3784 return ((struct apic_io_intr *)NULL); 3785 } 3786 3787 3788 struct mps_bus_info { 3789 char *bus_name; 3790 int bus_id; 3791 } bus_info_array[] = { 3792 "ISA ", BUS_ISA, 3793 "PCI ", BUS_PCI, 3794 "EISA ", BUS_EISA, 3795 "XPRESS", BUS_XPRESS, 3796 "PCMCIA", BUS_PCMCIA, 3797 "VL ", BUS_VL, 3798 "CBUS ", BUS_CBUS, 3799 "CBUSII", BUS_CBUSII, 3800 "FUTURE", BUS_FUTURE, 3801 "INTERN", BUS_INTERN, 3802 "MBI ", BUS_MBI, 3803 "MBII ", BUS_MBII, 3804 "MPI ", BUS_MPI, 3805 "MPSA ", BUS_MPSA, 3806 "NUBUS ", BUS_NUBUS, 3807 "TC ", BUS_TC, 3808 "VME ", BUS_VME, 3809 "PCI-E ", BUS_PCIE 3810 }; 3811 3812 static int 3813 apic_find_bus_type(char *bus) 3814 { 3815 int i = 0; 3816 3817 for (; i < sizeof (bus_info_array)/sizeof (struct mps_bus_info); i++) 3818 if (strncmp(bus, bus_info_array[i].bus_name, 3819 strlen(bus_info_array[i].bus_name)) == 0) 3820 return (bus_info_array[i].bus_id); 3821 APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus type for bus %s", bus)); 3822 return (0); 3823 } 3824 3825 static int 3826 apic_find_bus(int busid) 3827 { 3828 struct apic_bus *busp; 3829 3830 busp = apic_busp; 3831 while (busp->bus_entry == APIC_BUS_ENTRY) { 3832 if (busp->bus_id == busid) 3833 return (apic_find_bus_type((char *)&busp->bus_str1)); 3834 busp++; 3835 } 3836 APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus for bus id %x", busid)); 3837 return (0); 3838 } 3839 3840 static int 3841 apic_find_bus_id(int bustype) 3842 { 3843 struct apic_bus *busp; 3844 3845 busp = apic_busp; 3846 while (busp->bus_entry == APIC_BUS_ENTRY) { 3847 if (apic_find_bus_type((char *)&busp->bus_str1) == bustype) 3848 return (busp->bus_id); 3849 busp++; 3850 } 3851 APIC_VERBOSE_IOAPIC((CE_WARN, "Did not find bus id for bustype %x", 3852 bustype)); 3853 return (-1); 3854 } 3855 3856 /* 3857 * Check if a particular irq need to be reserved for any io_intr 3858 */ 3859 static struct apic_io_intr * 3860 apic_find_io_intr(int irqno) 3861 { 3862 struct apic_io_intr *intrp; 3863 3864 intrp = apic_io_intrp; 3865 if (intrp != NULL) { 3866 while (intrp->intr_entry == APIC_IO_INTR_ENTRY) { 3867 if (intrp->intr_irq == irqno && 3868 intrp->intr_type == IO_INTR_INT) 3869 return (intrp); 3870 intrp++; 3871 } 3872 } 3873 return ((struct apic_io_intr *)NULL); 3874 } 3875 3876 /* 3877 * Check if the given ioapicindex intin combination has already been assigned 3878 * an irq. If so return irqno. Else -1 3879 */ 3880 static int 3881 apic_find_intin(uchar_t ioapic, uchar_t intin) 3882 { 3883 apic_irq_t *irqptr; 3884 int i; 3885 3886 /* find ioapic and intin in the apic_irq_table[] and return the index */ 3887 for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { 3888 irqptr = apic_irq_table[i]; 3889 while (irqptr) { 3890 if ((irqptr->airq_mps_intr_index >= 0) && 3891 (irqptr->airq_intin_no == intin) && 3892 (irqptr->airq_ioapicindex == ioapic)) { 3893 APIC_VERBOSE_IOAPIC((CE_NOTE, "!Found irq " 3894 "entry for ioapic:intin %x:%x " 3895 "shared interrupts ?", ioapic, intin)); 3896 return (i); 3897 } 3898 irqptr = irqptr->airq_next; 3899 } 3900 } 3901 return (-1); 3902 } 3903 3904 int 3905 apic_allocate_irq(int irq) 3906 { 3907 int freeirq, i; 3908 3909 if ((freeirq = apic_find_free_irq(irq, (APIC_RESV_IRQ - 1))) == -1) 3910 if ((freeirq = apic_find_free_irq(APIC_FIRST_FREE_IRQ, 3911 (irq - 1))) == -1) { 3912 /* 3913 * if BIOS really defines every single irq in the mps 3914 * table, then don't worry about conflicting with 3915 * them, just use any free slot in apic_irq_table 3916 */ 3917 for (i = APIC_FIRST_FREE_IRQ; i < APIC_RESV_IRQ; i++) { 3918 if ((apic_irq_table[i] == NULL) || 3919 apic_irq_table[i]->airq_mps_intr_index == 3920 FREE_INDEX) { 3921 freeirq = i; 3922 break; 3923 } 3924 } 3925 if (freeirq == -1) { 3926 /* This shouldn't happen, but just in case */ 3927 cmn_err(CE_WARN, "pcplusmp: NO available IRQ"); 3928 return (-1); 3929 } 3930 } 3931 if (apic_irq_table[freeirq] == NULL) { 3932 apic_irq_table[freeirq] = 3933 kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); 3934 if (apic_irq_table[freeirq] == NULL) { 3935 cmn_err(CE_WARN, "pcplusmp: NO memory to allocate IRQ"); 3936 return (-1); 3937 } 3938 apic_irq_table[freeirq]->airq_mps_intr_index = FREE_INDEX; 3939 } 3940 return (freeirq); 3941 } 3942 3943 static int 3944 apic_find_free_irq(int start, int end) 3945 { 3946 int i; 3947 3948 for (i = start; i <= end; i++) 3949 /* Check if any I/O entry needs this IRQ */ 3950 if (apic_find_io_intr(i) == NULL) { 3951 /* Then see if it is free */ 3952 if ((apic_irq_table[i] == NULL) || 3953 (apic_irq_table[i]->airq_mps_intr_index == 3954 FREE_INDEX)) { 3955 return (i); 3956 } 3957 } 3958 return (-1); 3959 } 3960 3961 /* 3962 * Allocate a free vector for irq at ipl. Takes care of merging of multiple 3963 * IPLs into a single APIC level as well as stretching some IPLs onto multiple 3964 * levels. APIC_HI_PRI_VECTS interrupts are reserved for high priority 3965 * requests and allocated only when pri is set. 3966 */ 3967 static uchar_t 3968 apic_allocate_vector(int ipl, int irq, int pri) 3969 { 3970 int lowest, highest, i; 3971 3972 highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; 3973 lowest = apic_ipltopri[ipl - 1] + APIC_VECTOR_PER_IPL; 3974 3975 if (highest < lowest) /* Both ipl and ipl - 1 map to same pri */ 3976 lowest -= APIC_VECTOR_PER_IPL; 3977 3978 #ifdef DEBUG 3979 if (apic_restrict_vector) /* for testing shared interrupt logic */ 3980 highest = lowest + apic_restrict_vector + APIC_HI_PRI_VECTS; 3981 #endif /* DEBUG */ 3982 if (pri == 0) 3983 highest -= APIC_HI_PRI_VECTS; 3984 3985 for (i = lowest; i < highest; i++) { 3986 if (APIC_CHECK_RESERVE_VECTORS(i)) 3987 continue; 3988 if (apic_vector_to_irq[i] == APIC_RESV_IRQ) { 3989 apic_vector_to_irq[i] = (uchar_t)irq; 3990 return (i); 3991 } 3992 } 3993 3994 return (0); 3995 } 3996 3997 static void 3998 apic_modify_vector(uchar_t vector, int irq) 3999 { 4000 apic_vector_to_irq[vector] = (uchar_t)irq; 4001 } 4002 4003 /* 4004 * Mark vector as being in the process of being deleted. Interrupts 4005 * may still come in on some CPU. The moment an interrupt comes with 4006 * the new vector, we know we can free the old one. Called only from 4007 * addspl and delspl with interrupts disabled. Because an interrupt 4008 * can be shared, but no interrupt from either device may come in, 4009 * we also use a timeout mechanism, which we arbitrarily set to 4010 * apic_revector_timeout microseconds. 4011 */ 4012 static void 4013 apic_mark_vector(uchar_t oldvector, uchar_t newvector) 4014 { 4015 int iflag = intr_clear(); 4016 lock_set(&apic_revector_lock); 4017 if (!apic_oldvec_to_newvec) { 4018 apic_oldvec_to_newvec = 4019 kmem_zalloc(sizeof (newvector) * APIC_MAX_VECTOR * 2, 4020 KM_NOSLEEP); 4021 4022 if (!apic_oldvec_to_newvec) { 4023 /* 4024 * This failure is not catastrophic. 4025 * But, the oldvec will never be freed. 4026 */ 4027 apic_error |= APIC_ERR_MARK_VECTOR_FAIL; 4028 lock_clear(&apic_revector_lock); 4029 intr_restore(iflag); 4030 return; 4031 } 4032 apic_newvec_to_oldvec = &apic_oldvec_to_newvec[APIC_MAX_VECTOR]; 4033 } 4034 4035 /* See if we already did this for drivers which do double addintrs */ 4036 if (apic_oldvec_to_newvec[oldvector] != newvector) { 4037 apic_oldvec_to_newvec[oldvector] = newvector; 4038 apic_newvec_to_oldvec[newvector] = oldvector; 4039 apic_revector_pending++; 4040 } 4041 lock_clear(&apic_revector_lock); 4042 intr_restore(iflag); 4043 (void) timeout(apic_xlate_vector_free_timeout_handler, 4044 (void *)(uintptr_t)oldvector, drv_usectohz(apic_revector_timeout)); 4045 } 4046 4047 /* 4048 * xlate_vector is called from intr_enter if revector_pending is set. 4049 * It will xlate it if needed and mark the old vector as free. 4050 */ 4051 static uchar_t 4052 apic_xlate_vector(uchar_t vector) 4053 { 4054 uchar_t newvector, oldvector = 0; 4055 4056 lock_set(&apic_revector_lock); 4057 /* Do we really need to do this ? */ 4058 if (!apic_revector_pending) { 4059 lock_clear(&apic_revector_lock); 4060 return (vector); 4061 } 4062 if ((newvector = apic_oldvec_to_newvec[vector]) != 0) 4063 oldvector = vector; 4064 else { 4065 /* 4066 * The incoming vector is new . See if a stale entry is 4067 * remaining 4068 */ 4069 if ((oldvector = apic_newvec_to_oldvec[vector]) != 0) 4070 newvector = vector; 4071 } 4072 4073 if (oldvector) { 4074 apic_revector_pending--; 4075 apic_oldvec_to_newvec[oldvector] = 0; 4076 apic_newvec_to_oldvec[newvector] = 0; 4077 apic_free_vector(oldvector); 4078 lock_clear(&apic_revector_lock); 4079 /* There could have been more than one reprogramming! */ 4080 return (apic_xlate_vector(newvector)); 4081 } 4082 lock_clear(&apic_revector_lock); 4083 return (vector); 4084 } 4085 4086 void 4087 apic_xlate_vector_free_timeout_handler(void *arg) 4088 { 4089 int iflag; 4090 uchar_t oldvector, newvector; 4091 4092 oldvector = (uchar_t)(uintptr_t)arg; 4093 iflag = intr_clear(); 4094 lock_set(&apic_revector_lock); 4095 if ((newvector = apic_oldvec_to_newvec[oldvector]) != 0) { 4096 apic_free_vector(oldvector); 4097 apic_oldvec_to_newvec[oldvector] = 0; 4098 apic_newvec_to_oldvec[newvector] = 0; 4099 apic_revector_pending--; 4100 } 4101 4102 lock_clear(&apic_revector_lock); 4103 intr_restore(iflag); 4104 } 4105 4106 4107 /* Mark vector as not being used by any irq */ 4108 static void 4109 apic_free_vector(uchar_t vector) 4110 { 4111 apic_vector_to_irq[vector] = APIC_RESV_IRQ; 4112 } 4113 4114 /* 4115 * compute the polarity, trigger mode and vector for programming into 4116 * the I/O apic and record in airq_rdt_entry. 4117 */ 4118 static void 4119 apic_record_rdt_entry(apic_irq_t *irqptr, int irq) 4120 { 4121 int ioapicindex, bus_type, vector; 4122 short intr_index; 4123 uint_t level, po, io_po; 4124 struct apic_io_intr *iointrp; 4125 4126 intr_index = irqptr->airq_mps_intr_index; 4127 DDI_INTR_IMPLDBG((CE_CONT, "apic_record_rdt_entry: intr_index=%d " 4128 "irq = 0x%x dip = 0x%p vector = 0x%x\n", intr_index, irq, 4129 (void *)irqptr->airq_dip, irqptr->airq_vector)); 4130 4131 if (intr_index == RESERVE_INDEX) { 4132 apic_error |= APIC_ERR_INVALID_INDEX; 4133 return; 4134 } else if (APIC_IS_MSI_OR_MSIX_INDEX(intr_index)) { 4135 return; 4136 } 4137 4138 vector = irqptr->airq_vector; 4139 ioapicindex = irqptr->airq_ioapicindex; 4140 /* Assume edge triggered by default */ 4141 level = 0; 4142 /* Assume active high by default */ 4143 po = 0; 4144 4145 if (intr_index == DEFAULT_INDEX || intr_index == FREE_INDEX) { 4146 ASSERT(irq < 16); 4147 if (eisa_level_intr_mask & (1 << irq)) 4148 level = AV_LEVEL; 4149 if (intr_index == FREE_INDEX && apic_defconf == 0) 4150 apic_error |= APIC_ERR_INVALID_INDEX; 4151 } else if (intr_index == ACPI_INDEX) { 4152 bus_type = irqptr->airq_iflag.bustype; 4153 if (irqptr->airq_iflag.intr_el == INTR_EL_CONFORM) { 4154 if (bus_type == BUS_PCI) 4155 level = AV_LEVEL; 4156 } else 4157 level = (irqptr->airq_iflag.intr_el == INTR_EL_LEVEL) ? 4158 AV_LEVEL : 0; 4159 if (level && 4160 ((irqptr->airq_iflag.intr_po == INTR_PO_ACTIVE_LOW) || 4161 (irqptr->airq_iflag.intr_po == INTR_PO_CONFORM && 4162 bus_type == BUS_PCI))) 4163 po = AV_ACTIVE_LOW; 4164 } else { 4165 iointrp = apic_io_intrp + intr_index; 4166 bus_type = apic_find_bus(iointrp->intr_busid); 4167 if (iointrp->intr_el == INTR_EL_CONFORM) { 4168 if ((irq < 16) && (eisa_level_intr_mask & (1 << irq))) 4169 level = AV_LEVEL; 4170 else if (bus_type == BUS_PCI) 4171 level = AV_LEVEL; 4172 } else 4173 level = (iointrp->intr_el == INTR_EL_LEVEL) ? 4174 AV_LEVEL : 0; 4175 if (level && ((iointrp->intr_po == INTR_PO_ACTIVE_LOW) || 4176 (iointrp->intr_po == INTR_PO_CONFORM && 4177 bus_type == BUS_PCI))) 4178 po = AV_ACTIVE_LOW; 4179 } 4180 if (level) 4181 apic_level_intr[irq] = 1; 4182 /* 4183 * The 82489DX External APIC cannot do active low polarity interrupts. 4184 */ 4185 if (po && (apic_io_ver[ioapicindex] != IOAPIC_VER_82489DX)) 4186 io_po = po; 4187 else 4188 io_po = 0; 4189 4190 if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) 4191 printf("setio: ioapic=%x intin=%x level=%x po=%x vector=%x\n", 4192 ioapicindex, irqptr->airq_intin_no, level, io_po, vector); 4193 4194 irqptr->airq_rdt_entry = level|io_po|vector; 4195 } 4196 4197 /* 4198 * Call rebind to do the actual programming. 4199 */ 4200 static int 4201 apic_setup_io_intr(apic_irq_t *irqptr, int irq) 4202 { 4203 int rv; 4204 4205 if (rv = apic_rebind(irqptr, apic_irq_table[irq]->airq_cpu, 1, 4206 IMMEDIATE)) 4207 /* CPU is not up or interrupt is disabled. Fall back to 0 */ 4208 rv = apic_rebind(irqptr, 0, 1, IMMEDIATE); 4209 4210 return (rv); 4211 } 4212 4213 /* 4214 * Deferred reprogramming: Call apic_rebind to do the real work. 4215 */ 4216 static int 4217 apic_setup_io_intr_deferred(apic_irq_t *irqptr, int irq) 4218 { 4219 int rv; 4220 4221 if (rv = apic_rebind(irqptr, apic_irq_table[irq]->airq_cpu, 1, 4222 DEFERRED)) 4223 /* CPU is not up or interrupt is disabled. Fall back to 0 */ 4224 rv = apic_rebind(irqptr, 0, 1, DEFERRED); 4225 4226 return (rv); 4227 } 4228 4229 /* 4230 * Bind interrupt corresponding to irq_ptr to bind_cpu. acquire_lock 4231 * if false (0) means lock is already held (e.g: in rebind_all). 4232 */ 4233 static int 4234 apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, int acquire_lock, int when) 4235 { 4236 int intin_no; 4237 volatile int32_t *ioapic; 4238 uchar_t airq_temp_cpu; 4239 apic_cpus_info_t *cpu_infop; 4240 int iflag; 4241 int which_irq = apic_vector_to_irq[irq_ptr->airq_vector]; 4242 boolean_t restore_iflag = B_TRUE; 4243 4244 intin_no = irq_ptr->airq_intin_no; 4245 ioapic = apicioadr[irq_ptr->airq_ioapicindex]; 4246 airq_temp_cpu = irq_ptr->airq_temp_cpu; 4247 if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) { 4248 if (airq_temp_cpu & IRQ_USER_BOUND) 4249 /* Mask off high bit so it can be used as array index */ 4250 airq_temp_cpu &= ~IRQ_USER_BOUND; 4251 4252 ASSERT(airq_temp_cpu < apic_nproc); 4253 } 4254 4255 iflag = intr_clear(); 4256 4257 if (acquire_lock) 4258 lock_set(&apic_ioapic_lock); 4259 4260 /* 4261 * Can't bind to a CPU that's not online: 4262 */ 4263 cpu_infop = &apic_cpus[bind_cpu & ~IRQ_USER_BOUND]; 4264 if (!(cpu_infop->aci_status & APIC_CPU_INTR_ENABLE)) { 4265 4266 if (acquire_lock) 4267 lock_clear(&apic_ioapic_lock); 4268 4269 intr_restore(iflag); 4270 return (1); 4271 } 4272 4273 /* 4274 * If this is a deferred reprogramming attempt, ensure we have 4275 * not been passed stale data: 4276 */ 4277 if ((when == DEFERRED) && 4278 (apic_reprogram_info[which_irq].valid == 0)) { 4279 /* stale info, so just return */ 4280 if (acquire_lock) 4281 lock_clear(&apic_ioapic_lock); 4282 4283 intr_restore(iflag); 4284 return (0); 4285 } 4286 4287 /* 4288 * If this interrupt has been delivered to a CPU and that CPU 4289 * has not handled it yet, we cannot reprogram the IOAPIC now: 4290 */ 4291 if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index) && 4292 apic_check_stuck_interrupt(irq_ptr, airq_temp_cpu, bind_cpu, 4293 ioapic, intin_no, which_irq, iflag, &restore_iflag) != 0) { 4294 4295 if (acquire_lock) 4296 lock_clear(&apic_ioapic_lock); 4297 4298 if (restore_iflag) 4299 intr_restore(iflag); 4300 return (0); 4301 } 4302 4303 /* 4304 * NOTE: We do not unmask the RDT here, as an interrupt MAY still 4305 * come in before we have a chance to reprogram it below. The 4306 * reprogramming below will simultaneously change and unmask the 4307 * RDT entry. 4308 */ 4309 4310 if ((uchar_t)bind_cpu == IRQ_UNBOUND) { 4311 /* Write the RDT entry -- no specific CPU binding */ 4312 WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic, intin_no, AV_TOALL); 4313 4314 if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) 4315 apic_cpus[airq_temp_cpu].aci_temp_bound--; 4316 4317 /* Write the vector, trigger, and polarity portion of the RDT */ 4318 WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, 4319 AV_LDEST | AV_LOPRI | irq_ptr->airq_rdt_entry); 4320 if (acquire_lock) 4321 lock_clear(&apic_ioapic_lock); 4322 irq_ptr->airq_temp_cpu = IRQ_UNBOUND; 4323 intr_restore(iflag); 4324 return (0); 4325 } 4326 4327 if (bind_cpu & IRQ_USER_BOUND) { 4328 cpu_infop->aci_bound++; 4329 } else { 4330 cpu_infop->aci_temp_bound++; 4331 } 4332 ASSERT((bind_cpu & ~IRQ_USER_BOUND) < apic_nproc); 4333 if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { 4334 /* Write the RDT entry -- bind to a specific CPU: */ 4335 WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapic, intin_no, 4336 cpu_infop->aci_local_id << APIC_ID_BIT_OFFSET); 4337 } 4338 if ((airq_temp_cpu != IRQ_UNBOUND) && (airq_temp_cpu != IRQ_UNINIT)) { 4339 apic_cpus[airq_temp_cpu].aci_temp_bound--; 4340 } 4341 if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { 4342 /* Write the vector, trigger, and polarity portion of the RDT */ 4343 WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, 4344 AV_PDEST | AV_FIXED | irq_ptr->airq_rdt_entry); 4345 } else { 4346 int type = (irq_ptr->airq_mps_intr_index == MSI_INDEX) ? 4347 DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; 4348 (void) apic_pci_msi_disable_mode(irq_ptr->airq_dip, type, 4349 irq_ptr->airq_ioapicindex); 4350 if (irq_ptr->airq_ioapicindex == irq_ptr->airq_origirq) { 4351 /* first one */ 4352 DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " 4353 "apic_pci_msi_enable_vector\n")); 4354 if (apic_pci_msi_enable_vector(irq_ptr->airq_dip, type, 4355 which_irq, irq_ptr->airq_vector, 4356 irq_ptr->airq_intin_no, 4357 cpu_infop->aci_local_id) != PSM_SUCCESS) { 4358 cmn_err(CE_WARN, "pcplusmp: " 4359 "apic_pci_msi_enable_vector " 4360 "returned PSM_FAILURE"); 4361 } 4362 } 4363 if ((irq_ptr->airq_ioapicindex + irq_ptr->airq_intin_no - 1) == 4364 irq_ptr->airq_origirq) { /* last one */ 4365 DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " 4366 "pci_msi_enable_mode\n")); 4367 if (apic_pci_msi_enable_mode(irq_ptr->airq_dip, 4368 type, which_irq) != PSM_SUCCESS) { 4369 DDI_INTR_IMPLDBG((CE_CONT, "pcplusmp: " 4370 "pci_msi_enable failed\n")); 4371 (void) apic_pci_msi_unconfigure( 4372 irq_ptr->airq_dip, type, which_irq); 4373 } 4374 } 4375 } 4376 if (acquire_lock) 4377 lock_clear(&apic_ioapic_lock); 4378 irq_ptr->airq_temp_cpu = (uchar_t)bind_cpu; 4379 apic_redist_cpu_skip &= ~(1 << (bind_cpu & ~IRQ_USER_BOUND)); 4380 intr_restore(iflag); 4381 return (0); 4382 } 4383 4384 /* 4385 * Checks to see if the IOAPIC interrupt entry specified has its Remote IRR 4386 * bit set. Sets up a timeout to perform the reprogramming at a later time 4387 * if it cannot wait for the Remote IRR bit to clear (or if waiting did not 4388 * result in the bit's clearing). 4389 * 4390 * This function will mask the RDT entry if the Remote IRR bit is set. 4391 * 4392 * Returns non-zero if the caller should defer IOAPIC reprogramming. 4393 */ 4394 static int 4395 apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, 4396 int new_bind_cpu, volatile int32_t *ioapic, int intin_no, int which_irq, 4397 int iflag, boolean_t *intr_restorep) 4398 { 4399 int32_t rdt_entry; 4400 int waited; 4401 4402 /* Mask the RDT entry, but only if it's a level-triggered interrupt */ 4403 rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no); 4404 if ((rdt_entry & (AV_LEVEL|AV_MASK)) == AV_LEVEL) { 4405 4406 /* Mask it */ 4407 WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no, 4408 AV_MASK | rdt_entry); 4409 } 4410 4411 /* 4412 * Wait for the delivery pending bit to clear. 4413 */ 4414 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) & 4415 (AV_LEVEL|AV_PENDING)) == (AV_LEVEL|AV_PENDING)) { 4416 4417 /* 4418 * If we're still waiting on the delivery of this interrupt, 4419 * continue to wait here until it is delivered (this should be 4420 * a very small amount of time, but include a timeout just in 4421 * case). 4422 */ 4423 for (waited = 0; waited < apic_max_usecs_clear_pending; 4424 waited += APIC_USECS_PER_WAIT_INTERVAL) { 4425 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) 4426 & AV_PENDING) == 0) { 4427 break; 4428 } 4429 drv_usecwait(APIC_USECS_PER_WAIT_INTERVAL); 4430 } 4431 4432 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) & 4433 AV_PENDING) != 0) { 4434 cmn_err(CE_WARN, "!IOAPIC %d intin %d: Could not " 4435 "deliver interrupt to local APIC within " 4436 "%d usecs.", irq_ptr->airq_ioapicindex, 4437 irq_ptr->airq_intin_no, 4438 apic_max_usecs_clear_pending); 4439 } 4440 } 4441 4442 /* 4443 * If the remote IRR bit is set, then the interrupt has been sent 4444 * to a CPU for processing. We have no choice but to wait for 4445 * that CPU to process the interrupt, at which point the remote IRR 4446 * bit will be cleared. 4447 */ 4448 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) & 4449 (AV_LEVEL|AV_REMOTE_IRR)) == (AV_LEVEL|AV_REMOTE_IRR)) { 4450 4451 /* 4452 * If the CPU that this RDT is bound to is NOT the current 4453 * CPU, wait until that CPU handles the interrupt and ACKs 4454 * it. If this interrupt is not bound to any CPU (that is, 4455 * if it's bound to the logical destination of "anyone"), it 4456 * may have been delivered to the current CPU so handle that 4457 * case by deferring the reprogramming (below). 4458 */ 4459 kpreempt_disable(); 4460 if ((old_bind_cpu != IRQ_UNBOUND) && 4461 (old_bind_cpu != IRQ_UNINIT) && 4462 (old_bind_cpu != psm_get_cpu_id())) { 4463 for (waited = 0; waited < apic_max_usecs_clear_pending; 4464 waited += APIC_USECS_PER_WAIT_INTERVAL) { 4465 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, 4466 intin_no) & AV_REMOTE_IRR) == 0) { 4467 4468 /* Clear the reprogramming state: */ 4469 lock_set(&apic_ioapic_reprogram_lock); 4470 4471 apic_reprogram_info[which_irq].valid 4472 = 0; 4473 apic_reprogram_info[which_irq].bindcpu 4474 = 0; 4475 apic_reprogram_info[which_irq].timeouts 4476 = 0; 4477 4478 lock_clear(&apic_ioapic_reprogram_lock); 4479 4480 /* Remote IRR has cleared! */ 4481 kpreempt_enable(); 4482 return (0); 4483 } 4484 drv_usecwait(APIC_USECS_PER_WAIT_INTERVAL); 4485 } 4486 } 4487 kpreempt_enable(); 4488 4489 /* 4490 * If we waited and the Remote IRR bit is still not cleared, 4491 * AND if we've invoked the timeout APIC_REPROGRAM_MAX_TIMEOUTS 4492 * times for this interrupt, try the last-ditch workarounds: 4493 */ 4494 if (apic_reprogram_info[which_irq].timeouts >= 4495 APIC_REPROGRAM_MAX_TIMEOUTS) { 4496 4497 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, intin_no) 4498 & AV_REMOTE_IRR) != 0) { 4499 /* 4500 * Trying to clear the bit through normal 4501 * channels has failed. So as a last-ditch 4502 * effort, try to set the trigger mode to 4503 * edge, then to level. This has been 4504 * observed to work on many systems. 4505 */ 4506 WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, 4507 intin_no, 4508 READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, 4509 intin_no) & ~AV_LEVEL); 4510 4511 WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, 4512 intin_no, 4513 READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, 4514 intin_no) | AV_LEVEL); 4515 4516 /* 4517 * If the bit's STILL set, declare total and 4518 * utter failure 4519 */ 4520 if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic, 4521 intin_no) & AV_REMOTE_IRR) != 0) { 4522 cmn_err(CE_WARN, "!IOAPIC %d intin %d: " 4523 "Remote IRR failed to reset " 4524 "within %d usecs. Interrupts to " 4525 "this pin may cease to function.", 4526 irq_ptr->airq_ioapicindex, 4527 irq_ptr->airq_intin_no, 4528 apic_max_usecs_clear_pending); 4529 } 4530 } 4531 /* Clear the reprogramming state: */ 4532 lock_set(&apic_ioapic_reprogram_lock); 4533 4534 apic_reprogram_info[which_irq].valid = 0; 4535 apic_reprogram_info[which_irq].bindcpu = 0; 4536 apic_reprogram_info[which_irq].timeouts = 0; 4537 4538 lock_clear(&apic_ioapic_reprogram_lock); 4539 } else { 4540 #ifdef DEBUG 4541 cmn_err(CE_WARN, "Deferring reprogramming of irq %d", 4542 which_irq); 4543 #endif /* DEBUG */ 4544 /* 4545 * If waiting for the Remote IRR bit (above) didn't 4546 * allow it to clear, defer the reprogramming: 4547 */ 4548 lock_set(&apic_ioapic_reprogram_lock); 4549 4550 apic_reprogram_info[which_irq].valid = 1; 4551 apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; 4552 apic_reprogram_info[which_irq].timeouts++; 4553 4554 lock_clear(&apic_ioapic_reprogram_lock); 4555 4556 *intr_restorep = B_FALSE; 4557 intr_restore(iflag); 4558 4559 /* Fire up a timeout to handle this later */ 4560 (void) timeout(apic_reprogram_timeout_handler, 4561 (void *) 0, 4562 drv_usectohz(APIC_REPROGRAM_TIMEOUT_DELAY)); 4563 4564 /* Inform caller to defer IOAPIC programming: */ 4565 return (1); 4566 } 4567 } 4568 return (0); 4569 } 4570 4571 /* 4572 * Timeout handler that performs the APIC reprogramming 4573 */ 4574 /*ARGSUSED*/ 4575 static void 4576 apic_reprogram_timeout_handler(void *arg) 4577 { 4578 /*LINTED: set but not used in function*/ 4579 int i, result; 4580 4581 /* Serialize access to this function */ 4582 mutex_enter(&apic_reprogram_timeout_mutex); 4583 4584 /* 4585 * For each entry in the reprogramming state that's valid, 4586 * try the reprogramming again: 4587 */ 4588 for (i = 0; i < APIC_MAX_VECTOR; i++) { 4589 if (apic_reprogram_info[i].valid == 0) 4590 continue; 4591 /* 4592 * Though we can't really do anything about errors 4593 * at this point, keep track of them for reporting. 4594 * Note that it is very possible for apic_setup_io_intr 4595 * to re-register this very timeout if the Remote IRR bit 4596 * has not yet cleared. 4597 */ 4598 result = apic_setup_io_intr_deferred(apic_irq_table[i], i); 4599 4600 #ifdef DEBUG 4601 if (result) 4602 cmn_err(CE_WARN, "apic_reprogram_timeout: " 4603 "apic_setup_io_intr returned nonzero for " 4604 "irq=%d!", i); 4605 #endif /* DEBUG */ 4606 } 4607 4608 mutex_exit(&apic_reprogram_timeout_mutex); 4609 } 4610 4611 4612 /* 4613 * Called to migrate all interrupts at an irq to another cpu. safe 4614 * if true means we are not being called from an interrupt 4615 * context and hence it is safe to do a lock_set. If false 4616 * do only a lock_try and return failure ( non 0 ) if we cannot get it 4617 */ 4618 int 4619 apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu, int safe) 4620 { 4621 apic_irq_t *irqptr = irq_ptr; 4622 int retval = 0; 4623 int iflag; 4624 4625 iflag = intr_clear(); 4626 if (!safe) { 4627 if (lock_try(&apic_ioapic_lock) == 0) { 4628 intr_restore(iflag); 4629 return (1); 4630 } 4631 } else 4632 lock_set(&apic_ioapic_lock); 4633 4634 while (irqptr) { 4635 if (irqptr->airq_temp_cpu != IRQ_UNINIT) 4636 retval |= apic_rebind(irqptr, bind_cpu, 0, IMMEDIATE); 4637 irqptr = irqptr->airq_next; 4638 } 4639 lock_clear(&apic_ioapic_lock); 4640 intr_restore(iflag); 4641 return (retval); 4642 } 4643 4644 /* 4645 * apic_intr_redistribute does all the messy computations for identifying 4646 * which interrupt to move to which CPU. Currently we do just one interrupt 4647 * at a time. This reduces the time we spent doing all this within clock 4648 * interrupt. When it is done in idle, we could do more than 1. 4649 * First we find the most busy and the most free CPU (time in ISR only) 4650 * skipping those CPUs that has been identified as being ineligible (cpu_skip) 4651 * Then we look for IRQs which are closest to the difference between the 4652 * most busy CPU and the average ISR load. We try to find one whose load 4653 * is less than difference.If none exists, then we chose one larger than the 4654 * difference, provided it does not make the most idle CPU worse than the 4655 * most busy one. In the end, we clear all the busy fields for CPUs. For 4656 * IRQs, they are cleared as they are scanned. 4657 */ 4658 static void 4659 apic_intr_redistribute() 4660 { 4661 int busiest_cpu, most_free_cpu; 4662 int cpu_free, cpu_busy, max_busy, min_busy; 4663 int min_free, diff; 4664 int average_busy, cpus_online; 4665 int i, busy; 4666 apic_cpus_info_t *cpu_infop; 4667 apic_irq_t *min_busy_irq = NULL; 4668 apic_irq_t *max_busy_irq = NULL; 4669 4670 busiest_cpu = most_free_cpu = -1; 4671 cpu_free = cpu_busy = max_busy = average_busy = 0; 4672 min_free = apic_sample_factor_redistribution; 4673 cpus_online = 0; 4674 /* 4675 * Below we will check for CPU_INTR_ENABLE, bound, temp_bound, temp_cpu 4676 * without ioapic_lock. That is OK as we are just doing statistical 4677 * sampling anyway and any inaccuracy now will get corrected next time 4678 * The call to rebind which actually changes things will make sure 4679 * we are consistent. 4680 */ 4681 for (i = 0; i < apic_nproc; i++) { 4682 if (!(apic_redist_cpu_skip & (1 << i)) && 4683 (apic_cpus[i].aci_status & APIC_CPU_INTR_ENABLE)) { 4684 4685 cpu_infop = &apic_cpus[i]; 4686 /* 4687 * If no unbound interrupts or only 1 total on this 4688 * CPU, skip 4689 */ 4690 if (!cpu_infop->aci_temp_bound || 4691 (cpu_infop->aci_bound + cpu_infop->aci_temp_bound) 4692 == 1) { 4693 apic_redist_cpu_skip |= 1 << i; 4694 continue; 4695 } 4696 4697 busy = cpu_infop->aci_busy; 4698 average_busy += busy; 4699 cpus_online++; 4700 if (max_busy < busy) { 4701 max_busy = busy; 4702 busiest_cpu = i; 4703 } 4704 if (min_free > busy) { 4705 min_free = busy; 4706 most_free_cpu = i; 4707 } 4708 if (busy > apic_int_busy_mark) { 4709 cpu_busy |= 1 << i; 4710 } else { 4711 if (busy < apic_int_free_mark) 4712 cpu_free |= 1 << i; 4713 } 4714 } 4715 } 4716 if ((cpu_busy && cpu_free) || 4717 (max_busy >= (min_free + apic_diff_for_redistribution))) { 4718 4719 apic_num_imbalance++; 4720 #ifdef DEBUG 4721 if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { 4722 prom_printf( 4723 "redistribute busy=%x free=%x max=%x min=%x", 4724 cpu_busy, cpu_free, max_busy, min_free); 4725 } 4726 #endif /* DEBUG */ 4727 4728 4729 average_busy /= cpus_online; 4730 4731 diff = max_busy - average_busy; 4732 min_busy = max_busy; /* start with the max possible value */ 4733 max_busy = 0; 4734 min_busy_irq = max_busy_irq = NULL; 4735 i = apic_min_device_irq; 4736 for (; i < apic_max_device_irq; i++) { 4737 apic_irq_t *irq_ptr; 4738 /* Change to linked list per CPU ? */ 4739 if ((irq_ptr = apic_irq_table[i]) == NULL) 4740 continue; 4741 /* Check for irq_busy & decide which one to move */ 4742 /* Also zero them for next round */ 4743 if ((irq_ptr->airq_temp_cpu == busiest_cpu) && 4744 irq_ptr->airq_busy) { 4745 if (irq_ptr->airq_busy < diff) { 4746 /* 4747 * Check for least busy CPU, 4748 * best fit or what ? 4749 */ 4750 if (max_busy < irq_ptr->airq_busy) { 4751 /* 4752 * Most busy within the 4753 * required differential 4754 */ 4755 max_busy = irq_ptr->airq_busy; 4756 max_busy_irq = irq_ptr; 4757 } 4758 } else { 4759 if (min_busy > irq_ptr->airq_busy) { 4760 /* 4761 * least busy, but more than 4762 * the reqd diff 4763 */ 4764 if (min_busy < 4765 (diff + average_busy - 4766 min_free)) { 4767 /* 4768 * Making sure new cpu 4769 * will not end up 4770 * worse 4771 */ 4772 min_busy = 4773 irq_ptr->airq_busy; 4774 4775 min_busy_irq = irq_ptr; 4776 } 4777 } 4778 } 4779 } 4780 irq_ptr->airq_busy = 0; 4781 } 4782 4783 if (max_busy_irq != NULL) { 4784 #ifdef DEBUG 4785 if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { 4786 prom_printf("rebinding %x to %x", 4787 max_busy_irq->airq_vector, most_free_cpu); 4788 } 4789 #endif /* DEBUG */ 4790 if (apic_rebind_all(max_busy_irq, most_free_cpu, 0) 4791 == 0) 4792 /* Make change permenant */ 4793 max_busy_irq->airq_cpu = (uchar_t)most_free_cpu; 4794 } else if (min_busy_irq != NULL) { 4795 #ifdef DEBUG 4796 if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { 4797 prom_printf("rebinding %x to %x", 4798 min_busy_irq->airq_vector, most_free_cpu); 4799 } 4800 #endif /* DEBUG */ 4801 4802 if (apic_rebind_all(min_busy_irq, most_free_cpu, 0) == 4803 0) 4804 /* Make change permenant */ 4805 min_busy_irq->airq_cpu = (uchar_t)most_free_cpu; 4806 } else { 4807 if (cpu_busy != (1 << busiest_cpu)) { 4808 apic_redist_cpu_skip |= 1 << busiest_cpu; 4809 /* 4810 * We leave cpu_skip set so that next time we 4811 * can choose another cpu 4812 */ 4813 } 4814 } 4815 apic_num_rebind++; 4816 } else { 4817 /* 4818 * found nothing. Could be that we skipped over valid CPUs 4819 * or we have balanced everything. If we had a variable 4820 * ticks_for_redistribution, it could be increased here. 4821 * apic_int_busy, int_free etc would also need to be 4822 * changed. 4823 */ 4824 if (apic_redist_cpu_skip) 4825 apic_redist_cpu_skip = 0; 4826 } 4827 for (i = 0; i < apic_nproc; i++) { 4828 apic_cpus[i].aci_busy = 0; 4829 } 4830 } 4831 4832 static void 4833 apic_cleanup_busy() 4834 { 4835 int i; 4836 apic_irq_t *irq_ptr; 4837 4838 for (i = 0; i < apic_nproc; i++) { 4839 apic_cpus[i].aci_busy = 0; 4840 } 4841 4842 for (i = apic_min_device_irq; i < apic_max_device_irq; i++) { 4843 if ((irq_ptr = apic_irq_table[i]) != NULL) 4844 irq_ptr->airq_busy = 0; 4845 } 4846 apic_skipped_redistribute = 0; 4847 } 4848 4849 4850 /* 4851 * This function will reprogram the timer. 4852 * 4853 * When in oneshot mode the argument is the absolute time in future to 4854 * generate the interrupt at. 4855 * 4856 * When in periodic mode, the argument is the interval at which the 4857 * interrupts should be generated. There is no need to support the periodic 4858 * mode timer change at this time. 4859 */ 4860 static void 4861 apic_timer_reprogram(hrtime_t time) 4862 { 4863 hrtime_t now; 4864 uint_t ticks; 4865 4866 /* 4867 * We should be called from high PIL context (CBE_HIGH_PIL), 4868 * so kpreempt is disabled. 4869 */ 4870 4871 if (!apic_oneshot) { 4872 /* time is the interval for periodic mode */ 4873 ticks = (uint_t)((time) / apic_nsec_per_tick); 4874 } else { 4875 /* one shot mode */ 4876 4877 now = gethrtime(); 4878 4879 if (time <= now) { 4880 /* 4881 * requested to generate an interrupt in the past 4882 * generate an interrupt as soon as possible 4883 */ 4884 ticks = apic_min_timer_ticks; 4885 } else if ((time - now) > apic_nsec_max) { 4886 /* 4887 * requested to generate an interrupt at a time 4888 * further than what we are capable of. Set to max 4889 * the hardware can handle 4890 */ 4891 4892 ticks = APIC_MAXVAL; 4893 #ifdef DEBUG 4894 cmn_err(CE_CONT, "apic_timer_reprogram, request at" 4895 " %lld too far in future, current time" 4896 " %lld \n", time, now); 4897 #endif /* DEBUG */ 4898 } else 4899 ticks = (uint_t)((time - now) / apic_nsec_per_tick); 4900 } 4901 4902 if (ticks < apic_min_timer_ticks) 4903 ticks = apic_min_timer_ticks; 4904 4905 apicadr[APIC_INIT_COUNT] = ticks; 4906 4907 } 4908 4909 /* 4910 * This function will enable timer interrupts. 4911 */ 4912 static void 4913 apic_timer_enable(void) 4914 { 4915 /* 4916 * We should be Called from high PIL context (CBE_HIGH_PIL), 4917 * so kpreempt is disabled. 4918 */ 4919 4920 if (!apic_oneshot) 4921 apicadr[APIC_LOCAL_TIMER] = 4922 (apic_clkvect + APIC_BASE_VECT) | AV_TIME; 4923 else { 4924 /* one shot */ 4925 apicadr[APIC_LOCAL_TIMER] = (apic_clkvect + APIC_BASE_VECT); 4926 } 4927 } 4928 4929 /* 4930 * This function will disable timer interrupts. 4931 */ 4932 static void 4933 apic_timer_disable(void) 4934 { 4935 /* 4936 * We should be Called from high PIL context (CBE_HIGH_PIL), 4937 * so kpreempt is disabled. 4938 */ 4939 4940 apicadr[APIC_LOCAL_TIMER] = (apic_clkvect + APIC_BASE_VECT) | AV_MASK; 4941 } 4942 4943 4944 cyclic_id_t apic_cyclic_id; 4945 4946 /* 4947 * If this module needs to be a consumer of cyclic subsystem, they 4948 * can be added here, since at this time kernel cyclic subsystem is initialized 4949 * argument is not currently used, and is reserved for future. 4950 */ 4951 static void 4952 apic_post_cyclic_setup(void *arg) 4953 { 4954 _NOTE(ARGUNUSED(arg)) 4955 cyc_handler_t hdlr; 4956 cyc_time_t when; 4957 4958 /* cpu_lock is held */ 4959 4960 /* set up cyclics for intr redistribution */ 4961 4962 /* 4963 * In peridoc mode intr redistribution processing is done in 4964 * apic_intr_enter during clk intr processing 4965 */ 4966 if (!apic_oneshot) 4967 return; 4968 4969 hdlr.cyh_level = CY_LOW_LEVEL; 4970 hdlr.cyh_func = (cyc_func_t)apic_redistribute_compute; 4971 hdlr.cyh_arg = NULL; 4972 4973 when.cyt_when = 0; 4974 when.cyt_interval = apic_redistribute_sample_interval; 4975 apic_cyclic_id = cyclic_add(&hdlr, &when); 4976 4977 4978 } 4979 4980 static void 4981 apic_redistribute_compute(void) 4982 { 4983 int i, j, max_busy; 4984 4985 if (apic_enable_dynamic_migration) { 4986 if (++apic_nticks == apic_sample_factor_redistribution) { 4987 /* 4988 * Time to call apic_intr_redistribute(). 4989 * reset apic_nticks. This will cause max_busy 4990 * to be calculated below and if it is more than 4991 * apic_int_busy, we will do the whole thing 4992 */ 4993 apic_nticks = 0; 4994 } 4995 max_busy = 0; 4996 for (i = 0; i < apic_nproc; i++) { 4997 4998 /* 4999 * Check if curipl is non zero & if ISR is in 5000 * progress 5001 */ 5002 if (((j = apic_cpus[i].aci_curipl) != 0) && 5003 (apic_cpus[i].aci_ISR_in_progress & (1 << j))) { 5004 5005 int irq; 5006 apic_cpus[i].aci_busy++; 5007 irq = apic_cpus[i].aci_current[j]; 5008 apic_irq_table[irq]->airq_busy++; 5009 } 5010 5011 if (!apic_nticks && 5012 (apic_cpus[i].aci_busy > max_busy)) 5013 max_busy = apic_cpus[i].aci_busy; 5014 } 5015 if (!apic_nticks) { 5016 if (max_busy > apic_int_busy_mark) { 5017 /* 5018 * We could make the following check be 5019 * skipped > 1 in which case, we get a 5020 * redistribution at half the busy mark (due to 5021 * double interval). Need to be able to collect 5022 * more empirical data to decide if that is a 5023 * good strategy. Punt for now. 5024 */ 5025 if (apic_skipped_redistribute) 5026 apic_cleanup_busy(); 5027 else 5028 apic_intr_redistribute(); 5029 } else 5030 apic_skipped_redistribute++; 5031 } 5032 } 5033 } 5034 5035 5036 static int 5037 apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, 5038 int ipin, int *pci_irqp, iflag_t *intr_flagp) 5039 { 5040 5041 int status; 5042 acpi_psm_lnk_t acpipsmlnk; 5043 5044 if ((status = acpi_get_irq_cache_ent(busid, devid, ipin, pci_irqp, 5045 intr_flagp)) == ACPI_PSM_SUCCESS) { 5046 APIC_VERBOSE_IRQ((CE_CONT, "!pcplusmp: Found irqno %d " 5047 "from cache for device %s, instance #%d\n", *pci_irqp, 5048 ddi_get_name(dip), ddi_get_instance(dip))); 5049 return (status); 5050 } 5051 5052 bzero(&acpipsmlnk, sizeof (acpi_psm_lnk_t)); 5053 5054 if ((status = acpi_translate_pci_irq(dip, ipin, pci_irqp, intr_flagp, 5055 &acpipsmlnk)) == ACPI_PSM_FAILURE) { 5056 APIC_VERBOSE_IRQ((CE_WARN, "pcplusmp: " 5057 " acpi_translate_pci_irq failed for device %s, instance" 5058 " #%d", ddi_get_name(dip), ddi_get_instance(dip))); 5059 return (status); 5060 } 5061 5062 if (status == ACPI_PSM_PARTIAL && acpipsmlnk.lnkobj != NULL) { 5063 status = apic_acpi_irq_configure(&acpipsmlnk, dip, pci_irqp, 5064 intr_flagp); 5065 if (status != ACPI_PSM_SUCCESS) { 5066 status = acpi_get_current_irq_resource(&acpipsmlnk, 5067 pci_irqp, intr_flagp); 5068 } 5069 } 5070 5071 if (status == ACPI_PSM_SUCCESS) { 5072 acpi_new_irq_cache_ent(busid, devid, ipin, *pci_irqp, 5073 intr_flagp, &acpipsmlnk); 5074 5075 APIC_VERBOSE_IRQ((CE_CONT, "pcplusmp: [ACPI] " 5076 "new irq %d for device %s, instance #%d\n", 5077 *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip))); 5078 } 5079 5080 return (status); 5081 } 5082 5083 /* 5084 * Configures the irq for the interrupt link device identified by 5085 * acpipsmlnkp. 5086 * 5087 * Gets the current and the list of possible irq settings for the 5088 * device. If apic_unconditional_srs is not set, and the current 5089 * resource setting is in the list of possible irq settings, 5090 * current irq resource setting is passed to the caller. 5091 * 5092 * Otherwise, picks an irq number from the list of possible irq 5093 * settings, and sets the irq of the device to this value. 5094 * If prefer_crs is set, among a set of irq numbers in the list that have 5095 * the least number of devices sharing the interrupt, we pick current irq 5096 * resource setting if it is a member of this set. 5097 * 5098 * Passes the irq number in the value pointed to by pci_irqp, and 5099 * polarity and sensitivity in the structure pointed to by dipintrflagp 5100 * to the caller. 5101 * 5102 * Note that if setting the irq resource failed, but successfuly obtained 5103 * the current irq resource settings, passes the current irq resources 5104 * and considers it a success. 5105 * 5106 * Returns: 5107 * ACPI_PSM_SUCCESS on success. 5108 * 5109 * ACPI_PSM_FAILURE if an error occured during the configuration or 5110 * if a suitable irq was not found for this device, or if setting the 5111 * irq resource and obtaining the current resource fails. 5112 * 5113 */ 5114 static int 5115 apic_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, 5116 int *pci_irqp, iflag_t *dipintr_flagp) 5117 { 5118 5119 int i, min_share, foundnow, done = 0; 5120 int32_t irq; 5121 int32_t share_irq = -1; 5122 int32_t chosen_irq = -1; 5123 int cur_irq = -1; 5124 acpi_irqlist_t *irqlistp; 5125 acpi_irqlist_t *irqlistent; 5126 5127 if ((acpi_get_possible_irq_resources(acpipsmlnkp, &irqlistp)) 5128 == ACPI_PSM_FAILURE) { 5129 APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: Unable to determine " 5130 "or assign IRQ for device %s, instance #%d: The system was " 5131 "unable to get the list of potential IRQs from ACPI.", 5132 ddi_get_name(dip), ddi_get_instance(dip))); 5133 5134 return (ACPI_PSM_FAILURE); 5135 } 5136 5137 if ((acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, 5138 dipintr_flagp) == ACPI_PSM_SUCCESS) && (!apic_unconditional_srs) && 5139 (cur_irq > 0)) { 5140 /* 5141 * If an IRQ is set in CRS and that IRQ exists in the set 5142 * returned from _PRS, return that IRQ, otherwise print 5143 * a warning 5144 */ 5145 5146 if (acpi_irqlist_find_irq(irqlistp, cur_irq, NULL) 5147 == ACPI_PSM_SUCCESS) { 5148 5149 acpi_free_irqlist(irqlistp); 5150 ASSERT(pci_irqp != NULL); 5151 *pci_irqp = cur_irq; 5152 return (ACPI_PSM_SUCCESS); 5153 } 5154 5155 APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: Could not find the " 5156 "current irq %d for device %s, instance #%d in ACPI's " 5157 "list of possible irqs for this device. Picking one from " 5158 " the latter list.", cur_irq, ddi_get_name(dip), 5159 ddi_get_instance(dip))); 5160 } 5161 5162 irqlistent = irqlistp; 5163 min_share = 255; 5164 5165 while (irqlistent != NULL) { 5166 irqlistent->intr_flags.bustype = BUS_PCI; 5167 5168 for (foundnow = 0, i = 0; i < irqlistent->num_irqs; i++) { 5169 5170 irq = irqlistent->irqs[i]; 5171 5172 if ((irq < 16) && (apic_reserved_irqlist[irq])) 5173 continue; 5174 5175 if (irq == 0) { 5176 /* invalid irq number */ 5177 continue; 5178 } 5179 5180 if ((apic_irq_table[irq] == NULL) || 5181 (apic_irq_table[irq]->airq_dip == dip)) { 5182 chosen_irq = irq; 5183 foundnow = 1; 5184 /* 5185 * If we do not prefer current irq from crs 5186 * or if we do and this irq is the same as 5187 * current irq from crs, this is the one 5188 * to pick. 5189 */ 5190 if (!(apic_prefer_crs) || (irq == cur_irq)) { 5191 done = 1; 5192 break; 5193 } 5194 continue; 5195 } 5196 5197 if (irqlistent->intr_flags.intr_el == INTR_EL_EDGE) 5198 continue; 5199 5200 if (!acpi_intr_compatible(irqlistent->intr_flags, 5201 apic_irq_table[irq]->airq_iflag)) 5202 continue; 5203 5204 if ((apic_irq_table[irq]->airq_share < min_share) || 5205 ((apic_irq_table[irq]->airq_share == min_share) && 5206 (cur_irq == irq) && (apic_prefer_crs))) { 5207 min_share = apic_irq_table[irq]->airq_share; 5208 share_irq = irq; 5209 foundnow = 1; 5210 } 5211 } 5212 5213 /* 5214 * If we found an IRQ in the inner loop this time, save the 5215 * details from the irqlist for later use. 5216 */ 5217 if (foundnow && ((chosen_irq != -1) || (share_irq != -1))) { 5218 /* 5219 * Copy the acpi_prs_private_t and flags from this 5220 * irq list entry, since we found an irq from this 5221 * entry. 5222 */ 5223 acpipsmlnkp->acpi_prs_prv = irqlistent->acpi_prs_prv; 5224 *dipintr_flagp = irqlistent->intr_flags; 5225 } 5226 5227 if (done) 5228 break; 5229 5230 /* Go to the next irqlist entry */ 5231 irqlistent = irqlistent->next; 5232 } 5233 5234 5235 acpi_free_irqlist(irqlistp); 5236 if (chosen_irq != -1) 5237 irq = chosen_irq; 5238 else if (share_irq != -1) 5239 irq = share_irq; 5240 else { 5241 APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: Could not find a " 5242 "suitable irq from the list of possible irqs for device " 5243 "%s, instance #%d in ACPI's list of possible irqs", 5244 ddi_get_name(dip), ddi_get_instance(dip))); 5245 return (ACPI_PSM_FAILURE); 5246 } 5247 5248 APIC_VERBOSE_IRQ((CE_CONT, "!pcplusmp: Setting irq %d for device %s " 5249 "instance #%d\n", irq, ddi_get_name(dip), ddi_get_instance(dip))); 5250 5251 if ((acpi_set_irq_resource(acpipsmlnkp, irq)) == ACPI_PSM_SUCCESS) { 5252 /* 5253 * setting irq was successful, check to make sure CRS 5254 * reflects that. If CRS does not agree with what we 5255 * set, return the irq that was set. 5256 */ 5257 5258 if (acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, 5259 dipintr_flagp) == ACPI_PSM_SUCCESS) { 5260 5261 if (cur_irq != irq) 5262 APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: " 5263 "IRQ resource set (irqno %d) for device %s " 5264 "instance #%d, differs from current " 5265 "setting irqno %d", 5266 irq, ddi_get_name(dip), 5267 ddi_get_instance(dip), cur_irq)); 5268 } 5269 5270 /* 5271 * return the irq that was set, and not what CRS reports, 5272 * since CRS has been seen to be bogus on some systems 5273 */ 5274 cur_irq = irq; 5275 } else { 5276 APIC_VERBOSE_IRQ((CE_WARN, "!pcplusmp: set resource irq %d " 5277 "failed for device %s instance #%d", 5278 irq, ddi_get_name(dip), ddi_get_instance(dip))); 5279 5280 if (cur_irq == -1) 5281 return (ACPI_PSM_FAILURE); 5282 } 5283 5284 ASSERT(pci_irqp != NULL); 5285 *pci_irqp = cur_irq; 5286 return (ACPI_PSM_SUCCESS); 5287 } 5288