1 /* 2 * Copyright (c) 1991 The Regents of the University of California. 3 * Copyright (c) 1996, by Steve Passe. All rights reserved. 4 * Copyright (c) 2005,2008 The DragonFly Project. All rights reserved. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The DragonFly Project 8 * by Matthew Dillon <dillon@backplane.com> 9 * 10 * This code is derived from software contributed to Berkeley by 11 * William Jolitz. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in 21 * the documentation and/or other materials provided with the 22 * distribution. 23 * 3. Neither the name of The DragonFly Project nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific, prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 31 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 32 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 37 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * $DragonFly: src/sys/platform/pc64/apic/apic_abi.c,v 1.1 2008/08/29 17:07:12 dillon Exp $ 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/machintr.h> 47 #include <sys/interrupt.h> 48 #include <sys/bus.h> 49 #include <sys/rman.h> 50 #include <sys/thread2.h> 51 52 #include <machine/smp.h> 53 #include <machine/segments.h> 54 #include <machine/md_var.h> 55 #include <machine/intr_machdep.h> 56 #include <machine/globaldata.h> 57 58 #include <machine_base/isa/isa_intr.h> 59 #include <machine_base/icu/icu.h> 60 #include <machine_base/icu/icu_var.h> 61 #include <machine_base/apic/ioapic.h> 62 #include <machine_base/apic/ioapic_abi.h> 63 #include <machine_base/apic/ioapic_ipl.h> 64 #include <machine_base/apic/apicreg.h> 65 66 #include <dev/acpica5/acpi_sci_var.h> 67 68 #define IOAPIC_HWI_VECTORS IDT_HWI_VECTORS 69 70 extern inthand_t 71 IDTVEC(ioapic_intr0), 72 IDTVEC(ioapic_intr1), 73 IDTVEC(ioapic_intr2), 74 IDTVEC(ioapic_intr3), 75 IDTVEC(ioapic_intr4), 76 IDTVEC(ioapic_intr5), 77 IDTVEC(ioapic_intr6), 78 IDTVEC(ioapic_intr7), 79 IDTVEC(ioapic_intr8), 80 IDTVEC(ioapic_intr9), 81 IDTVEC(ioapic_intr10), 82 IDTVEC(ioapic_intr11), 83 IDTVEC(ioapic_intr12), 84 IDTVEC(ioapic_intr13), 85 IDTVEC(ioapic_intr14), 86 IDTVEC(ioapic_intr15), 87 IDTVEC(ioapic_intr16), 88 IDTVEC(ioapic_intr17), 89 IDTVEC(ioapic_intr18), 90 IDTVEC(ioapic_intr19), 91 IDTVEC(ioapic_intr20), 92 IDTVEC(ioapic_intr21), 93 IDTVEC(ioapic_intr22), 94 IDTVEC(ioapic_intr23), 95 IDTVEC(ioapic_intr24), 96 IDTVEC(ioapic_intr25), 97 IDTVEC(ioapic_intr26), 98 IDTVEC(ioapic_intr27), 99 IDTVEC(ioapic_intr28), 100 IDTVEC(ioapic_intr29), 101 IDTVEC(ioapic_intr30), 102 IDTVEC(ioapic_intr31), 103 IDTVEC(ioapic_intr32), 104 IDTVEC(ioapic_intr33), 105 IDTVEC(ioapic_intr34), 106 IDTVEC(ioapic_intr35), 107 IDTVEC(ioapic_intr36), 108 IDTVEC(ioapic_intr37), 109 IDTVEC(ioapic_intr38), 110 IDTVEC(ioapic_intr39), 111 IDTVEC(ioapic_intr40), 112 IDTVEC(ioapic_intr41), 113 IDTVEC(ioapic_intr42), 114 IDTVEC(ioapic_intr43), 115 IDTVEC(ioapic_intr44), 116 IDTVEC(ioapic_intr45), 117 IDTVEC(ioapic_intr46), 118 IDTVEC(ioapic_intr47), 119 IDTVEC(ioapic_intr48), 120 IDTVEC(ioapic_intr49), 121 IDTVEC(ioapic_intr50), 122 IDTVEC(ioapic_intr51), 123 IDTVEC(ioapic_intr52), 124 IDTVEC(ioapic_intr53), 125 IDTVEC(ioapic_intr54), 126 IDTVEC(ioapic_intr55), 127 IDTVEC(ioapic_intr56), 128 IDTVEC(ioapic_intr57), 129 IDTVEC(ioapic_intr58), 130 IDTVEC(ioapic_intr59), 131 IDTVEC(ioapic_intr60), 132 IDTVEC(ioapic_intr61), 133 IDTVEC(ioapic_intr62), 134 IDTVEC(ioapic_intr63), 135 IDTVEC(ioapic_intr64), 136 IDTVEC(ioapic_intr65), 137 IDTVEC(ioapic_intr66), 138 IDTVEC(ioapic_intr67), 139 IDTVEC(ioapic_intr68), 140 IDTVEC(ioapic_intr69), 141 IDTVEC(ioapic_intr70), 142 IDTVEC(ioapic_intr71), 143 IDTVEC(ioapic_intr72), 144 IDTVEC(ioapic_intr73), 145 IDTVEC(ioapic_intr74), 146 IDTVEC(ioapic_intr75), 147 IDTVEC(ioapic_intr76), 148 IDTVEC(ioapic_intr77), 149 IDTVEC(ioapic_intr78), 150 IDTVEC(ioapic_intr79), 151 IDTVEC(ioapic_intr80), 152 IDTVEC(ioapic_intr81), 153 IDTVEC(ioapic_intr82), 154 IDTVEC(ioapic_intr83), 155 IDTVEC(ioapic_intr84), 156 IDTVEC(ioapic_intr85), 157 IDTVEC(ioapic_intr86), 158 IDTVEC(ioapic_intr87), 159 IDTVEC(ioapic_intr88), 160 IDTVEC(ioapic_intr89), 161 IDTVEC(ioapic_intr90), 162 IDTVEC(ioapic_intr91), 163 IDTVEC(ioapic_intr92), 164 IDTVEC(ioapic_intr93), 165 IDTVEC(ioapic_intr94), 166 IDTVEC(ioapic_intr95), 167 IDTVEC(ioapic_intr96), 168 IDTVEC(ioapic_intr97), 169 IDTVEC(ioapic_intr98), 170 IDTVEC(ioapic_intr99), 171 IDTVEC(ioapic_intr100), 172 IDTVEC(ioapic_intr101), 173 IDTVEC(ioapic_intr102), 174 IDTVEC(ioapic_intr103), 175 IDTVEC(ioapic_intr104), 176 IDTVEC(ioapic_intr105), 177 IDTVEC(ioapic_intr106), 178 IDTVEC(ioapic_intr107), 179 IDTVEC(ioapic_intr108), 180 IDTVEC(ioapic_intr109), 181 IDTVEC(ioapic_intr110), 182 IDTVEC(ioapic_intr111), 183 IDTVEC(ioapic_intr112), 184 IDTVEC(ioapic_intr113), 185 IDTVEC(ioapic_intr114), 186 IDTVEC(ioapic_intr115), 187 IDTVEC(ioapic_intr116), 188 IDTVEC(ioapic_intr117), 189 IDTVEC(ioapic_intr118), 190 IDTVEC(ioapic_intr119), 191 IDTVEC(ioapic_intr120), 192 IDTVEC(ioapic_intr121), 193 IDTVEC(ioapic_intr122), 194 IDTVEC(ioapic_intr123), 195 IDTVEC(ioapic_intr124), 196 IDTVEC(ioapic_intr125), 197 IDTVEC(ioapic_intr126), 198 IDTVEC(ioapic_intr127), 199 IDTVEC(ioapic_intr128), 200 IDTVEC(ioapic_intr129), 201 IDTVEC(ioapic_intr130), 202 IDTVEC(ioapic_intr131), 203 IDTVEC(ioapic_intr132), 204 IDTVEC(ioapic_intr133), 205 IDTVEC(ioapic_intr134), 206 IDTVEC(ioapic_intr135), 207 IDTVEC(ioapic_intr136), 208 IDTVEC(ioapic_intr137), 209 IDTVEC(ioapic_intr138), 210 IDTVEC(ioapic_intr139), 211 IDTVEC(ioapic_intr140), 212 IDTVEC(ioapic_intr141), 213 IDTVEC(ioapic_intr142), 214 IDTVEC(ioapic_intr143), 215 IDTVEC(ioapic_intr144), 216 IDTVEC(ioapic_intr145), 217 IDTVEC(ioapic_intr146), 218 IDTVEC(ioapic_intr147), 219 IDTVEC(ioapic_intr148), 220 IDTVEC(ioapic_intr149), 221 IDTVEC(ioapic_intr150), 222 IDTVEC(ioapic_intr151), 223 IDTVEC(ioapic_intr152), 224 IDTVEC(ioapic_intr153), 225 IDTVEC(ioapic_intr154), 226 IDTVEC(ioapic_intr155), 227 IDTVEC(ioapic_intr156), 228 IDTVEC(ioapic_intr157), 229 IDTVEC(ioapic_intr158), 230 IDTVEC(ioapic_intr159), 231 IDTVEC(ioapic_intr160), 232 IDTVEC(ioapic_intr161), 233 IDTVEC(ioapic_intr162), 234 IDTVEC(ioapic_intr163), 235 IDTVEC(ioapic_intr164), 236 IDTVEC(ioapic_intr165), 237 IDTVEC(ioapic_intr166), 238 IDTVEC(ioapic_intr167), 239 IDTVEC(ioapic_intr168), 240 IDTVEC(ioapic_intr169), 241 IDTVEC(ioapic_intr170), 242 IDTVEC(ioapic_intr171), 243 IDTVEC(ioapic_intr172), 244 IDTVEC(ioapic_intr173), 245 IDTVEC(ioapic_intr174), 246 IDTVEC(ioapic_intr175), 247 IDTVEC(ioapic_intr176), 248 IDTVEC(ioapic_intr177), 249 IDTVEC(ioapic_intr178), 250 IDTVEC(ioapic_intr179), 251 IDTVEC(ioapic_intr180), 252 IDTVEC(ioapic_intr181), 253 IDTVEC(ioapic_intr182), 254 IDTVEC(ioapic_intr183), 255 IDTVEC(ioapic_intr184), 256 IDTVEC(ioapic_intr185), 257 IDTVEC(ioapic_intr186), 258 IDTVEC(ioapic_intr187), 259 IDTVEC(ioapic_intr188), 260 IDTVEC(ioapic_intr189), 261 IDTVEC(ioapic_intr190), 262 IDTVEC(ioapic_intr191); 263 264 static inthand_t *ioapic_intr[IOAPIC_HWI_VECTORS] = { 265 &IDTVEC(ioapic_intr0), 266 &IDTVEC(ioapic_intr1), 267 &IDTVEC(ioapic_intr2), 268 &IDTVEC(ioapic_intr3), 269 &IDTVEC(ioapic_intr4), 270 &IDTVEC(ioapic_intr5), 271 &IDTVEC(ioapic_intr6), 272 &IDTVEC(ioapic_intr7), 273 &IDTVEC(ioapic_intr8), 274 &IDTVEC(ioapic_intr9), 275 &IDTVEC(ioapic_intr10), 276 &IDTVEC(ioapic_intr11), 277 &IDTVEC(ioapic_intr12), 278 &IDTVEC(ioapic_intr13), 279 &IDTVEC(ioapic_intr14), 280 &IDTVEC(ioapic_intr15), 281 &IDTVEC(ioapic_intr16), 282 &IDTVEC(ioapic_intr17), 283 &IDTVEC(ioapic_intr18), 284 &IDTVEC(ioapic_intr19), 285 &IDTVEC(ioapic_intr20), 286 &IDTVEC(ioapic_intr21), 287 &IDTVEC(ioapic_intr22), 288 &IDTVEC(ioapic_intr23), 289 &IDTVEC(ioapic_intr24), 290 &IDTVEC(ioapic_intr25), 291 &IDTVEC(ioapic_intr26), 292 &IDTVEC(ioapic_intr27), 293 &IDTVEC(ioapic_intr28), 294 &IDTVEC(ioapic_intr29), 295 &IDTVEC(ioapic_intr30), 296 &IDTVEC(ioapic_intr31), 297 &IDTVEC(ioapic_intr32), 298 &IDTVEC(ioapic_intr33), 299 &IDTVEC(ioapic_intr34), 300 &IDTVEC(ioapic_intr35), 301 &IDTVEC(ioapic_intr36), 302 &IDTVEC(ioapic_intr37), 303 &IDTVEC(ioapic_intr38), 304 &IDTVEC(ioapic_intr39), 305 &IDTVEC(ioapic_intr40), 306 &IDTVEC(ioapic_intr41), 307 &IDTVEC(ioapic_intr42), 308 &IDTVEC(ioapic_intr43), 309 &IDTVEC(ioapic_intr44), 310 &IDTVEC(ioapic_intr45), 311 &IDTVEC(ioapic_intr46), 312 &IDTVEC(ioapic_intr47), 313 &IDTVEC(ioapic_intr48), 314 &IDTVEC(ioapic_intr49), 315 &IDTVEC(ioapic_intr50), 316 &IDTVEC(ioapic_intr51), 317 &IDTVEC(ioapic_intr52), 318 &IDTVEC(ioapic_intr53), 319 &IDTVEC(ioapic_intr54), 320 &IDTVEC(ioapic_intr55), 321 &IDTVEC(ioapic_intr56), 322 &IDTVEC(ioapic_intr57), 323 &IDTVEC(ioapic_intr58), 324 &IDTVEC(ioapic_intr59), 325 &IDTVEC(ioapic_intr60), 326 &IDTVEC(ioapic_intr61), 327 &IDTVEC(ioapic_intr62), 328 &IDTVEC(ioapic_intr63), 329 &IDTVEC(ioapic_intr64), 330 &IDTVEC(ioapic_intr65), 331 &IDTVEC(ioapic_intr66), 332 &IDTVEC(ioapic_intr67), 333 &IDTVEC(ioapic_intr68), 334 &IDTVEC(ioapic_intr69), 335 &IDTVEC(ioapic_intr70), 336 &IDTVEC(ioapic_intr71), 337 &IDTVEC(ioapic_intr72), 338 &IDTVEC(ioapic_intr73), 339 &IDTVEC(ioapic_intr74), 340 &IDTVEC(ioapic_intr75), 341 &IDTVEC(ioapic_intr76), 342 &IDTVEC(ioapic_intr77), 343 &IDTVEC(ioapic_intr78), 344 &IDTVEC(ioapic_intr79), 345 &IDTVEC(ioapic_intr80), 346 &IDTVEC(ioapic_intr81), 347 &IDTVEC(ioapic_intr82), 348 &IDTVEC(ioapic_intr83), 349 &IDTVEC(ioapic_intr84), 350 &IDTVEC(ioapic_intr85), 351 &IDTVEC(ioapic_intr86), 352 &IDTVEC(ioapic_intr87), 353 &IDTVEC(ioapic_intr88), 354 &IDTVEC(ioapic_intr89), 355 &IDTVEC(ioapic_intr90), 356 &IDTVEC(ioapic_intr91), 357 &IDTVEC(ioapic_intr92), 358 &IDTVEC(ioapic_intr93), 359 &IDTVEC(ioapic_intr94), 360 &IDTVEC(ioapic_intr95), 361 &IDTVEC(ioapic_intr96), 362 &IDTVEC(ioapic_intr97), 363 &IDTVEC(ioapic_intr98), 364 &IDTVEC(ioapic_intr99), 365 &IDTVEC(ioapic_intr100), 366 &IDTVEC(ioapic_intr101), 367 &IDTVEC(ioapic_intr102), 368 &IDTVEC(ioapic_intr103), 369 &IDTVEC(ioapic_intr104), 370 &IDTVEC(ioapic_intr105), 371 &IDTVEC(ioapic_intr106), 372 &IDTVEC(ioapic_intr107), 373 &IDTVEC(ioapic_intr108), 374 &IDTVEC(ioapic_intr109), 375 &IDTVEC(ioapic_intr110), 376 &IDTVEC(ioapic_intr111), 377 &IDTVEC(ioapic_intr112), 378 &IDTVEC(ioapic_intr113), 379 &IDTVEC(ioapic_intr114), 380 &IDTVEC(ioapic_intr115), 381 &IDTVEC(ioapic_intr116), 382 &IDTVEC(ioapic_intr117), 383 &IDTVEC(ioapic_intr118), 384 &IDTVEC(ioapic_intr119), 385 &IDTVEC(ioapic_intr120), 386 &IDTVEC(ioapic_intr121), 387 &IDTVEC(ioapic_intr122), 388 &IDTVEC(ioapic_intr123), 389 &IDTVEC(ioapic_intr124), 390 &IDTVEC(ioapic_intr125), 391 &IDTVEC(ioapic_intr126), 392 &IDTVEC(ioapic_intr127), 393 &IDTVEC(ioapic_intr128), 394 &IDTVEC(ioapic_intr129), 395 &IDTVEC(ioapic_intr130), 396 &IDTVEC(ioapic_intr131), 397 &IDTVEC(ioapic_intr132), 398 &IDTVEC(ioapic_intr133), 399 &IDTVEC(ioapic_intr134), 400 &IDTVEC(ioapic_intr135), 401 &IDTVEC(ioapic_intr136), 402 &IDTVEC(ioapic_intr137), 403 &IDTVEC(ioapic_intr138), 404 &IDTVEC(ioapic_intr139), 405 &IDTVEC(ioapic_intr140), 406 &IDTVEC(ioapic_intr141), 407 &IDTVEC(ioapic_intr142), 408 &IDTVEC(ioapic_intr143), 409 &IDTVEC(ioapic_intr144), 410 &IDTVEC(ioapic_intr145), 411 &IDTVEC(ioapic_intr146), 412 &IDTVEC(ioapic_intr147), 413 &IDTVEC(ioapic_intr148), 414 &IDTVEC(ioapic_intr149), 415 &IDTVEC(ioapic_intr150), 416 &IDTVEC(ioapic_intr151), 417 &IDTVEC(ioapic_intr152), 418 &IDTVEC(ioapic_intr153), 419 &IDTVEC(ioapic_intr154), 420 &IDTVEC(ioapic_intr155), 421 &IDTVEC(ioapic_intr156), 422 &IDTVEC(ioapic_intr157), 423 &IDTVEC(ioapic_intr158), 424 &IDTVEC(ioapic_intr159), 425 &IDTVEC(ioapic_intr160), 426 &IDTVEC(ioapic_intr161), 427 &IDTVEC(ioapic_intr162), 428 &IDTVEC(ioapic_intr163), 429 &IDTVEC(ioapic_intr164), 430 &IDTVEC(ioapic_intr165), 431 &IDTVEC(ioapic_intr166), 432 &IDTVEC(ioapic_intr167), 433 &IDTVEC(ioapic_intr168), 434 &IDTVEC(ioapic_intr169), 435 &IDTVEC(ioapic_intr170), 436 &IDTVEC(ioapic_intr171), 437 &IDTVEC(ioapic_intr172), 438 &IDTVEC(ioapic_intr173), 439 &IDTVEC(ioapic_intr174), 440 &IDTVEC(ioapic_intr175), 441 &IDTVEC(ioapic_intr176), 442 &IDTVEC(ioapic_intr177), 443 &IDTVEC(ioapic_intr178), 444 &IDTVEC(ioapic_intr179), 445 &IDTVEC(ioapic_intr180), 446 &IDTVEC(ioapic_intr181), 447 &IDTVEC(ioapic_intr182), 448 &IDTVEC(ioapic_intr183), 449 &IDTVEC(ioapic_intr184), 450 &IDTVEC(ioapic_intr185), 451 &IDTVEC(ioapic_intr186), 452 &IDTVEC(ioapic_intr187), 453 &IDTVEC(ioapic_intr188), 454 &IDTVEC(ioapic_intr189), 455 &IDTVEC(ioapic_intr190), 456 &IDTVEC(ioapic_intr191) 457 }; 458 459 #define IOAPIC_HWI_SYSCALL (IDT_OFFSET_SYSCALL - IDT_OFFSET) 460 461 static struct ioapic_irqmap { 462 int im_type; /* IOAPIC_IMT_ */ 463 enum intr_trigger im_trig; 464 enum intr_polarity im_pola; 465 int im_gsi; 466 uint32_t im_flags; /* IOAPIC_IMF_ */ 467 } ioapic_irqmaps[MAXCPU][IOAPIC_HWI_VECTORS]; 468 469 #define IOAPIC_IMT_UNUSED 0 470 #define IOAPIC_IMT_RESERVED 1 471 #define IOAPIC_IMT_LINE 2 472 #define IOAPIC_IMT_SYSCALL 3 473 474 #define IOAPIC_IMT_ISHWI(map) ((map)->im_type != IOAPIC_IMT_RESERVED && \ 475 (map)->im_type != IOAPIC_IMT_SYSCALL) 476 477 #define IOAPIC_IMF_CONF 0x1 478 479 extern void IOAPIC_INTREN(int); 480 extern void IOAPIC_INTRDIS(int); 481 482 extern int imcr_present; 483 484 static void ioapic_abi_intr_enable(int); 485 static void ioapic_abi_intr_disable(int); 486 static void ioapic_abi_intr_setup(int, int); 487 static void ioapic_abi_intr_teardown(int); 488 static void ioapic_abi_intr_config(int, 489 enum intr_trigger, enum intr_polarity); 490 static int ioapic_abi_intr_cpuid(int); 491 492 static void ioapic_abi_finalize(void); 493 static void ioapic_abi_cleanup(void); 494 static void ioapic_abi_setdefault(void); 495 static void ioapic_abi_stabilize(void); 496 static void ioapic_abi_initmap(void); 497 static void ioapic_abi_rman_setup(struct rman *); 498 499 static int ioapic_abi_gsi_cpuid(int, int); 500 501 struct machintr_abi MachIntrABI_IOAPIC = { 502 MACHINTR_IOAPIC, 503 .intr_disable = ioapic_abi_intr_disable, 504 .intr_enable = ioapic_abi_intr_enable, 505 .intr_setup = ioapic_abi_intr_setup, 506 .intr_teardown = ioapic_abi_intr_teardown, 507 .intr_config = ioapic_abi_intr_config, 508 .intr_cpuid = ioapic_abi_intr_cpuid, 509 510 .finalize = ioapic_abi_finalize, 511 .cleanup = ioapic_abi_cleanup, 512 .setdefault = ioapic_abi_setdefault, 513 .stabilize = ioapic_abi_stabilize, 514 .initmap = ioapic_abi_initmap, 515 .rman_setup = ioapic_abi_rman_setup 516 }; 517 518 static int ioapic_abi_extint_irq = -1; 519 static int ioapic_abi_line_irq_max; 520 static int ioapic_abi_gsi_balance; 521 522 struct ioapic_irqinfo ioapic_irqs[IOAPIC_HWI_VECTORS]; 523 524 static void 525 ioapic_abi_intr_enable(int irq) 526 { 527 if (irq < 0 || irq >= IOAPIC_HWI_VECTORS) { 528 kprintf("ioapic_abi_intr_enable invalid irq %d\n", irq); 529 return; 530 } 531 IOAPIC_INTREN(irq); 532 } 533 534 static void 535 ioapic_abi_intr_disable(int irq) 536 { 537 if (irq < 0 || irq >= IOAPIC_HWI_VECTORS) { 538 kprintf("ioapic_abi_intr_disable invalid irq %d\n", irq); 539 return; 540 } 541 IOAPIC_INTRDIS(irq); 542 } 543 544 static void 545 ioapic_abi_finalize(void) 546 { 547 KKASSERT(MachIntrABI.type == MACHINTR_IOAPIC); 548 KKASSERT(ioapic_enable); 549 550 /* 551 * If an IMCR is present, program bit 0 to disconnect the 8259 552 * from the BSP. 553 */ 554 if (imcr_present) { 555 outb(0x22, 0x70); /* select IMCR */ 556 outb(0x23, 0x01); /* disconnect 8259 */ 557 } 558 } 559 560 /* 561 * This routine is called after physical interrupts are enabled but before 562 * the critical section is released. We need to clean out any interrupts 563 * that had already been posted to the cpu. 564 */ 565 static void 566 ioapic_abi_cleanup(void) 567 { 568 bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending)); 569 } 570 571 /* Must never be called */ 572 static void 573 ioapic_abi_stabilize(void) 574 { 575 panic("ioapic_stabilize is called\n"); 576 } 577 578 static void 579 ioapic_abi_intr_setup(int intr, int flags) 580 { 581 int vector, select; 582 uint32_t value; 583 register_t ef; 584 585 KKASSERT(intr >= 0 && intr < IOAPIC_HWI_VECTORS && 586 intr != IOAPIC_HWI_SYSCALL); 587 KKASSERT(ioapic_irqs[intr].io_addr != NULL); 588 589 ef = read_rflags(); 590 cpu_disable_intr(); 591 592 vector = IDT_OFFSET + intr; 593 594 /* 595 * Now reprogram the vector in the IO APIC. In order to avoid 596 * losing an EOI for a level interrupt, which is vector based, 597 * make sure that the IO APIC is programmed for edge-triggering 598 * first, then reprogrammed with the new vector. This should 599 * clear the IRR bit. 600 */ 601 imen_lock(); 602 603 select = ioapic_irqs[intr].io_idx; 604 value = ioapic_read(ioapic_irqs[intr].io_addr, select); 605 value |= IOART_INTMSET; 606 607 ioapic_write(ioapic_irqs[intr].io_addr, select, 608 (value & ~APIC_TRIGMOD_MASK)); 609 ioapic_write(ioapic_irqs[intr].io_addr, select, 610 (value & ~IOART_INTVEC) | vector); 611 612 imen_unlock(); 613 614 machintr_intr_enable(intr); 615 616 write_rflags(ef); 617 } 618 619 static void 620 ioapic_abi_intr_teardown(int intr) 621 { 622 int vector, select; 623 uint32_t value; 624 register_t ef; 625 626 KKASSERT(intr >= 0 && intr < IOAPIC_HWI_VECTORS && 627 intr != IOAPIC_HWI_SYSCALL); 628 KKASSERT(ioapic_irqs[intr].io_addr != NULL); 629 630 ef = read_rflags(); 631 cpu_disable_intr(); 632 633 /* 634 * Teardown an interrupt vector. The vector should already be 635 * installed in the cpu's IDT, but make sure. 636 */ 637 machintr_intr_disable(intr); 638 639 vector = IDT_OFFSET + intr; 640 641 /* 642 * In order to avoid losing an EOI for a level interrupt, which 643 * is vector based, make sure that the IO APIC is programmed for 644 * edge-triggering first, then reprogrammed with the new vector. 645 * This should clear the IRR bit. 646 */ 647 imen_lock(); 648 649 select = ioapic_irqs[intr].io_idx; 650 value = ioapic_read(ioapic_irqs[intr].io_addr, select); 651 652 ioapic_write(ioapic_irqs[intr].io_addr, select, 653 (value & ~APIC_TRIGMOD_MASK)); 654 ioapic_write(ioapic_irqs[intr].io_addr, select, 655 (value & ~IOART_INTVEC) | vector); 656 657 imen_unlock(); 658 659 write_rflags(ef); 660 } 661 662 static void 663 ioapic_abi_setdefault(void) 664 { 665 int intr; 666 667 for (intr = 0; intr < IOAPIC_HWI_VECTORS; ++intr) { 668 if (intr == IOAPIC_HWI_SYSCALL) 669 continue; 670 setidt(IDT_OFFSET + intr, ioapic_intr[intr], SDT_SYSIGT, 671 SEL_KPL, 0); 672 } 673 } 674 675 static void 676 ioapic_abi_initmap(void) 677 { 678 int cpu; 679 680 kgetenv_int("hw.ioapic.gsi.balance", &ioapic_abi_gsi_balance); 681 682 /* 683 * NOTE: ncpus is not ready yet 684 */ 685 for (cpu = 0; cpu < MAXCPU; ++cpu) { 686 int i; 687 688 for (i = 0; i < IOAPIC_HWI_VECTORS; ++i) 689 ioapic_irqmaps[cpu][i].im_gsi = -1; 690 ioapic_irqmaps[cpu][IOAPIC_HWI_SYSCALL].im_type = 691 IOAPIC_IMT_SYSCALL; 692 } 693 } 694 695 void 696 ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig, 697 enum intr_polarity pola) 698 { 699 struct ioapic_irqinfo *info; 700 struct ioapic_irqmap *map; 701 void *ioaddr; 702 int pin, cpuid; 703 704 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 705 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 706 707 KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS); 708 if (irq > ioapic_abi_line_irq_max) 709 ioapic_abi_line_irq_max = irq; 710 711 cpuid = ioapic_abi_gsi_cpuid(irq, gsi); 712 713 map = &ioapic_irqmaps[cpuid][irq]; 714 715 KKASSERT(map->im_type == IOAPIC_IMT_UNUSED); 716 map->im_type = IOAPIC_IMT_LINE; 717 718 map->im_gsi = gsi; 719 map->im_trig = trig; 720 map->im_pola = pola; 721 722 if (bootverbose) { 723 kprintf("IOAPIC: irq %d -> gsi %d %s/%s\n", 724 irq, map->im_gsi, 725 intr_str_trigger(map->im_trig), 726 intr_str_polarity(map->im_pola)); 727 } 728 729 pin = ioapic_gsi_pin(map->im_gsi); 730 ioaddr = ioapic_gsi_ioaddr(map->im_gsi); 731 732 info = &ioapic_irqs[irq]; 733 734 imen_lock(); 735 736 info->io_addr = ioaddr; 737 info->io_idx = IOAPIC_REDTBL + (2 * pin); 738 info->io_flags = IOAPIC_IRQI_FLAG_MASKED; 739 if (map->im_trig == INTR_TRIGGER_LEVEL) 740 info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL; 741 742 ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq, 743 map->im_trig, map->im_pola, cpuid); 744 745 imen_unlock(); 746 } 747 748 void 749 ioapic_abi_fixup_irqmap(void) 750 { 751 int cpu; 752 753 for (cpu = 0; cpu < ncpus; ++cpu) { 754 int i; 755 756 for (i = 0; i < ISA_IRQ_CNT; ++i) { 757 struct ioapic_irqmap *map = &ioapic_irqmaps[cpu][i]; 758 759 if (map->im_type == IOAPIC_IMT_UNUSED) { 760 map->im_type = IOAPIC_IMT_RESERVED; 761 if (bootverbose) { 762 kprintf("IOAPIC: " 763 "cpu%d irq %d reserved\n", cpu, i); 764 } 765 } 766 } 767 } 768 769 ioapic_abi_line_irq_max += 1; 770 if (bootverbose) 771 kprintf("IOAPIC: line irq max %d\n", ioapic_abi_line_irq_max); 772 } 773 774 int 775 ioapic_abi_find_gsi(int gsi, enum intr_trigger trig, enum intr_polarity pola) 776 { 777 int cpu; 778 779 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 780 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 781 782 for (cpu = 0; cpu < ncpus; ++cpu) { 783 int irq; 784 785 for (irq = 0; irq < ioapic_abi_line_irq_max; ++irq) { 786 const struct ioapic_irqmap *map = 787 &ioapic_irqmaps[cpu][irq]; 788 789 if (map->im_gsi == gsi) { 790 KKASSERT(map->im_type == IOAPIC_IMT_LINE); 791 792 if (map->im_flags & IOAPIC_IMF_CONF) { 793 if (map->im_trig != trig || 794 map->im_pola != pola) 795 return -1; 796 } 797 return irq; 798 } 799 } 800 } 801 return -1; 802 } 803 804 int 805 ioapic_abi_find_irq(int irq, enum intr_trigger trig, enum intr_polarity pola) 806 { 807 int cpu; 808 809 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 810 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 811 812 if (irq < 0 || irq >= ioapic_abi_line_irq_max) 813 return -1; 814 815 for (cpu = 0; cpu < ncpus; ++cpu) { 816 const struct ioapic_irqmap *map = &ioapic_irqmaps[cpu][irq]; 817 818 if (map->im_type == IOAPIC_IMT_LINE) { 819 if (map->im_flags & IOAPIC_IMF_CONF) { 820 if (map->im_trig != trig || 821 map->im_pola != pola) 822 return -1; 823 } 824 return irq; 825 } 826 } 827 return -1; 828 } 829 830 static void 831 ioapic_abi_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola) 832 { 833 struct ioapic_irqinfo *info; 834 struct ioapic_irqmap *map = NULL; 835 void *ioaddr; 836 int pin, cpuid; 837 838 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 839 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 840 841 KKASSERT(irq >= 0 && irq < ioapic_abi_line_irq_max); 842 for (cpuid = 0; cpuid < ncpus; ++cpuid) { 843 map = &ioapic_irqmaps[cpuid][irq]; 844 if (map->im_type == IOAPIC_IMT_LINE) 845 break; 846 } 847 KKASSERT(cpuid < ncpus); 848 849 #ifdef notyet 850 if (map->im_flags & IOAPIC_IMF_CONF) { 851 if (trig != map->im_trig) { 852 panic("ioapic_intr_config: trig %s -> %s\n", 853 intr_str_trigger(map->im_trig), 854 intr_str_trigger(trig)); 855 } 856 if (pola != map->im_pola) { 857 panic("ioapic_intr_config: pola %s -> %s\n", 858 intr_str_polarity(map->im_pola), 859 intr_str_polarity(pola)); 860 } 861 return; 862 } 863 #endif 864 map->im_flags |= IOAPIC_IMF_CONF; 865 866 if (trig == map->im_trig && pola == map->im_pola) 867 return; 868 869 if (bootverbose) { 870 kprintf("IOAPIC: irq %d, gsi %d %s/%s -> %s/%s\n", 871 irq, map->im_gsi, 872 intr_str_trigger(map->im_trig), 873 intr_str_polarity(map->im_pola), 874 intr_str_trigger(trig), 875 intr_str_polarity(pola)); 876 } 877 map->im_trig = trig; 878 map->im_pola = pola; 879 880 pin = ioapic_gsi_pin(map->im_gsi); 881 ioaddr = ioapic_gsi_ioaddr(map->im_gsi); 882 883 info = &ioapic_irqs[irq]; 884 885 imen_lock(); 886 887 info->io_flags &= ~IOAPIC_IRQI_FLAG_LEVEL; 888 if (map->im_trig == INTR_TRIGGER_LEVEL) 889 info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL; 890 891 ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq, 892 map->im_trig, map->im_pola, cpuid); 893 894 imen_unlock(); 895 } 896 897 int 898 ioapic_abi_extint_irqmap(int irq) 899 { 900 struct ioapic_irqinfo *info; 901 struct ioapic_irqmap *map; 902 void *ioaddr; 903 int pin, error, vec; 904 905 /* XXX only irq0 is allowed */ 906 KKASSERT(irq == 0); 907 908 vec = IDT_OFFSET + irq; 909 910 if (ioapic_abi_extint_irq == irq) 911 return 0; 912 else if (ioapic_abi_extint_irq >= 0) 913 return EEXIST; 914 915 error = icu_ioapic_extint(irq, vec); 916 if (error) 917 return error; 918 919 /* ExtINT is always targeted to cpu0 */ 920 map = &ioapic_irqmaps[0][irq]; 921 922 KKASSERT(map->im_type == IOAPIC_IMT_RESERVED || 923 map->im_type == IOAPIC_IMT_LINE); 924 if (map->im_type == IOAPIC_IMT_LINE) { 925 if (map->im_flags & IOAPIC_IMF_CONF) 926 return EEXIST; 927 } 928 ioapic_abi_extint_irq = irq; 929 930 map->im_type = IOAPIC_IMT_LINE; 931 map->im_trig = INTR_TRIGGER_EDGE; 932 map->im_pola = INTR_POLARITY_HIGH; 933 map->im_flags = IOAPIC_IMF_CONF; 934 935 map->im_gsi = ioapic_extpin_gsi(); 936 KKASSERT(map->im_gsi >= 0); 937 938 if (bootverbose) { 939 kprintf("IOAPIC: irq %d -> extint gsi %d %s/%s\n", 940 irq, map->im_gsi, 941 intr_str_trigger(map->im_trig), 942 intr_str_polarity(map->im_pola)); 943 } 944 945 pin = ioapic_gsi_pin(map->im_gsi); 946 ioaddr = ioapic_gsi_ioaddr(map->im_gsi); 947 948 info = &ioapic_irqs[irq]; 949 950 imen_lock(); 951 952 info->io_addr = ioaddr; 953 info->io_idx = IOAPIC_REDTBL + (2 * pin); 954 info->io_flags = IOAPIC_IRQI_FLAG_MASKED; 955 956 ioapic_extpin_setup(ioaddr, pin, vec); 957 958 imen_unlock(); 959 960 return 0; 961 } 962 963 static int 964 ioapic_abi_intr_cpuid(int irq) 965 { 966 const struct ioapic_irqmap *map = NULL; 967 int cpuid; 968 969 KKASSERT(irq >= 0 && irq < ioapic_abi_line_irq_max); 970 971 for (cpuid = 0; cpuid < ncpus; ++cpuid) { 972 map = &ioapic_irqmaps[cpuid][irq]; 973 if (map->im_type == IOAPIC_IMT_LINE) 974 return cpuid; 975 } 976 977 /* XXX some drivers tries to peek at reserved IRQs */ 978 for (cpuid = 0; cpuid < ncpus; ++cpuid) { 979 map = &ioapic_irqmaps[cpuid][irq]; 980 KKASSERT(map->im_type == IOAPIC_IMT_RESERVED); 981 } 982 return 0; 983 } 984 985 static int 986 ioapic_abi_gsi_cpuid(int irq, int gsi) 987 { 988 char envpath[32]; 989 int cpuid = -1; 990 991 KKASSERT(gsi >= 0); 992 993 if (irq == 0 || gsi == 0) { 994 if (bootverbose) { 995 kprintf("IOAPIC: irq %d, gsi %d -> cpu0 (0)\n", 996 irq, gsi); 997 } 998 return 0; 999 } 1000 1001 if (irq == acpi_sci_irqno()) { 1002 if (bootverbose) { 1003 kprintf("IOAPIC: irq %d, gsi %d -> cpu0 (sci)\n", 1004 irq, gsi); 1005 } 1006 return 0; 1007 } 1008 1009 ksnprintf(envpath, sizeof(envpath), "hw.ioapic.gsi.%d.cpu", gsi); 1010 kgetenv_int(envpath, &cpuid); 1011 1012 if (cpuid < 0) { 1013 if (!ioapic_abi_gsi_balance) { 1014 if (bootverbose) { 1015 kprintf("IOAPIC: irq %d, gsi %d -> cpu0 " 1016 "(fixed)\n", irq, gsi); 1017 } 1018 return 0; 1019 } 1020 1021 cpuid = gsi % ncpus; 1022 if (bootverbose) { 1023 kprintf("IOAPIC: irq %d, gsi %d -> cpu%d (auto)\n", 1024 irq, gsi, cpuid); 1025 } 1026 } else if (cpuid >= ncpus) { 1027 cpuid = ncpus - 1; 1028 if (bootverbose) { 1029 kprintf("IOAPIC: irq %d, gsi %d -> cpu%d (fixup)\n", 1030 irq, gsi, cpuid); 1031 } 1032 } else { 1033 if (bootverbose) { 1034 kprintf("IOAPIC: irq %d, gsi %d -> cpu%d (user)\n", 1035 irq, gsi, cpuid); 1036 } 1037 } 1038 return cpuid; 1039 } 1040 1041 static void 1042 ioapic_abi_rman_setup(struct rman *rm) 1043 { 1044 int start, end, i; 1045 1046 KASSERT(rm->rm_cpuid >= 0 && rm->rm_cpuid < MAXCPU, 1047 ("invalid rman cpuid %d", rm->rm_cpuid)); 1048 1049 start = end = -1; 1050 for (i = 0; i < IOAPIC_HWI_VECTORS; ++i) { 1051 const struct ioapic_irqmap *map = 1052 &ioapic_irqmaps[rm->rm_cpuid][i]; 1053 1054 if (start < 0) { 1055 if (IOAPIC_IMT_ISHWI(map)) 1056 start = end = i; 1057 } else { 1058 if (IOAPIC_IMT_ISHWI(map)) { 1059 end = i; 1060 } else { 1061 KKASSERT(end >= 0); 1062 if (bootverbose) { 1063 kprintf("IOAPIC: rman cpu%d %d - %d\n", 1064 rm->rm_cpuid, start, end); 1065 } 1066 if (rman_manage_region(rm, start, end)) { 1067 panic("rman_manage_region" 1068 "(cpu%d %d - %d)", rm->rm_cpuid, 1069 start, end); 1070 } 1071 start = end = -1; 1072 } 1073 } 1074 } 1075 if (start >= 0) { 1076 KKASSERT(end >= 0); 1077 if (bootverbose) { 1078 kprintf("IOAPIC: rman cpu%d %d - %d\n", 1079 rm->rm_cpuid, start, end); 1080 } 1081 if (rman_manage_region(rm, start, end)) { 1082 panic("rman_manage_region(cpu%d %d - %d)", 1083 rm->rm_cpuid, start, end); 1084 } 1085 } 1086 } 1087