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