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 50 #include <machine/smp.h> 51 #include <machine/segments.h> 52 #include <machine/md_var.h> 53 #include <machine/intr_machdep.h> 54 #include <machine_base/icu/icu.h> 55 #include <machine/globaldata.h> 56 57 #include <sys/thread2.h> 58 59 #include <machine_base/icu/icu_var.h> 60 #include <machine_base/apic/ioapic_abi.h> 61 #include <machine_base/apic/ioapic_ipl.h> 62 63 #ifdef SMP /* APIC-IO */ 64 65 extern inthand_t 66 IDTVEC(ioapic_intr0), 67 IDTVEC(ioapic_intr1), 68 IDTVEC(ioapic_intr2), 69 IDTVEC(ioapic_intr3), 70 IDTVEC(ioapic_intr4), 71 IDTVEC(ioapic_intr5), 72 IDTVEC(ioapic_intr6), 73 IDTVEC(ioapic_intr7), 74 IDTVEC(ioapic_intr8), 75 IDTVEC(ioapic_intr9), 76 IDTVEC(ioapic_intr10), 77 IDTVEC(ioapic_intr11), 78 IDTVEC(ioapic_intr12), 79 IDTVEC(ioapic_intr13), 80 IDTVEC(ioapic_intr14), 81 IDTVEC(ioapic_intr15), 82 IDTVEC(ioapic_intr16), 83 IDTVEC(ioapic_intr17), 84 IDTVEC(ioapic_intr18), 85 IDTVEC(ioapic_intr19), 86 IDTVEC(ioapic_intr20), 87 IDTVEC(ioapic_intr21), 88 IDTVEC(ioapic_intr22), 89 IDTVEC(ioapic_intr23), 90 IDTVEC(ioapic_intr24), 91 IDTVEC(ioapic_intr25), 92 IDTVEC(ioapic_intr26), 93 IDTVEC(ioapic_intr27), 94 IDTVEC(ioapic_intr28), 95 IDTVEC(ioapic_intr29), 96 IDTVEC(ioapic_intr30), 97 IDTVEC(ioapic_intr31), 98 IDTVEC(ioapic_intr32), 99 IDTVEC(ioapic_intr33), 100 IDTVEC(ioapic_intr34), 101 IDTVEC(ioapic_intr35), 102 IDTVEC(ioapic_intr36), 103 IDTVEC(ioapic_intr37), 104 IDTVEC(ioapic_intr38), 105 IDTVEC(ioapic_intr39), 106 IDTVEC(ioapic_intr40), 107 IDTVEC(ioapic_intr41), 108 IDTVEC(ioapic_intr42), 109 IDTVEC(ioapic_intr43), 110 IDTVEC(ioapic_intr44), 111 IDTVEC(ioapic_intr45), 112 IDTVEC(ioapic_intr46), 113 IDTVEC(ioapic_intr47), 114 IDTVEC(ioapic_intr48), 115 IDTVEC(ioapic_intr49), 116 IDTVEC(ioapic_intr50), 117 IDTVEC(ioapic_intr51), 118 IDTVEC(ioapic_intr52), 119 IDTVEC(ioapic_intr53), 120 IDTVEC(ioapic_intr54), 121 IDTVEC(ioapic_intr55), 122 IDTVEC(ioapic_intr56), 123 IDTVEC(ioapic_intr57), 124 IDTVEC(ioapic_intr58), 125 IDTVEC(ioapic_intr59), 126 IDTVEC(ioapic_intr60), 127 IDTVEC(ioapic_intr61), 128 IDTVEC(ioapic_intr62), 129 IDTVEC(ioapic_intr63), 130 IDTVEC(ioapic_intr64), 131 IDTVEC(ioapic_intr65), 132 IDTVEC(ioapic_intr66), 133 IDTVEC(ioapic_intr67), 134 IDTVEC(ioapic_intr68), 135 IDTVEC(ioapic_intr69), 136 IDTVEC(ioapic_intr70), 137 IDTVEC(ioapic_intr71), 138 IDTVEC(ioapic_intr72), 139 IDTVEC(ioapic_intr73), 140 IDTVEC(ioapic_intr74), 141 IDTVEC(ioapic_intr75), 142 IDTVEC(ioapic_intr76), 143 IDTVEC(ioapic_intr77), 144 IDTVEC(ioapic_intr78), 145 IDTVEC(ioapic_intr79), 146 IDTVEC(ioapic_intr80), 147 IDTVEC(ioapic_intr81), 148 IDTVEC(ioapic_intr82), 149 IDTVEC(ioapic_intr83), 150 IDTVEC(ioapic_intr84), 151 IDTVEC(ioapic_intr85), 152 IDTVEC(ioapic_intr86), 153 IDTVEC(ioapic_intr87), 154 IDTVEC(ioapic_intr88), 155 IDTVEC(ioapic_intr89), 156 IDTVEC(ioapic_intr90), 157 IDTVEC(ioapic_intr91), 158 IDTVEC(ioapic_intr92), 159 IDTVEC(ioapic_intr93), 160 IDTVEC(ioapic_intr94), 161 IDTVEC(ioapic_intr95), 162 IDTVEC(ioapic_intr96), 163 IDTVEC(ioapic_intr97), 164 IDTVEC(ioapic_intr98), 165 IDTVEC(ioapic_intr99), 166 IDTVEC(ioapic_intr100), 167 IDTVEC(ioapic_intr101), 168 IDTVEC(ioapic_intr102), 169 IDTVEC(ioapic_intr103), 170 IDTVEC(ioapic_intr104), 171 IDTVEC(ioapic_intr105), 172 IDTVEC(ioapic_intr106), 173 IDTVEC(ioapic_intr107), 174 IDTVEC(ioapic_intr108), 175 IDTVEC(ioapic_intr109), 176 IDTVEC(ioapic_intr110), 177 IDTVEC(ioapic_intr111), 178 IDTVEC(ioapic_intr112), 179 IDTVEC(ioapic_intr113), 180 IDTVEC(ioapic_intr114), 181 IDTVEC(ioapic_intr115), 182 IDTVEC(ioapic_intr116), 183 IDTVEC(ioapic_intr117), 184 IDTVEC(ioapic_intr118), 185 IDTVEC(ioapic_intr119), 186 IDTVEC(ioapic_intr120), 187 IDTVEC(ioapic_intr121), 188 IDTVEC(ioapic_intr122), 189 IDTVEC(ioapic_intr123), 190 IDTVEC(ioapic_intr124), 191 IDTVEC(ioapic_intr125), 192 IDTVEC(ioapic_intr126), 193 IDTVEC(ioapic_intr127), 194 IDTVEC(ioapic_intr128), 195 IDTVEC(ioapic_intr129), 196 IDTVEC(ioapic_intr130), 197 IDTVEC(ioapic_intr131), 198 IDTVEC(ioapic_intr132), 199 IDTVEC(ioapic_intr133), 200 IDTVEC(ioapic_intr134), 201 IDTVEC(ioapic_intr135), 202 IDTVEC(ioapic_intr136), 203 IDTVEC(ioapic_intr137), 204 IDTVEC(ioapic_intr138), 205 IDTVEC(ioapic_intr139), 206 IDTVEC(ioapic_intr140), 207 IDTVEC(ioapic_intr141), 208 IDTVEC(ioapic_intr142), 209 IDTVEC(ioapic_intr143), 210 IDTVEC(ioapic_intr144), 211 IDTVEC(ioapic_intr145), 212 IDTVEC(ioapic_intr146), 213 IDTVEC(ioapic_intr147), 214 IDTVEC(ioapic_intr148), 215 IDTVEC(ioapic_intr149), 216 IDTVEC(ioapic_intr150), 217 IDTVEC(ioapic_intr151), 218 IDTVEC(ioapic_intr152), 219 IDTVEC(ioapic_intr153), 220 IDTVEC(ioapic_intr154), 221 IDTVEC(ioapic_intr155), 222 IDTVEC(ioapic_intr156), 223 IDTVEC(ioapic_intr157), 224 IDTVEC(ioapic_intr158), 225 IDTVEC(ioapic_intr159), 226 IDTVEC(ioapic_intr160), 227 IDTVEC(ioapic_intr161), 228 IDTVEC(ioapic_intr162), 229 IDTVEC(ioapic_intr163), 230 IDTVEC(ioapic_intr164), 231 IDTVEC(ioapic_intr165), 232 IDTVEC(ioapic_intr166), 233 IDTVEC(ioapic_intr167), 234 IDTVEC(ioapic_intr168), 235 IDTVEC(ioapic_intr169), 236 IDTVEC(ioapic_intr170), 237 IDTVEC(ioapic_intr171), 238 IDTVEC(ioapic_intr172), 239 IDTVEC(ioapic_intr173), 240 IDTVEC(ioapic_intr174), 241 IDTVEC(ioapic_intr175), 242 IDTVEC(ioapic_intr176), 243 IDTVEC(ioapic_intr177), 244 IDTVEC(ioapic_intr178), 245 IDTVEC(ioapic_intr179), 246 IDTVEC(ioapic_intr180), 247 IDTVEC(ioapic_intr181), 248 IDTVEC(ioapic_intr182), 249 IDTVEC(ioapic_intr183), 250 IDTVEC(ioapic_intr184), 251 IDTVEC(ioapic_intr185), 252 IDTVEC(ioapic_intr186), 253 IDTVEC(ioapic_intr187), 254 IDTVEC(ioapic_intr188), 255 IDTVEC(ioapic_intr189), 256 IDTVEC(ioapic_intr190), 257 IDTVEC(ioapic_intr191); 258 259 static inthand_t *ioapic_intr[IOAPIC_HWI_VECTORS] = { 260 &IDTVEC(ioapic_intr0), 261 &IDTVEC(ioapic_intr1), 262 &IDTVEC(ioapic_intr2), 263 &IDTVEC(ioapic_intr3), 264 &IDTVEC(ioapic_intr4), 265 &IDTVEC(ioapic_intr5), 266 &IDTVEC(ioapic_intr6), 267 &IDTVEC(ioapic_intr7), 268 &IDTVEC(ioapic_intr8), 269 &IDTVEC(ioapic_intr9), 270 &IDTVEC(ioapic_intr10), 271 &IDTVEC(ioapic_intr11), 272 &IDTVEC(ioapic_intr12), 273 &IDTVEC(ioapic_intr13), 274 &IDTVEC(ioapic_intr14), 275 &IDTVEC(ioapic_intr15), 276 &IDTVEC(ioapic_intr16), 277 &IDTVEC(ioapic_intr17), 278 &IDTVEC(ioapic_intr18), 279 &IDTVEC(ioapic_intr19), 280 &IDTVEC(ioapic_intr20), 281 &IDTVEC(ioapic_intr21), 282 &IDTVEC(ioapic_intr22), 283 &IDTVEC(ioapic_intr23), 284 &IDTVEC(ioapic_intr24), 285 &IDTVEC(ioapic_intr25), 286 &IDTVEC(ioapic_intr26), 287 &IDTVEC(ioapic_intr27), 288 &IDTVEC(ioapic_intr28), 289 &IDTVEC(ioapic_intr29), 290 &IDTVEC(ioapic_intr30), 291 &IDTVEC(ioapic_intr31), 292 &IDTVEC(ioapic_intr32), 293 &IDTVEC(ioapic_intr33), 294 &IDTVEC(ioapic_intr34), 295 &IDTVEC(ioapic_intr35), 296 &IDTVEC(ioapic_intr36), 297 &IDTVEC(ioapic_intr37), 298 &IDTVEC(ioapic_intr38), 299 &IDTVEC(ioapic_intr39), 300 &IDTVEC(ioapic_intr40), 301 &IDTVEC(ioapic_intr41), 302 &IDTVEC(ioapic_intr42), 303 &IDTVEC(ioapic_intr43), 304 &IDTVEC(ioapic_intr44), 305 &IDTVEC(ioapic_intr45), 306 &IDTVEC(ioapic_intr46), 307 &IDTVEC(ioapic_intr47), 308 &IDTVEC(ioapic_intr48), 309 &IDTVEC(ioapic_intr49), 310 &IDTVEC(ioapic_intr50), 311 &IDTVEC(ioapic_intr51), 312 &IDTVEC(ioapic_intr52), 313 &IDTVEC(ioapic_intr53), 314 &IDTVEC(ioapic_intr54), 315 &IDTVEC(ioapic_intr55), 316 &IDTVEC(ioapic_intr56), 317 &IDTVEC(ioapic_intr57), 318 &IDTVEC(ioapic_intr58), 319 &IDTVEC(ioapic_intr59), 320 &IDTVEC(ioapic_intr60), 321 &IDTVEC(ioapic_intr61), 322 &IDTVEC(ioapic_intr62), 323 &IDTVEC(ioapic_intr63), 324 &IDTVEC(ioapic_intr64), 325 &IDTVEC(ioapic_intr65), 326 &IDTVEC(ioapic_intr66), 327 &IDTVEC(ioapic_intr67), 328 &IDTVEC(ioapic_intr68), 329 &IDTVEC(ioapic_intr69), 330 &IDTVEC(ioapic_intr70), 331 &IDTVEC(ioapic_intr71), 332 &IDTVEC(ioapic_intr72), 333 &IDTVEC(ioapic_intr73), 334 &IDTVEC(ioapic_intr74), 335 &IDTVEC(ioapic_intr75), 336 &IDTVEC(ioapic_intr76), 337 &IDTVEC(ioapic_intr77), 338 &IDTVEC(ioapic_intr78), 339 &IDTVEC(ioapic_intr79), 340 &IDTVEC(ioapic_intr80), 341 &IDTVEC(ioapic_intr81), 342 &IDTVEC(ioapic_intr82), 343 &IDTVEC(ioapic_intr83), 344 &IDTVEC(ioapic_intr84), 345 &IDTVEC(ioapic_intr85), 346 &IDTVEC(ioapic_intr86), 347 &IDTVEC(ioapic_intr87), 348 &IDTVEC(ioapic_intr88), 349 &IDTVEC(ioapic_intr89), 350 &IDTVEC(ioapic_intr90), 351 &IDTVEC(ioapic_intr91), 352 &IDTVEC(ioapic_intr92), 353 &IDTVEC(ioapic_intr93), 354 &IDTVEC(ioapic_intr94), 355 &IDTVEC(ioapic_intr95), 356 &IDTVEC(ioapic_intr96), 357 &IDTVEC(ioapic_intr97), 358 &IDTVEC(ioapic_intr98), 359 &IDTVEC(ioapic_intr99), 360 &IDTVEC(ioapic_intr100), 361 &IDTVEC(ioapic_intr101), 362 &IDTVEC(ioapic_intr102), 363 &IDTVEC(ioapic_intr103), 364 &IDTVEC(ioapic_intr104), 365 &IDTVEC(ioapic_intr105), 366 &IDTVEC(ioapic_intr106), 367 &IDTVEC(ioapic_intr107), 368 &IDTVEC(ioapic_intr108), 369 &IDTVEC(ioapic_intr109), 370 &IDTVEC(ioapic_intr110), 371 &IDTVEC(ioapic_intr111), 372 &IDTVEC(ioapic_intr112), 373 &IDTVEC(ioapic_intr113), 374 &IDTVEC(ioapic_intr114), 375 &IDTVEC(ioapic_intr115), 376 &IDTVEC(ioapic_intr116), 377 &IDTVEC(ioapic_intr117), 378 &IDTVEC(ioapic_intr118), 379 &IDTVEC(ioapic_intr119), 380 &IDTVEC(ioapic_intr120), 381 &IDTVEC(ioapic_intr121), 382 &IDTVEC(ioapic_intr122), 383 &IDTVEC(ioapic_intr123), 384 &IDTVEC(ioapic_intr124), 385 &IDTVEC(ioapic_intr125), 386 &IDTVEC(ioapic_intr126), 387 &IDTVEC(ioapic_intr127), 388 &IDTVEC(ioapic_intr128), 389 &IDTVEC(ioapic_intr129), 390 &IDTVEC(ioapic_intr130), 391 &IDTVEC(ioapic_intr131), 392 &IDTVEC(ioapic_intr132), 393 &IDTVEC(ioapic_intr133), 394 &IDTVEC(ioapic_intr134), 395 &IDTVEC(ioapic_intr135), 396 &IDTVEC(ioapic_intr136), 397 &IDTVEC(ioapic_intr137), 398 &IDTVEC(ioapic_intr138), 399 &IDTVEC(ioapic_intr139), 400 &IDTVEC(ioapic_intr140), 401 &IDTVEC(ioapic_intr141), 402 &IDTVEC(ioapic_intr142), 403 &IDTVEC(ioapic_intr143), 404 &IDTVEC(ioapic_intr144), 405 &IDTVEC(ioapic_intr145), 406 &IDTVEC(ioapic_intr146), 407 &IDTVEC(ioapic_intr147), 408 &IDTVEC(ioapic_intr148), 409 &IDTVEC(ioapic_intr149), 410 &IDTVEC(ioapic_intr150), 411 &IDTVEC(ioapic_intr151), 412 &IDTVEC(ioapic_intr152), 413 &IDTVEC(ioapic_intr153), 414 &IDTVEC(ioapic_intr154), 415 &IDTVEC(ioapic_intr155), 416 &IDTVEC(ioapic_intr156), 417 &IDTVEC(ioapic_intr157), 418 &IDTVEC(ioapic_intr158), 419 &IDTVEC(ioapic_intr159), 420 &IDTVEC(ioapic_intr160), 421 &IDTVEC(ioapic_intr161), 422 &IDTVEC(ioapic_intr162), 423 &IDTVEC(ioapic_intr163), 424 &IDTVEC(ioapic_intr164), 425 &IDTVEC(ioapic_intr165), 426 &IDTVEC(ioapic_intr166), 427 &IDTVEC(ioapic_intr167), 428 &IDTVEC(ioapic_intr168), 429 &IDTVEC(ioapic_intr169), 430 &IDTVEC(ioapic_intr170), 431 &IDTVEC(ioapic_intr171), 432 &IDTVEC(ioapic_intr172), 433 &IDTVEC(ioapic_intr173), 434 &IDTVEC(ioapic_intr174), 435 &IDTVEC(ioapic_intr175), 436 &IDTVEC(ioapic_intr176), 437 &IDTVEC(ioapic_intr177), 438 &IDTVEC(ioapic_intr178), 439 &IDTVEC(ioapic_intr179), 440 &IDTVEC(ioapic_intr180), 441 &IDTVEC(ioapic_intr181), 442 &IDTVEC(ioapic_intr182), 443 &IDTVEC(ioapic_intr183), 444 &IDTVEC(ioapic_intr184), 445 &IDTVEC(ioapic_intr185), 446 &IDTVEC(ioapic_intr186), 447 &IDTVEC(ioapic_intr187), 448 &IDTVEC(ioapic_intr188), 449 &IDTVEC(ioapic_intr189), 450 &IDTVEC(ioapic_intr190), 451 &IDTVEC(ioapic_intr191) 452 }; 453 454 #define IOAPIC_HWI_SYSCALL (IDT_OFFSET_SYSCALL - IDT_OFFSET) 455 456 static struct ioapic_irqmap { 457 int im_type; /* IOAPIC_IMT_ */ 458 enum intr_trigger im_trig; 459 enum intr_polarity im_pola; 460 int im_gsi; 461 uint32_t im_flags; /* IOAPIC_IMF_ */ 462 } ioapic_irqmaps[MAX_HARDINTS]; /* XXX MAX_HARDINTS may not be correct */ 463 464 #define IOAPIC_IMT_UNUSED 0 465 #define IOAPIC_IMT_RESERVED 1 466 #define IOAPIC_IMT_LINE 2 467 #define IOAPIC_IMT_SYSCALL 3 468 469 #define IOAPIC_IMF_CONF 0x1 470 471 extern void IOAPIC_INTREN(int); 472 extern void IOAPIC_INTRDIS(int); 473 474 static int ioapic_setvar(int, const void *); 475 static int ioapic_getvar(int, void *); 476 static int ioapic_vectorctl(int, int, int); 477 static void ioapic_finalize(void); 478 static void ioapic_cleanup(void); 479 static void ioapic_setdefault(void); 480 static void ioapic_stabilize(void); 481 static void ioapic_initmap(void); 482 static void ioapic_intr_config(int, enum intr_trigger, enum intr_polarity); 483 484 struct machintr_abi MachIntrABI_IOAPIC = { 485 MACHINTR_IOAPIC, 486 .intrdis = IOAPIC_INTRDIS, 487 .intren = IOAPIC_INTREN, 488 .vectorctl = ioapic_vectorctl, 489 .setvar = ioapic_setvar, 490 .getvar = ioapic_getvar, 491 .finalize = ioapic_finalize, 492 .cleanup = ioapic_cleanup, 493 .setdefault = ioapic_setdefault, 494 .stabilize = ioapic_stabilize, 495 .initmap = ioapic_initmap, 496 .intr_config = ioapic_intr_config 497 }; 498 499 static int ioapic_abi_extint_irq = -1; 500 501 static int 502 ioapic_setvar(int varid, const void *buf) 503 { 504 return ENOENT; 505 } 506 507 static int 508 ioapic_getvar(int varid, void *buf) 509 { 510 return ENOENT; 511 } 512 513 static void 514 ioapic_finalize(void) 515 { 516 KKASSERT(MachIntrABI.type == MACHINTR_IOAPIC); 517 KKASSERT(apic_io_enable); 518 519 /* 520 * If an IMCR is present, program bit 0 to disconnect the 8259 521 * from the BSP. 522 */ 523 if (imcr_present) { 524 outb(0x22, 0x70); /* select IMCR */ 525 outb(0x23, 0x01); /* disconnect 8259 */ 526 } 527 } 528 529 /* 530 * This routine is called after physical interrupts are enabled but before 531 * the critical section is released. We need to clean out any interrupts 532 * that had already been posted to the cpu. 533 */ 534 static void 535 ioapic_cleanup(void) 536 { 537 bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending)); 538 } 539 540 /* Must never be called */ 541 static void 542 ioapic_stabilize(void) 543 { 544 panic("ioapic_stabilize is called\n"); 545 } 546 547 static int 548 ioapic_vectorctl(int op, int intr, int flags) 549 { 550 int error; 551 int vector; 552 int select; 553 uint32_t value; 554 register_t ef; 555 556 if (intr < 0 || intr >= IOAPIC_HWI_VECTORS || 557 intr == IOAPIC_HWI_SYSCALL) 558 return EINVAL; 559 560 ef = read_rflags(); 561 cpu_disable_intr(); 562 error = 0; 563 564 switch(op) { 565 case MACHINTR_VECTOR_SETUP: 566 vector = IDT_OFFSET + intr; 567 setidt(vector, ioapic_intr[intr], SDT_SYSIGT, SEL_KPL, 0); 568 569 /* 570 * Now reprogram the vector in the IO APIC. In order to avoid 571 * losing an EOI for a level interrupt, which is vector based, 572 * make sure that the IO APIC is programmed for edge-triggering 573 * first, then reprogrammed with the new vector. This should 574 * clear the IRR bit. 575 */ 576 if (int_to_apicintpin[intr].ioapic >= 0) { 577 imen_lock(); 578 579 select = int_to_apicintpin[intr].redirindex; 580 value = ioapic_read(int_to_apicintpin[intr].apic_address, 581 select); 582 value |= IOART_INTMSET; 583 584 ioapic_write(int_to_apicintpin[intr].apic_address, 585 select, (value & ~APIC_TRIGMOD_MASK)); 586 ioapic_write(int_to_apicintpin[intr].apic_address, 587 select, (value & ~IOART_INTVEC) | vector); 588 589 imen_unlock(); 590 } 591 592 machintr_intren(intr); 593 break; 594 595 case MACHINTR_VECTOR_TEARDOWN: 596 /* 597 * Teardown an interrupt vector. The vector should already be 598 * installed in the cpu's IDT, but make sure. 599 */ 600 machintr_intrdis(intr); 601 602 vector = IDT_OFFSET + intr; 603 setidt(vector, ioapic_intr[intr], SDT_SYSIGT, SEL_KPL, 0); 604 605 /* 606 * In order to avoid losing an EOI for a level interrupt, which 607 * is vector based, make sure that the IO APIC is programmed for 608 * edge-triggering first, then reprogrammed with the new vector. 609 * This should clear the IRR bit. 610 */ 611 if (int_to_apicintpin[intr].ioapic >= 0) { 612 imen_lock(); 613 614 select = int_to_apicintpin[intr].redirindex; 615 value = ioapic_read(int_to_apicintpin[intr].apic_address, 616 select); 617 618 ioapic_write(int_to_apicintpin[intr].apic_address, 619 select, (value & ~APIC_TRIGMOD_MASK)); 620 ioapic_write(int_to_apicintpin[intr].apic_address, 621 select, (value & ~IOART_INTVEC) | vector); 622 623 imen_unlock(); 624 } 625 break; 626 627 default: 628 error = EOPNOTSUPP; 629 break; 630 } 631 632 write_rflags(ef); 633 return error; 634 } 635 636 static void 637 ioapic_setdefault(void) 638 { 639 int intr; 640 641 for (intr = 0; intr < IOAPIC_HWI_VECTORS; ++intr) { 642 if (intr == IOAPIC_HWI_SYSCALL) 643 continue; 644 setidt(IDT_OFFSET + intr, ioapic_intr[intr], SDT_SYSIGT, 645 SEL_KPL, 0); 646 } 647 } 648 649 static void 650 ioapic_initmap(void) 651 { 652 int i; 653 654 for (i = 0; i < IOAPIC_HWI_VECTORS; ++i) 655 ioapic_irqmaps[i].im_gsi = -1; 656 ioapic_irqmaps[IOAPIC_HWI_SYSCALL].im_type = IOAPIC_IMT_SYSCALL; 657 } 658 659 void 660 ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig, 661 enum intr_polarity pola) 662 { 663 struct apic_intmapinfo *info; 664 struct ioapic_irqmap *map; 665 void *ioaddr; 666 int pin; 667 668 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 669 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 670 671 KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS); 672 map = &ioapic_irqmaps[irq]; 673 674 KKASSERT(map->im_type == IOAPIC_IMT_UNUSED); 675 map->im_type = IOAPIC_IMT_LINE; 676 677 map->im_gsi = gsi; 678 map->im_trig = trig; 679 map->im_pola = pola; 680 681 if (bootverbose) { 682 kprintf("IOAPIC: irq %d -> gsi %d %s/%s\n", 683 irq, map->im_gsi, 684 intr_str_trigger(map->im_trig), 685 intr_str_polarity(map->im_pola)); 686 } 687 688 pin = ioapic_gsi_pin(map->im_gsi); 689 ioaddr = ioapic_gsi_ioaddr(map->im_gsi); 690 691 info = &int_to_apicintpin[irq]; 692 693 imen_lock(); 694 695 info->ioapic = 0; /* XXX unused */ 696 info->int_pin = pin; 697 info->apic_address = ioaddr; 698 info->redirindex = IOAPIC_REDTBL + (2 * pin); 699 info->flags = IOAPIC_IM_FLAG_MASKED; 700 if (map->im_trig == INTR_TRIGGER_LEVEL) 701 info->flags |= IOAPIC_IM_FLAG_LEVEL; 702 703 ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq, 704 map->im_trig, map->im_pola); 705 706 imen_unlock(); 707 } 708 709 void 710 ioapic_abi_fixup_irqmap(void) 711 { 712 int i; 713 714 for (i = 0; i < 16; ++i) { 715 struct ioapic_irqmap *map = &ioapic_irqmaps[i]; 716 717 if (map->im_type == IOAPIC_IMT_UNUSED) { 718 map->im_type = IOAPIC_IMT_RESERVED; 719 if (bootverbose) 720 kprintf("IOAPIC: irq %d reserved\n", i); 721 } 722 } 723 } 724 725 int 726 ioapic_abi_find_gsi(int gsi, enum intr_trigger trig, enum intr_polarity pola) 727 { 728 int irq; 729 730 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 731 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 732 733 for (irq = 0; irq < IOAPIC_HWI_VECTORS; ++irq) { 734 const struct ioapic_irqmap *map = &ioapic_irqmaps[irq]; 735 736 if (map->im_gsi == gsi) { 737 KKASSERT(map->im_type == IOAPIC_IMT_LINE); 738 739 if (map->im_flags & IOAPIC_IMF_CONF) { 740 if (map->im_trig != trig || 741 map->im_pola != pola) 742 return -1; 743 } 744 return irq; 745 } 746 } 747 return -1; 748 } 749 750 int 751 ioapic_abi_find_irq(int irq, enum intr_trigger trig, enum intr_polarity pola) 752 { 753 const struct ioapic_irqmap *map; 754 755 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 756 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 757 758 if (irq < 0 || irq >= IOAPIC_HWI_VECTORS) 759 return -1; 760 map = &ioapic_irqmaps[irq]; 761 762 if (map->im_type != IOAPIC_IMT_LINE) 763 return -1; 764 765 if (map->im_flags & IOAPIC_IMF_CONF) { 766 if (map->im_trig != trig || map->im_pola != pola) 767 return -1; 768 } 769 return irq; 770 } 771 772 static void 773 ioapic_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola) 774 { 775 struct apic_intmapinfo *info; 776 struct ioapic_irqmap *map; 777 void *ioaddr; 778 int pin; 779 780 KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); 781 KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); 782 783 KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS); 784 map = &ioapic_irqmaps[irq]; 785 786 KKASSERT(map->im_type == IOAPIC_IMT_LINE); 787 788 #ifdef notyet 789 if (map->im_flags & IOAPIC_IMF_CONF) { 790 if (trig != map->im_trig) { 791 panic("ioapic_intr_config: trig %s -> %s\n", 792 intr_str_trigger(map->im_trig), 793 intr_str_trigger(trig)); 794 } 795 if (pola != map->im_pola) { 796 panic("ioapic_intr_config: pola %s -> %s\n", 797 intr_str_polarity(map->im_pola), 798 intr_str_polarity(pola)); 799 } 800 return; 801 } 802 #endif 803 map->im_flags |= IOAPIC_IMF_CONF; 804 805 if (trig == map->im_trig && pola == map->im_pola) 806 return; 807 808 if (bootverbose) { 809 kprintf("IOAPIC: irq %d, gsi %d %s/%s -> %s/%s\n", 810 irq, map->im_gsi, 811 intr_str_trigger(map->im_trig), 812 intr_str_polarity(map->im_pola), 813 intr_str_trigger(trig), 814 intr_str_polarity(pola)); 815 } 816 map->im_trig = trig; 817 map->im_pola = pola; 818 819 pin = ioapic_gsi_pin(map->im_gsi); 820 ioaddr = ioapic_gsi_ioaddr(map->im_gsi); 821 822 info = &int_to_apicintpin[irq]; 823 824 imen_lock(); 825 826 info->flags &= ~IOAPIC_IM_FLAG_LEVEL; 827 if (map->im_trig == INTR_TRIGGER_LEVEL) 828 info->flags |= IOAPIC_IM_FLAG_LEVEL; 829 830 ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq, 831 map->im_trig, map->im_pola); 832 833 imen_unlock(); 834 } 835 836 int 837 ioapic_abi_extint_irqmap(int irq) 838 { 839 struct apic_intmapinfo *info; 840 struct ioapic_irqmap *map; 841 void *ioaddr; 842 int pin, error, vec; 843 844 vec = IDT_OFFSET + irq; 845 846 if (ioapic_abi_extint_irq == irq) 847 return 0; 848 else if (ioapic_abi_extint_irq >= 0) 849 return EEXIST; 850 851 error = icu_ioapic_extint(irq, vec); 852 if (error) 853 return error; 854 855 map = &ioapic_irqmaps[irq]; 856 857 KKASSERT(map->im_type == IOAPIC_IMT_RESERVED || 858 map->im_type == IOAPIC_IMT_LINE); 859 if (map->im_type == IOAPIC_IMT_LINE) { 860 if (map->im_flags & IOAPIC_IMF_CONF) 861 return EEXIST; 862 } 863 ioapic_abi_extint_irq = irq; 864 865 map->im_type = IOAPIC_IMT_LINE; 866 map->im_trig = INTR_TRIGGER_EDGE; 867 map->im_pola = INTR_POLARITY_HIGH; 868 map->im_flags = IOAPIC_IMF_CONF; 869 870 map->im_gsi = ioapic_extpin_gsi(); 871 KKASSERT(map->im_gsi >= 0); 872 873 if (bootverbose) { 874 kprintf("IOAPIC: irq %d -> extint gsi %d %s/%s\n", 875 irq, map->im_gsi, 876 intr_str_trigger(map->im_trig), 877 intr_str_polarity(map->im_pola)); 878 } 879 880 pin = ioapic_gsi_pin(map->im_gsi); 881 ioaddr = ioapic_gsi_ioaddr(map->im_gsi); 882 883 info = &int_to_apicintpin[irq]; 884 885 imen_lock(); 886 887 info->ioapic = 0; /* XXX unused */ 888 info->int_pin = pin; 889 info->apic_address = ioaddr; 890 info->redirindex = IOAPIC_REDTBL + (2 * pin); 891 info->flags = IOAPIC_IM_FLAG_MASKED; 892 893 ioapic_extpin_setup(ioaddr, pin, vec); 894 895 imen_unlock(); 896 897 return 0; 898 } 899 900 #endif /* SMP */ 901