1 /* 2 * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de. 3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. 5 * Distributed under the terms of the MIT License. 6 * 7 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 8 * Distributed under the terms of the NewOS License. 9 */ 10 11 12 #include <cpu.h> 13 #include <int.h> 14 #include <kscheduler.h> 15 #include <ksyscalls.h> 16 #include <smp.h> 17 #include <team.h> 18 #include <thread.h> 19 #include <vm/vm.h> 20 #include <vm/vm_priv.h> 21 22 #include <arch/cpu.h> 23 #include <arch/int.h> 24 #include <arch/smp.h> 25 #include <arch/user_debugger.h> 26 #include <arch/vm.h> 27 28 #include <arch/x86/apic.h> 29 #include <arch/x86/descriptors.h> 30 #include <arch/x86/vm86.h> 31 32 #include "interrupts.h" 33 #include "irq_routing_table.h" 34 35 #include <ACPI.h> 36 #include <AutoDeleter.h> 37 #include <safemode.h> 38 #include <string.h> 39 #include <stdio.h> 40 41 42 //#define TRACE_ARCH_INT 43 #ifdef TRACE_ARCH_INT 44 # define TRACE(x) dprintf x 45 #else 46 # define TRACE(x) ; 47 #endif 48 49 50 // Definitions for the PIC 8259 controller 51 // (this is not a complete list, only what we're actually using) 52 53 #define PIC_MASTER_CONTROL 0x20 54 #define PIC_MASTER_MASK 0x21 55 #define PIC_SLAVE_CONTROL 0xa0 56 #define PIC_SLAVE_MASK 0xa1 57 #define PIC_MASTER_INIT1 PIC_MASTER_CONTROL 58 #define PIC_MASTER_INIT2 PIC_MASTER_MASK 59 #define PIC_MASTER_INIT3 PIC_MASTER_MASK 60 #define PIC_MASTER_INIT4 PIC_MASTER_MASK 61 #define PIC_SLAVE_INIT1 PIC_SLAVE_CONTROL 62 #define PIC_SLAVE_INIT2 PIC_SLAVE_MASK 63 #define PIC_SLAVE_INIT3 PIC_SLAVE_MASK 64 #define PIC_SLAVE_INIT4 PIC_SLAVE_MASK 65 66 // the edge/level trigger control registers 67 #define PIC_MASTER_TRIGGER_MODE 0x4d0 68 #define PIC_SLAVE_TRIGGER_MODE 0x4d1 69 70 #define PIC_INIT1 0x10 71 #define PIC_INIT1_SEND_INIT4 0x01 72 #define PIC_INIT3_IR2_IS_SLAVE 0x04 73 #define PIC_INIT3_SLAVE_ID2 0x02 74 #define PIC_INIT4_x86_MODE 0x01 75 76 #define PIC_CONTROL3 0x08 77 #define PIC_CONTROL3_READ_ISR 0x03 78 #define PIC_CONTROL3_READ_IRR 0x02 79 80 #define PIC_NON_SPECIFIC_EOI 0x20 81 82 #define PIC_SLAVE_INT_BASE 8 83 #define PIC_NUM_INTS 0x0f 84 85 86 // Definitions for a 82093AA IO APIC controller 87 #define IO_APIC_IDENTIFICATION 0x00 88 #define IO_APIC_VERSION 0x01 89 #define IO_APIC_ARBITRATION 0x02 90 #define IO_APIC_REDIRECTION_TABLE 0x10 // entry = base + 2 * index 91 92 // Fields for the version register 93 #define IO_APIC_VERSION_SHIFT 0 94 #define IO_APIC_VERSION_MASK 0xff 95 #define IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT 16 96 #define IO_APIC_MAX_REDIRECTION_ENTRY_MASK 0xff 97 98 // Fields of each redirection table entry 99 #define IO_APIC_DESTINATION_FIELD_SHIFT 56 100 #define IO_APIC_DESTINATION_FIELD_MASK 0x0f 101 #define IO_APIC_INTERRUPT_MASK_SHIFT 16 102 #define IO_APIC_INTERRUPT_MASKED 1 103 #define IO_APIC_INTERRUPT_UNMASKED 0 104 #define IO_APIC_TRIGGER_MODE_SHIFT 15 105 #define IO_APIC_TRIGGER_MODE_EDGE 0 106 #define IO_APIC_TRIGGER_MODE_LEVEL 1 107 #define IO_APIC_REMOTE_IRR_SHIFT 14 108 #define IO_APIC_PIN_POLARITY_SHIFT 13 109 #define IO_APIC_PIN_POLARITY_HIGH_ACTIVE 0 110 #define IO_APIC_PIN_POLARITY_LOW_ACTIVE 1 111 #define IO_APIC_DELIVERY_STATUS_SHIFT 12 112 #define IO_APIC_DELIVERY_STATUS_IDLE 0 113 #define IO_APIC_DELIVERY_STATUS_PENDING 1 114 #define IO_APIC_DESTINATION_MODE_SHIFT 11 115 #define IO_APIC_DESTINATION_MODE_PHYSICAL 0 116 #define IO_APIC_DESTINATION_MODE_LOGICAL 1 117 #define IO_APIC_DELIVERY_MODE_SHIFT 8 118 #define IO_APIC_DELIVERY_MODE_MASK 0x07 119 #define IO_APIC_DELIVERY_MODE_FIXED 0 120 #define IO_APIC_DELIVERY_MODE_LOWEST_PRIO 1 121 #define IO_APIC_DELIVERY_MODE_SMI 2 122 #define IO_APIC_DELIVERY_MODE_NMI 4 123 #define IO_APIC_DELIVERY_MODE_INIT 5 124 #define IO_APIC_DELIVERY_MODE_EXT_INT 7 125 #define IO_APIC_INTERRUPT_VECTOR_SHIFT 0 126 #define IO_APIC_INTERRUPT_VECTOR_MASK 0xff 127 128 typedef struct ioapic_s { 129 volatile uint32 io_register_select; 130 uint32 reserved[3]; 131 volatile uint32 io_window_register; 132 } ioapic; 133 134 static ioapic *sIOAPIC = NULL; 135 static uint32 sIOAPICMaxRedirectionEntry = 23; 136 137 static uint32 sIRQToIOAPICPin[256]; 138 139 typedef struct interrupt_controller_s { 140 const char *name; 141 void (*enable_io_interrupt)(int32 num); 142 void (*disable_io_interrupt)(int32 num); 143 void (*configure_io_interrupt)(int32 num, uint32 config); 144 bool (*is_spurious_interrupt)(int32 num); 145 bool (*end_of_interrupt)(int32 num); 146 } interrupt_controller; 147 148 static const interrupt_controller *sCurrentPIC = NULL; 149 150 static const char *kInterruptNames[] = { 151 /* 0 */ "Divide Error Exception", 152 /* 1 */ "Debug Exception", 153 /* 2 */ "NMI Interrupt", 154 /* 3 */ "Breakpoint Exception", 155 /* 4 */ "Overflow Exception", 156 /* 5 */ "BOUND Range Exceeded Exception", 157 /* 6 */ "Invalid Opcode Exception", 158 /* 7 */ "Device Not Available Exception", 159 /* 8 */ "Double Fault Exception", 160 /* 9 */ "Coprocessor Segment Overrun", 161 /* 10 */ "Invalid TSS Exception", 162 /* 11 */ "Segment Not Present", 163 /* 12 */ "Stack Fault Exception", 164 /* 13 */ "General Protection Exception", 165 /* 14 */ "Page-Fault Exception", 166 /* 15 */ "-", 167 /* 16 */ "x87 FPU Floating-Point Error", 168 /* 17 */ "Alignment Check Exception", 169 /* 18 */ "Machine-Check Exception", 170 /* 19 */ "SIMD Floating-Point Exception", 171 }; 172 static const int kInterruptNameCount = 20; 173 174 #define MAX_ARGS 16 175 176 typedef struct { 177 uint32 a, b; 178 } desc_table; 179 static desc_table* sIDTs[B_MAX_CPU_COUNT]; 180 181 static uint32 sLevelTriggeredInterrupts = 0; 182 // binary mask: 1 level, 0 edge 183 184 // table with functions handling respective interrupts 185 typedef void interrupt_handler_function(struct iframe* frame); 186 #define INTERRUPT_HANDLER_TABLE_SIZE 256 187 interrupt_handler_function* gInterruptHandlerTable[ 188 INTERRUPT_HANDLER_TABLE_SIZE]; 189 190 191 /*! Initializes a descriptor in an IDT. 192 */ 193 static void 194 set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl) 195 { 196 unsigned int gate1; // first byte of gate desc 197 unsigned int gate2; // second byte of gate desc 198 199 gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr); 200 gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8); 201 202 gate_addr->a = gate1; 203 gate_addr->b = gate2; 204 } 205 206 207 /*! Initializes the descriptor for interrupt vector \a n in the IDT of the 208 specified CPU to an interrupt-gate descriptor with the given procedure 209 address. 210 For CPUs other than the boot CPU it must not be called before 211 arch_int_init_post_vm(). 212 */ 213 static void 214 set_interrupt_gate(int32 cpu, int n, void (*addr)()) 215 { 216 set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL); 217 } 218 219 220 /*! Initializes the descriptor for interrupt vector \a n in the IDT of the 221 specified CPU to an trap-gate descriptor with the given procedure address. 222 For CPUs other than the boot CPU it must not be called before 223 arch_int_init_post_vm(). 224 */ 225 static void 226 set_trap_gate(int32 cpu, int n, void (*addr)()) 227 { 228 set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER); 229 } 230 231 232 /*! Initializes the descriptor for interrupt vector \a n in the IDT of CPU 233 \a cpu to a task-gate descripter referring to the TSS segment identified 234 by TSS segment selector \a segment. 235 For CPUs other than the boot CPU it must not be called before 236 arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine). 237 */ 238 void 239 x86_set_task_gate(int32 cpu, int32 n, int32 segment) 240 { 241 sIDTs[cpu][n].a = (segment << 16); 242 sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5 243 } 244 245 246 /*! Returns the virtual IDT address for CPU \a cpu. */ 247 void* 248 x86_get_idt(int32 cpu) 249 { 250 return sIDTs[cpu]; 251 } 252 253 254 // #pragma mark - PIC 255 256 257 /*! Tests if the interrupt in-service register of the responsible 258 PIC is set for interrupts 7 and 15, and if that's not the case, 259 it must assume it's a spurious interrupt. 260 */ 261 static bool 262 pic_is_spurious_interrupt(int32 num) 263 { 264 if (num != 7) 265 return false; 266 267 // Note, detecting spurious interrupts on line 15 obviously doesn't 268 // work correctly - and since those are extremely rare, anyway, we 269 // just ignore them 270 271 out8(PIC_CONTROL3 | PIC_CONTROL3_READ_ISR, PIC_MASTER_CONTROL); 272 int32 isr = in8(PIC_MASTER_CONTROL); 273 out8(PIC_CONTROL3 | PIC_CONTROL3_READ_IRR, PIC_MASTER_CONTROL); 274 275 return (isr & 0x80) == 0; 276 } 277 278 279 /*! Sends a non-specified EOI (end of interrupt) notice to the PIC in 280 question (or both of them). 281 This clears the PIC interrupt in-service bit. 282 */ 283 static bool 284 pic_end_of_interrupt(int32 num) 285 { 286 if (num < 0 || num > PIC_NUM_INTS) 287 return false; 288 289 // PIC 8259 controlled interrupt 290 if (num >= PIC_SLAVE_INT_BASE) 291 out8(PIC_NON_SPECIFIC_EOI, PIC_SLAVE_CONTROL); 292 293 // we always need to acknowledge the master PIC 294 out8(PIC_NON_SPECIFIC_EOI, PIC_MASTER_CONTROL); 295 return true; 296 } 297 298 299 static void 300 pic_enable_io_interrupt(int32 num) 301 { 302 // interrupt is specified "normalized" 303 if (num < 0 || num > PIC_NUM_INTS) 304 return; 305 306 // enable PIC 8259 controlled interrupt 307 308 TRACE(("pic_enable_io_interrupt: irq %ld\n", num)); 309 310 if (num < PIC_SLAVE_INT_BASE) 311 out8(in8(PIC_MASTER_MASK) & ~(1 << num), PIC_MASTER_MASK); 312 else 313 out8(in8(PIC_SLAVE_MASK) & ~(1 << (num - PIC_SLAVE_INT_BASE)), PIC_SLAVE_MASK); 314 } 315 316 317 static void 318 pic_disable_io_interrupt(int32 num) 319 { 320 // interrupt is specified "normalized" 321 // never disable slave pic line IRQ 2 322 if (num < 0 || num > PIC_NUM_INTS || num == 2) 323 return; 324 325 // disable PIC 8259 controlled interrupt 326 327 TRACE(("pic_disable_io_interrupt: irq %ld\n", num)); 328 329 if (num < PIC_SLAVE_INT_BASE) 330 out8(in8(PIC_MASTER_MASK) | (1 << num), PIC_MASTER_MASK); 331 else 332 out8(in8(PIC_SLAVE_MASK) | (1 << (num - PIC_SLAVE_INT_BASE)), PIC_SLAVE_MASK); 333 } 334 335 336 static void 337 pic_configure_io_interrupt(int32 num, uint32 config) 338 { 339 uint8 value; 340 int32 localBit; 341 if (num < 0 || num > PIC_NUM_INTS || num == 2) 342 return; 343 344 TRACE(("pic_configure_io_interrupt: irq %ld; config 0x%08lx\n", num, config)); 345 346 if (num < PIC_SLAVE_INT_BASE) { 347 value = in8(PIC_MASTER_TRIGGER_MODE); 348 localBit = num; 349 } else { 350 value = in8(PIC_SLAVE_TRIGGER_MODE); 351 localBit = num - PIC_SLAVE_INT_BASE; 352 } 353 354 if (config & B_LEVEL_TRIGGERED) 355 value |= 1 << localBit; 356 else 357 value &= ~(1 << localBit); 358 359 if (num < PIC_SLAVE_INT_BASE) 360 out8(value, PIC_MASTER_TRIGGER_MODE); 361 else 362 out8(value, PIC_SLAVE_TRIGGER_MODE); 363 364 sLevelTriggeredInterrupts = in8(PIC_MASTER_TRIGGER_MODE) 365 | (in8(PIC_SLAVE_TRIGGER_MODE) << 8); 366 } 367 368 369 static void 370 pic_init(void) 371 { 372 static interrupt_controller picController = { 373 "8259 PIC", 374 &pic_enable_io_interrupt, 375 &pic_disable_io_interrupt, 376 &pic_configure_io_interrupt, 377 &pic_is_spurious_interrupt, 378 &pic_end_of_interrupt 379 }; 380 381 // Start initialization sequence for the master and slave PICs 382 out8(PIC_INIT1 | PIC_INIT1_SEND_INIT4, PIC_MASTER_INIT1); 383 out8(PIC_INIT1 | PIC_INIT1_SEND_INIT4, PIC_SLAVE_INIT1); 384 385 // Set start of interrupts to 0x20 for master, 0x28 for slave 386 out8(ARCH_INTERRUPT_BASE, PIC_MASTER_INIT2); 387 out8(ARCH_INTERRUPT_BASE + PIC_SLAVE_INT_BASE, PIC_SLAVE_INIT2); 388 389 // Specify cascading through interrupt 2 390 out8(PIC_INIT3_IR2_IS_SLAVE, PIC_MASTER_INIT3); 391 out8(PIC_INIT3_SLAVE_ID2, PIC_SLAVE_INIT3); 392 393 // Set both to operate in 8086 mode 394 out8(PIC_INIT4_x86_MODE, PIC_MASTER_INIT4); 395 out8(PIC_INIT4_x86_MODE, PIC_SLAVE_INIT4); 396 397 out8(0xfb, PIC_MASTER_MASK); // Mask off all interrupts (except slave pic line IRQ 2). 398 out8(0xff, PIC_SLAVE_MASK); // Mask off interrupts on the slave. 399 400 // determine which interrupts are level or edge triggered 401 402 #if 0 403 // should set everything possible to level triggered 404 out8(0xf8, PIC_MASTER_TRIGGER_MODE); 405 out8(0xde, PIC_SLAVE_TRIGGER_MODE); 406 #endif 407 408 sLevelTriggeredInterrupts = in8(PIC_MASTER_TRIGGER_MODE) 409 | (in8(PIC_SLAVE_TRIGGER_MODE) << 8); 410 411 TRACE(("PIC level trigger mode: 0x%08lx\n", sLevelTriggeredInterrupts)); 412 413 // make the pic controller the current one 414 sCurrentPIC = &picController; 415 } 416 417 418 // #pragma mark - I/O APIC 419 420 421 static inline uint32 422 ioapic_read_32(uint8 registerSelect) 423 { 424 sIOAPIC->io_register_select = registerSelect; 425 return sIOAPIC->io_window_register; 426 } 427 428 429 static inline void 430 ioapic_write_32(uint8 registerSelect, uint32 value) 431 { 432 sIOAPIC->io_register_select = registerSelect; 433 sIOAPIC->io_window_register = value; 434 } 435 436 437 static inline uint64 438 ioapic_read_64(uint8 registerSelect) 439 { 440 sIOAPIC->io_register_select = registerSelect + 1; 441 uint64 result = sIOAPIC->io_window_register; 442 result <<= 32; 443 sIOAPIC->io_register_select = registerSelect; 444 result |= sIOAPIC->io_window_register; 445 return result; 446 } 447 448 449 static inline void 450 ioapic_write_64(uint8 registerSelect, uint64 value) 451 { 452 sIOAPIC->io_register_select = registerSelect; 453 sIOAPIC->io_window_register = (uint32)value; 454 sIOAPIC->io_register_select = registerSelect + 1; 455 sIOAPIC->io_window_register = (uint32)(value >> 32); 456 } 457 458 459 static bool 460 ioapic_is_spurious_interrupt(int32 num) 461 { 462 // the spurious interrupt vector is initialized to the max value in smp 463 return num == 0xff - ARCH_INTERRUPT_BASE; 464 } 465 466 467 static bool 468 ioapic_end_of_interrupt(int32 num) 469 { 470 apic_end_of_interrupt(); 471 return true; 472 } 473 474 475 static void 476 ioapic_enable_io_interrupt(int32 num) 477 { 478 int32 pin = sIRQToIOAPICPin[num]; 479 if (pin < 0 || pin > (int32)sIOAPICMaxRedirectionEntry) 480 return; 481 482 TRACE(("ioapic_enable_io_interrupt: IRQ %ld -> pin %ld\n", num, pin)); 483 484 uint64 entry = ioapic_read_64(IO_APIC_REDIRECTION_TABLE + pin * 2); 485 entry &= ~(1 << IO_APIC_INTERRUPT_MASK_SHIFT); 486 entry |= IO_APIC_INTERRUPT_UNMASKED << IO_APIC_INTERRUPT_MASK_SHIFT; 487 ioapic_write_64(IO_APIC_REDIRECTION_TABLE + pin * 2, entry); 488 } 489 490 491 static void 492 ioapic_disable_io_interrupt(int32 num) 493 { 494 int32 pin = sIRQToIOAPICPin[num]; 495 if (pin < 0 || pin > (int32)sIOAPICMaxRedirectionEntry) 496 return; 497 498 TRACE(("ioapic_disable_io_interrupt: IRQ %ld -> pin %ld\n", num, pin)); 499 500 uint64 entry = ioapic_read_64(IO_APIC_REDIRECTION_TABLE + pin * 2); 501 entry &= ~(1 << IO_APIC_INTERRUPT_MASK_SHIFT); 502 entry |= IO_APIC_INTERRUPT_MASKED << IO_APIC_INTERRUPT_MASK_SHIFT; 503 ioapic_write_64(IO_APIC_REDIRECTION_TABLE + pin * 2, entry); 504 } 505 506 507 static void 508 ioapic_configure_io_interrupt(int32 num, uint32 config) 509 { 510 int32 pin = sIRQToIOAPICPin[num]; 511 if (pin < 0 || pin > (int32)sIOAPICMaxRedirectionEntry) 512 return; 513 514 TRACE(("ioapic_configure_io_interrupt: IRQ %ld -> pin %ld; config 0x%08lx\n", 515 num, pin, config)); 516 517 uint64 entry = ioapic_read_64(IO_APIC_REDIRECTION_TABLE + pin * 2); 518 entry &= ~((1 << IO_APIC_TRIGGER_MODE_SHIFT) 519 | (1 << IO_APIC_PIN_POLARITY_SHIFT) 520 | (IO_APIC_INTERRUPT_VECTOR_MASK << IO_APIC_INTERRUPT_VECTOR_SHIFT)); 521 522 if (config & B_LEVEL_TRIGGERED) { 523 entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT); 524 sLevelTriggeredInterrupts |= (1 << num); 525 } else { 526 entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT); 527 sLevelTriggeredInterrupts &= ~(1 << num); 528 } 529 530 if (config & B_LOW_ACTIVE_POLARITY) 531 entry |= (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT); 532 else 533 entry |= (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT); 534 535 entry |= (num + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT; 536 ioapic_write_64(IO_APIC_REDIRECTION_TABLE + pin * 2, entry); 537 } 538 539 540 static void 541 ioapic_map(kernel_args* args) 542 { 543 if (args->arch_args.apic == NULL) { 544 dprintf("no local apic available\n"); 545 return; 546 } 547 548 if (args->arch_args.ioapic == NULL) { 549 dprintf("no ioapic available, not using ioapics for interrupt routing\n"); 550 return; 551 } 552 553 // map in the ioapic 554 sIOAPIC = (ioapic *)args->arch_args.ioapic; 555 if (vm_map_physical_memory(B_SYSTEM_TEAM, "ioapic", (void**)&sIOAPIC, 556 B_EXACT_ADDRESS, B_PAGE_SIZE, 557 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 558 args->arch_args.ioapic_phys, true) < 0) { 559 panic("mapping the ioapic failed"); 560 return; 561 } 562 } 563 564 565 static void 566 ioapic_init(kernel_args* args) 567 { 568 static const interrupt_controller ioapicController = { 569 "82093AA IOAPIC", 570 &ioapic_enable_io_interrupt, 571 &ioapic_disable_io_interrupt, 572 &ioapic_configure_io_interrupt, 573 &ioapic_is_spurious_interrupt, 574 &ioapic_end_of_interrupt 575 }; 576 577 if (sIOAPIC == NULL) 578 return; 579 580 if (!get_safemode_boolean(B_SAFEMODE_DISABLE_IOAPIC, true)) { 581 dprintf("ioapic explicitly disabled, not using ioapics for interrupt " 582 "routing\n"); 583 return; 584 } 585 586 uint32 version = ioapic_read_32(IO_APIC_VERSION); 587 if (version == 0xffffffff) { 588 dprintf("ioapic seems inaccessible, not using it\n"); 589 return; 590 } 591 592 // load acpi module 593 status_t status; 594 acpi_module_info* acpiModule; 595 status = get_module(B_ACPI_MODULE_NAME, (module_info**)&acpiModule); 596 if (status != B_OK) { 597 dprintf("acpi module not available, not configuring ioapic\n"); 598 return; 599 } 600 BPrivate::CObjectDeleter<const char, status_t> 601 acpiModulePutter(B_ACPI_MODULE_NAME, put_module); 602 603 // load pci module 604 pci_module_info* pciModule; 605 status = get_module(B_PCI_MODULE_NAME, (module_info**)&pciModule); 606 if (status != B_OK) { 607 dprintf("could not load pci module, not configuring ioapic\n"); 608 return; 609 } 610 CObjectDeleter<const char, status_t> pciModulePutter(B_PCI_MODULE_NAME, 611 put_module); 612 613 // TODO: here ACPI needs to be used to properly set up the PCI IRQ 614 // routing. 615 616 IRQRoutingTable table; 617 status = read_irq_routing_table(pciModule, acpiModule, &table); 618 if (status != B_OK) { 619 dprintf("reading IRQ routing table failed, no ioapic.\n"); 620 return; 621 } 622 623 sLevelTriggeredInterrupts = 0; 624 sIOAPICMaxRedirectionEntry 625 = ((version >> IO_APIC_MAX_REDIRECTION_ENTRY_SHIFT) 626 & IO_APIC_MAX_REDIRECTION_ENTRY_MASK); 627 628 // use the boot CPU as the target for all interrupts 629 uint64 targetAPIC = args->arch_args.cpu_apic_id[0]; 630 631 // program the interrupt vectors of the ioapic 632 for (uint32 i = 0; i <= sIOAPICMaxRedirectionEntry; i++) { 633 // initialize everything to deliver to the boot CPU in physical mode 634 // and masked until explicitly enabled through enable_io_interrupt() 635 uint64 entry = (targetAPIC << IO_APIC_DESTINATION_FIELD_SHIFT) 636 | (IO_APIC_INTERRUPT_MASKED << IO_APIC_INTERRUPT_MASK_SHIFT) 637 | (IO_APIC_DESTINATION_MODE_PHYSICAL << IO_APIC_DESTINATION_MODE_SHIFT) 638 | ((i + ARCH_INTERRUPT_BASE) << IO_APIC_INTERRUPT_VECTOR_SHIFT); 639 640 if (i == 0) { 641 // make redirection entry 0 into an external interrupt 642 entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT) 643 | (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT) 644 | (IO_APIC_DELIVERY_MODE_EXT_INT << IO_APIC_DELIVERY_MODE_SHIFT); 645 } else if (i < 16) { 646 // make 1-15 ISA interrupts 647 entry |= (IO_APIC_TRIGGER_MODE_EDGE << IO_APIC_TRIGGER_MODE_SHIFT) 648 | (IO_APIC_PIN_POLARITY_HIGH_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT) 649 | (IO_APIC_DELIVERY_MODE_FIXED << IO_APIC_DELIVERY_MODE_SHIFT); 650 } else { 651 // and the rest are PCI interrupts 652 entry |= (IO_APIC_TRIGGER_MODE_LEVEL << IO_APIC_TRIGGER_MODE_SHIFT) 653 | (IO_APIC_PIN_POLARITY_LOW_ACTIVE << IO_APIC_PIN_POLARITY_SHIFT) 654 | (IO_APIC_DELIVERY_MODE_FIXED << IO_APIC_DELIVERY_MODE_SHIFT); 655 sLevelTriggeredInterrupts |= (1 << i); 656 } 657 658 ioapic_write_64(IO_APIC_REDIRECTION_TABLE + 2 * i, entry); 659 } 660 661 // setup default 1:1 mapping 662 for (uint32 i = 0; i < 256; i++) 663 sIRQToIOAPICPin[i] = i; 664 665 // configure apic interrupts assume 1:1 mapping 666 for (int i = 0; i < table.Count(); i++) { 667 irq_routing_entry& entry = table.ElementAt(i); 668 irq_descriptor irqDescriptor; 669 read_current_irq(acpiModule, entry.source, &irqDescriptor); 670 uint32 config = 0; 671 config |= irqDescriptor.polarity; 672 config |= irqDescriptor.interrupt_mode; 673 ioapic_configure_io_interrupt(irqDescriptor.irq, config); 674 } 675 676 // prefer the ioapic over the normal pic 677 dprintf("using ioapic for interrupt routing\n"); 678 sCurrentPIC = &ioapicController; 679 } 680 681 682 // #pragma mark - 683 684 685 void 686 arch_int_enable_io_interrupt(int irq) 687 { 688 sCurrentPIC->enable_io_interrupt(irq); 689 } 690 691 692 void 693 arch_int_disable_io_interrupt(int irq) 694 { 695 sCurrentPIC->disable_io_interrupt(irq); 696 } 697 698 699 void 700 arch_int_configure_io_interrupt(int irq, uint32 config) 701 { 702 sCurrentPIC->configure_io_interrupt(irq, config); 703 } 704 705 706 #undef arch_int_enable_interrupts 707 #undef arch_int_disable_interrupts 708 #undef arch_int_restore_interrupts 709 #undef arch_int_are_interrupts_enabled 710 711 712 void 713 arch_int_enable_interrupts(void) 714 { 715 arch_int_enable_interrupts_inline(); 716 } 717 718 719 int 720 arch_int_disable_interrupts(void) 721 { 722 return arch_int_disable_interrupts_inline(); 723 } 724 725 726 void 727 arch_int_restore_interrupts(int oldState) 728 { 729 arch_int_restore_interrupts_inline(oldState); 730 } 731 732 733 bool 734 arch_int_are_interrupts_enabled(void) 735 { 736 return arch_int_are_interrupts_enabled_inline(); 737 } 738 739 740 static const char * 741 exception_name(int number, char *buffer, int32 bufferSize) 742 { 743 if (number >= 0 && number < kInterruptNameCount) 744 return kInterruptNames[number]; 745 746 snprintf(buffer, bufferSize, "exception %d", number); 747 return buffer; 748 } 749 750 751 static void 752 invalid_exception(struct iframe* frame) 753 { 754 struct thread* thread = thread_get_current_thread(); 755 char name[32]; 756 panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", 757 frame->vector, exception_name(frame->vector, name, sizeof(name)), 758 frame->eip, thread ? thread->id : -1); 759 } 760 761 762 static void 763 fatal_exception(struct iframe *frame) 764 { 765 char name[32]; 766 panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", 767 exception_name(frame->vector, name, sizeof(name)), frame->error_code); 768 } 769 770 771 static void 772 unexpected_exception(struct iframe* frame) 773 { 774 debug_exception_type type; 775 int signal; 776 777 if (IFRAME_IS_VM86(frame)) { 778 x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ? 779 B_OK : B_ERROR); 780 // won't get here 781 } 782 783 switch (frame->vector) { 784 case 0: // Divide Error Exception (#DE) 785 type = B_DIVIDE_ERROR; 786 signal = SIGFPE; 787 break; 788 789 case 4: // Overflow Exception (#OF) 790 type = B_OVERFLOW_EXCEPTION; 791 signal = SIGTRAP; 792 break; 793 794 case 5: // BOUND Range Exceeded Exception (#BR) 795 type = B_BOUNDS_CHECK_EXCEPTION; 796 signal = SIGTRAP; 797 break; 798 799 case 6: // Invalid Opcode Exception (#UD) 800 type = B_INVALID_OPCODE_EXCEPTION; 801 signal = SIGILL; 802 break; 803 804 case 13: // General Protection Exception (#GP) 805 type = B_GENERAL_PROTECTION_FAULT; 806 signal = SIGILL; 807 break; 808 809 case 16: // x87 FPU Floating-Point Error (#MF) 810 type = B_FLOATING_POINT_EXCEPTION; 811 signal = SIGFPE; 812 break; 813 814 case 17: // Alignment Check Exception (#AC) 815 type = B_ALIGNMENT_EXCEPTION; 816 signal = SIGTRAP; 817 break; 818 819 case 19: // SIMD Floating-Point Exception (#XF) 820 type = B_FLOATING_POINT_EXCEPTION; 821 signal = SIGFPE; 822 break; 823 824 default: 825 invalid_exception(frame); 826 return; 827 } 828 829 if (IFRAME_IS_USER(frame)) { 830 struct sigaction action; 831 struct thread* thread = thread_get_current_thread(); 832 833 enable_interrupts(); 834 835 // If the thread has a signal handler for the signal, we simply send it 836 // the signal. Otherwise we notify the user debugger first. 837 if (sigaction(signal, NULL, &action) == 0 838 && action.sa_handler != SIG_DFL 839 && action.sa_handler != SIG_IGN) { 840 send_signal(thread->id, signal); 841 } else if (user_debug_exception_occurred(type, signal)) 842 send_signal(team_get_current_team_id(), signal); 843 } else { 844 char name[32]; 845 panic("Unexpected exception \"%s\" occurred in kernel mode! " 846 "Error code: 0x%lx\n", 847 exception_name(frame->vector, name, sizeof(name)), 848 frame->error_code); 849 } 850 } 851 852 853 void 854 x86_double_fault_exception(struct iframe* frame) 855 { 856 int cpu = x86_double_fault_get_cpu(); 857 858 // The double fault iframe contains no useful information (as 859 // per Intel's architecture spec). Thus we simply save the 860 // information from the (unhandlable) exception which caused the 861 // double in our iframe. This will result even in useful stack 862 // traces. Only problem is that we trust that at least the 863 // TSS is still accessible. 864 struct tss *tss = &gCPU[cpu].arch.tss; 865 866 frame->cs = tss->cs; 867 frame->es = tss->es; 868 frame->ds = tss->ds; 869 frame->fs = tss->fs; 870 frame->gs = tss->gs; 871 frame->eip = tss->eip; 872 frame->ebp = tss->ebp; 873 frame->esp = tss->esp; 874 frame->eax = tss->eax; 875 frame->ebx = tss->ebx; 876 frame->ecx = tss->ecx; 877 frame->edx = tss->edx; 878 frame->esi = tss->esi; 879 frame->edi = tss->edi; 880 frame->flags = tss->eflags; 881 882 // Use a special handler for page faults which avoids the triple fault 883 // pitfalls. 884 set_interrupt_gate(cpu, 14, &trap14_double_fault); 885 886 debug_double_fault(cpu); 887 } 888 889 890 void 891 x86_page_fault_exception_double_fault(struct iframe* frame) 892 { 893 uint32 cr2; 894 asm("movl %%cr2, %0" : "=r" (cr2)); 895 896 // Only if this CPU has a fault handler, we're allowed to be here. 897 cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; 898 addr_t faultHandler = cpu.fault_handler; 899 if (faultHandler != 0) { 900 debug_set_page_fault_info(cr2, frame->eip, 901 (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); 902 frame->eip = faultHandler; 903 frame->ebp = cpu.fault_handler_stack_pointer; 904 return; 905 } 906 907 // No fault handler. This is bad. Since we originally came from a double 908 // fault, we don't try to reenter the kernel debugger. Instead we just 909 // print the info we've got and enter an infinite loop. 910 kprintf("Page fault in double fault debugger without fault handler! " 911 "Touching address %p from eip %p. Entering infinite loop...\n", 912 (void*)cr2, (void*)frame->eip); 913 914 while (true); 915 } 916 917 918 static void 919 page_fault_exception(struct iframe* frame) 920 { 921 struct thread *thread = thread_get_current_thread(); 922 uint32 cr2; 923 addr_t newip; 924 925 asm("movl %%cr2, %0" : "=r" (cr2)); 926 927 if (debug_debugger_running()) { 928 // If this CPU or this thread has a fault handler, we're allowed to be 929 // here. 930 if (thread != NULL) { 931 cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; 932 if (cpu->fault_handler != 0) { 933 debug_set_page_fault_info(cr2, frame->eip, 934 (frame->error_code & 0x2) != 0 935 ? DEBUG_PAGE_FAULT_WRITE : 0); 936 frame->eip = cpu->fault_handler; 937 frame->ebp = cpu->fault_handler_stack_pointer; 938 return; 939 } 940 941 if (thread->fault_handler != 0) { 942 kprintf("ERROR: thread::fault_handler used in kernel " 943 "debugger!\n"); 944 debug_set_page_fault_info(cr2, frame->eip, 945 (frame->error_code & 0x2) != 0 946 ? DEBUG_PAGE_FAULT_WRITE : 0); 947 frame->eip = thread->fault_handler; 948 return; 949 } 950 } 951 952 // otherwise, not really 953 panic("page fault in debugger without fault handler! Touching " 954 "address %p from eip %p\n", (void *)cr2, (void *)frame->eip); 955 return; 956 } else if ((frame->flags & 0x200) == 0) { 957 // interrupts disabled 958 959 // If a page fault handler is installed, we're allowed to be here. 960 // TODO: Now we are generally allowing user_memcpy() with interrupts 961 // disabled, which in most cases is a bug. We should add some thread 962 // flag allowing to explicitly indicate that this handling is desired. 963 if (thread && thread->fault_handler != 0) { 964 if (frame->eip != thread->fault_handler) { 965 frame->eip = thread->fault_handler; 966 return; 967 } 968 969 // The fault happened at the fault handler address. This is a 970 // certain infinite loop. 971 panic("page fault, interrupts disabled, fault handler loop. " 972 "Touching address %p from eip %p\n", (void*)cr2, 973 (void*)frame->eip); 974 } 975 976 // If we are not running the kernel startup the page fault was not 977 // allowed to happen and we must panic. 978 panic("page fault, but interrupts were disabled. Touching address " 979 "%p from eip %p\n", (void *)cr2, (void *)frame->eip); 980 return; 981 } else if (thread != NULL && thread->page_faults_allowed < 1) { 982 panic("page fault not allowed at this place. Touching address " 983 "%p from eip %p\n", (void *)cr2, (void *)frame->eip); 984 return; 985 } 986 987 enable_interrupts(); 988 989 vm_page_fault(cr2, frame->eip, 990 (frame->error_code & 0x2) != 0, // write access 991 (frame->error_code & 0x4) != 0, // userland 992 &newip); 993 if (newip != 0) { 994 // the page fault handler wants us to modify the iframe to set the 995 // IP the cpu will return to to be this ip 996 frame->eip = newip; 997 } 998 } 999 1000 1001 static void 1002 hardware_interrupt(struct iframe* frame) 1003 { 1004 int32 vector = frame->vector - ARCH_INTERRUPT_BASE; 1005 bool levelTriggered = false; 1006 struct thread* thread = thread_get_current_thread(); 1007 1008 if (sCurrentPIC->is_spurious_interrupt(vector)) { 1009 TRACE(("got spurious interrupt at vector %ld\n", vector)); 1010 return; 1011 } 1012 1013 if (vector < 32) 1014 levelTriggered = (sLevelTriggeredInterrupts & (1 << vector)) != 0; 1015 1016 if (!levelTriggered) { 1017 // if it's not handled by the current pic then it's an apic generated 1018 // interrupt like local interrupts, msi or ipi. 1019 if (!sCurrentPIC->end_of_interrupt(vector)) 1020 apic_end_of_interrupt(); 1021 } 1022 1023 int_io_interrupt_handler(vector, levelTriggered); 1024 1025 if (levelTriggered) { 1026 if (!sCurrentPIC->end_of_interrupt(vector)) 1027 apic_end_of_interrupt(); 1028 } 1029 1030 cpu_status state = disable_interrupts(); 1031 if (thread->cpu->invoke_scheduler) { 1032 GRAB_THREAD_LOCK(); 1033 scheduler_reschedule(); 1034 RELEASE_THREAD_LOCK(); 1035 restore_interrupts(state); 1036 } else if (thread->post_interrupt_callback != NULL) { 1037 restore_interrupts(state); 1038 void (*callback)(void*) = thread->post_interrupt_callback; 1039 void* data = thread->post_interrupt_data; 1040 1041 thread->post_interrupt_callback = NULL; 1042 thread->post_interrupt_data = NULL; 1043 1044 callback(data); 1045 } 1046 } 1047 1048 1049 status_t 1050 arch_int_init(struct kernel_args *args) 1051 { 1052 int i; 1053 interrupt_handler_function** table; 1054 1055 // set the global sIDT variable 1056 sIDTs[0] = (desc_table *)args->arch_args.vir_idt; 1057 1058 // setup the standard programmable interrupt controller 1059 pic_init(); 1060 1061 set_interrupt_gate(0, 0, &trap0); 1062 set_interrupt_gate(0, 1, &trap1); 1063 set_interrupt_gate(0, 2, &trap2); 1064 set_trap_gate(0, 3, &trap3); 1065 set_interrupt_gate(0, 4, &trap4); 1066 set_interrupt_gate(0, 5, &trap5); 1067 set_interrupt_gate(0, 6, &trap6); 1068 set_interrupt_gate(0, 7, &trap7); 1069 // trap8 (double fault) is set in arch_cpu.c 1070 set_interrupt_gate(0, 9, &trap9); 1071 set_interrupt_gate(0, 10, &trap10); 1072 set_interrupt_gate(0, 11, &trap11); 1073 set_interrupt_gate(0, 12, &trap12); 1074 set_interrupt_gate(0, 13, &trap13); 1075 set_interrupt_gate(0, 14, &trap14); 1076 // set_interrupt_gate(0, 15, &trap15); 1077 set_interrupt_gate(0, 16, &trap16); 1078 set_interrupt_gate(0, 17, &trap17); 1079 set_interrupt_gate(0, 18, &trap18); 1080 set_interrupt_gate(0, 19, &trap19); 1081 1082 // legacy or ioapic interrupts 1083 set_interrupt_gate(0, 32, &trap32); 1084 set_interrupt_gate(0, 33, &trap33); 1085 set_interrupt_gate(0, 34, &trap34); 1086 set_interrupt_gate(0, 35, &trap35); 1087 set_interrupt_gate(0, 36, &trap36); 1088 set_interrupt_gate(0, 37, &trap37); 1089 set_interrupt_gate(0, 38, &trap38); 1090 set_interrupt_gate(0, 39, &trap39); 1091 set_interrupt_gate(0, 40, &trap40); 1092 set_interrupt_gate(0, 41, &trap41); 1093 set_interrupt_gate(0, 42, &trap42); 1094 set_interrupt_gate(0, 43, &trap43); 1095 set_interrupt_gate(0, 44, &trap44); 1096 set_interrupt_gate(0, 45, &trap45); 1097 set_interrupt_gate(0, 46, &trap46); 1098 set_interrupt_gate(0, 47, &trap47); 1099 1100 // additional ioapic interrupts 1101 set_interrupt_gate(0, 48, &trap48); 1102 set_interrupt_gate(0, 49, &trap49); 1103 set_interrupt_gate(0, 50, &trap50); 1104 set_interrupt_gate(0, 51, &trap51); 1105 set_interrupt_gate(0, 52, &trap52); 1106 set_interrupt_gate(0, 53, &trap53); 1107 set_interrupt_gate(0, 54, &trap54); 1108 set_interrupt_gate(0, 55, &trap55); 1109 1110 // configurable msi or msi-x interrupts 1111 set_interrupt_gate(0, 56, &trap56); 1112 set_interrupt_gate(0, 57, &trap57); 1113 set_interrupt_gate(0, 58, &trap58); 1114 set_interrupt_gate(0, 59, &trap59); 1115 set_interrupt_gate(0, 60, &trap60); 1116 set_interrupt_gate(0, 61, &trap61); 1117 set_interrupt_gate(0, 62, &trap62); 1118 set_interrupt_gate(0, 63, &trap63); 1119 set_interrupt_gate(0, 64, &trap64); 1120 set_interrupt_gate(0, 65, &trap65); 1121 set_interrupt_gate(0, 66, &trap66); 1122 set_interrupt_gate(0, 67, &trap67); 1123 set_interrupt_gate(0, 68, &trap68); 1124 set_interrupt_gate(0, 69, &trap69); 1125 set_interrupt_gate(0, 70, &trap70); 1126 set_interrupt_gate(0, 71, &trap71); 1127 set_interrupt_gate(0, 72, &trap72); 1128 set_interrupt_gate(0, 73, &trap73); 1129 set_interrupt_gate(0, 74, &trap74); 1130 set_interrupt_gate(0, 75, &trap75); 1131 set_interrupt_gate(0, 76, &trap76); 1132 set_interrupt_gate(0, 77, &trap77); 1133 set_interrupt_gate(0, 78, &trap78); 1134 set_interrupt_gate(0, 79, &trap79); 1135 set_interrupt_gate(0, 80, &trap80); 1136 set_interrupt_gate(0, 81, &trap81); 1137 set_interrupt_gate(0, 82, &trap82); 1138 set_interrupt_gate(0, 83, &trap83); 1139 set_interrupt_gate(0, 84, &trap84); 1140 set_interrupt_gate(0, 85, &trap85); 1141 set_interrupt_gate(0, 86, &trap86); 1142 set_interrupt_gate(0, 87, &trap87); 1143 set_interrupt_gate(0, 88, &trap88); 1144 set_interrupt_gate(0, 89, &trap89); 1145 set_interrupt_gate(0, 90, &trap90); 1146 set_interrupt_gate(0, 91, &trap91); 1147 set_interrupt_gate(0, 92, &trap92); 1148 set_interrupt_gate(0, 93, &trap93); 1149 set_interrupt_gate(0, 94, &trap94); 1150 set_interrupt_gate(0, 95, &trap95); 1151 set_interrupt_gate(0, 96, &trap96); 1152 set_interrupt_gate(0, 97, &trap97); 1153 1154 set_trap_gate(0, 98, &trap98); // for performance testing only 1155 set_trap_gate(0, 99, &trap99); // syscall interrupt 1156 1157 // configurable msi or msi-x interrupts 1158 set_interrupt_gate(0, 100, &trap100); 1159 set_interrupt_gate(0, 101, &trap101); 1160 set_interrupt_gate(0, 102, &trap102); 1161 set_interrupt_gate(0, 103, &trap103); 1162 set_interrupt_gate(0, 104, &trap104); 1163 set_interrupt_gate(0, 105, &trap105); 1164 set_interrupt_gate(0, 106, &trap106); 1165 set_interrupt_gate(0, 107, &trap107); 1166 set_interrupt_gate(0, 108, &trap108); 1167 set_interrupt_gate(0, 109, &trap109); 1168 set_interrupt_gate(0, 110, &trap110); 1169 set_interrupt_gate(0, 111, &trap111); 1170 set_interrupt_gate(0, 112, &trap112); 1171 set_interrupt_gate(0, 113, &trap113); 1172 set_interrupt_gate(0, 114, &trap114); 1173 set_interrupt_gate(0, 115, &trap115); 1174 set_interrupt_gate(0, 116, &trap116); 1175 set_interrupt_gate(0, 117, &trap117); 1176 set_interrupt_gate(0, 118, &trap118); 1177 set_interrupt_gate(0, 119, &trap119); 1178 set_interrupt_gate(0, 120, &trap120); 1179 set_interrupt_gate(0, 121, &trap121); 1180 set_interrupt_gate(0, 122, &trap122); 1181 set_interrupt_gate(0, 123, &trap123); 1182 set_interrupt_gate(0, 124, &trap124); 1183 set_interrupt_gate(0, 125, &trap125); 1184 set_interrupt_gate(0, 126, &trap126); 1185 set_interrupt_gate(0, 127, &trap127); 1186 set_interrupt_gate(0, 128, &trap128); 1187 set_interrupt_gate(0, 129, &trap129); 1188 set_interrupt_gate(0, 130, &trap130); 1189 set_interrupt_gate(0, 131, &trap131); 1190 set_interrupt_gate(0, 132, &trap132); 1191 set_interrupt_gate(0, 133, &trap133); 1192 set_interrupt_gate(0, 134, &trap134); 1193 set_interrupt_gate(0, 135, &trap135); 1194 set_interrupt_gate(0, 136, &trap136); 1195 set_interrupt_gate(0, 137, &trap137); 1196 set_interrupt_gate(0, 138, &trap138); 1197 set_interrupt_gate(0, 139, &trap139); 1198 set_interrupt_gate(0, 140, &trap140); 1199 set_interrupt_gate(0, 141, &trap141); 1200 set_interrupt_gate(0, 142, &trap142); 1201 set_interrupt_gate(0, 143, &trap143); 1202 set_interrupt_gate(0, 144, &trap144); 1203 set_interrupt_gate(0, 145, &trap145); 1204 set_interrupt_gate(0, 146, &trap146); 1205 set_interrupt_gate(0, 147, &trap147); 1206 set_interrupt_gate(0, 148, &trap148); 1207 set_interrupt_gate(0, 149, &trap149); 1208 set_interrupt_gate(0, 150, &trap150); 1209 set_interrupt_gate(0, 151, &trap151); 1210 set_interrupt_gate(0, 152, &trap152); 1211 set_interrupt_gate(0, 153, &trap153); 1212 set_interrupt_gate(0, 154, &trap154); 1213 set_interrupt_gate(0, 155, &trap155); 1214 set_interrupt_gate(0, 156, &trap156); 1215 set_interrupt_gate(0, 157, &trap157); 1216 set_interrupt_gate(0, 158, &trap158); 1217 set_interrupt_gate(0, 159, &trap159); 1218 set_interrupt_gate(0, 160, &trap160); 1219 set_interrupt_gate(0, 161, &trap161); 1220 set_interrupt_gate(0, 162, &trap162); 1221 set_interrupt_gate(0, 163, &trap163); 1222 set_interrupt_gate(0, 164, &trap164); 1223 set_interrupt_gate(0, 165, &trap165); 1224 set_interrupt_gate(0, 166, &trap166); 1225 set_interrupt_gate(0, 167, &trap167); 1226 set_interrupt_gate(0, 168, &trap168); 1227 set_interrupt_gate(0, 169, &trap169); 1228 set_interrupt_gate(0, 170, &trap170); 1229 set_interrupt_gate(0, 171, &trap171); 1230 set_interrupt_gate(0, 172, &trap172); 1231 set_interrupt_gate(0, 173, &trap173); 1232 set_interrupt_gate(0, 174, &trap174); 1233 set_interrupt_gate(0, 175, &trap175); 1234 set_interrupt_gate(0, 176, &trap176); 1235 set_interrupt_gate(0, 177, &trap177); 1236 set_interrupt_gate(0, 178, &trap178); 1237 set_interrupt_gate(0, 179, &trap179); 1238 set_interrupt_gate(0, 180, &trap180); 1239 set_interrupt_gate(0, 181, &trap181); 1240 set_interrupt_gate(0, 182, &trap182); 1241 set_interrupt_gate(0, 183, &trap183); 1242 set_interrupt_gate(0, 184, &trap184); 1243 set_interrupt_gate(0, 185, &trap185); 1244 set_interrupt_gate(0, 186, &trap186); 1245 set_interrupt_gate(0, 187, &trap187); 1246 set_interrupt_gate(0, 188, &trap188); 1247 set_interrupt_gate(0, 189, &trap189); 1248 set_interrupt_gate(0, 190, &trap190); 1249 set_interrupt_gate(0, 191, &trap191); 1250 set_interrupt_gate(0, 192, &trap192); 1251 set_interrupt_gate(0, 193, &trap193); 1252 set_interrupt_gate(0, 194, &trap194); 1253 set_interrupt_gate(0, 195, &trap195); 1254 set_interrupt_gate(0, 196, &trap196); 1255 set_interrupt_gate(0, 197, &trap197); 1256 set_interrupt_gate(0, 198, &trap198); 1257 set_interrupt_gate(0, 199, &trap199); 1258 set_interrupt_gate(0, 200, &trap200); 1259 set_interrupt_gate(0, 201, &trap201); 1260 set_interrupt_gate(0, 202, &trap202); 1261 set_interrupt_gate(0, 203, &trap203); 1262 set_interrupt_gate(0, 204, &trap204); 1263 set_interrupt_gate(0, 205, &trap205); 1264 set_interrupt_gate(0, 206, &trap206); 1265 set_interrupt_gate(0, 207, &trap207); 1266 set_interrupt_gate(0, 208, &trap208); 1267 set_interrupt_gate(0, 209, &trap209); 1268 set_interrupt_gate(0, 210, &trap210); 1269 set_interrupt_gate(0, 211, &trap211); 1270 set_interrupt_gate(0, 212, &trap212); 1271 set_interrupt_gate(0, 213, &trap213); 1272 set_interrupt_gate(0, 214, &trap214); 1273 set_interrupt_gate(0, 215, &trap215); 1274 set_interrupt_gate(0, 216, &trap216); 1275 set_interrupt_gate(0, 217, &trap217); 1276 set_interrupt_gate(0, 218, &trap218); 1277 set_interrupt_gate(0, 219, &trap219); 1278 set_interrupt_gate(0, 220, &trap220); 1279 set_interrupt_gate(0, 221, &trap221); 1280 set_interrupt_gate(0, 222, &trap222); 1281 set_interrupt_gate(0, 223, &trap223); 1282 set_interrupt_gate(0, 224, &trap224); 1283 set_interrupt_gate(0, 225, &trap225); 1284 set_interrupt_gate(0, 226, &trap226); 1285 set_interrupt_gate(0, 227, &trap227); 1286 set_interrupt_gate(0, 228, &trap228); 1287 set_interrupt_gate(0, 229, &trap229); 1288 set_interrupt_gate(0, 230, &trap230); 1289 set_interrupt_gate(0, 231, &trap231); 1290 set_interrupt_gate(0, 232, &trap232); 1291 set_interrupt_gate(0, 233, &trap233); 1292 set_interrupt_gate(0, 234, &trap234); 1293 set_interrupt_gate(0, 235, &trap235); 1294 set_interrupt_gate(0, 236, &trap236); 1295 set_interrupt_gate(0, 237, &trap237); 1296 set_interrupt_gate(0, 238, &trap238); 1297 set_interrupt_gate(0, 239, &trap239); 1298 set_interrupt_gate(0, 240, &trap240); 1299 set_interrupt_gate(0, 241, &trap241); 1300 set_interrupt_gate(0, 242, &trap242); 1301 set_interrupt_gate(0, 243, &trap243); 1302 set_interrupt_gate(0, 244, &trap244); 1303 set_interrupt_gate(0, 245, &trap245); 1304 set_interrupt_gate(0, 246, &trap246); 1305 set_interrupt_gate(0, 247, &trap247); 1306 set_interrupt_gate(0, 248, &trap248); 1307 set_interrupt_gate(0, 249, &trap249); 1308 set_interrupt_gate(0, 250, &trap250); 1309 1310 // smp / apic local interrupts 1311 set_interrupt_gate(0, 251, &trap251); 1312 set_interrupt_gate(0, 252, &trap252); 1313 set_interrupt_gate(0, 253, &trap253); 1314 set_interrupt_gate(0, 254, &trap254); 1315 set_interrupt_gate(0, 255, &trap255); 1316 1317 // init interrupt handler table 1318 table = gInterruptHandlerTable; 1319 1320 // defaults 1321 for (i = 0; i < ARCH_INTERRUPT_BASE; i++) 1322 table[i] = invalid_exception; 1323 for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) 1324 table[i] = hardware_interrupt; 1325 1326 table[0] = unexpected_exception; // Divide Error Exception (#DE) 1327 table[1] = x86_handle_debug_exception; // Debug Exception (#DB) 1328 table[2] = fatal_exception; // NMI Interrupt 1329 table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) 1330 table[4] = unexpected_exception; // Overflow Exception (#OF) 1331 table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) 1332 table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) 1333 table[7] = fatal_exception; // Device Not Available Exception (#NM) 1334 table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) 1335 table[9] = fatal_exception; // Coprocessor Segment Overrun 1336 table[10] = fatal_exception; // Invalid TSS Exception (#TS) 1337 table[11] = fatal_exception; // Segment Not Present (#NP) 1338 table[12] = fatal_exception; // Stack Fault Exception (#SS) 1339 table[13] = unexpected_exception; // General Protection Exception (#GP) 1340 table[14] = page_fault_exception; // Page-Fault Exception (#PF) 1341 table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) 1342 table[17] = unexpected_exception; // Alignment Check Exception (#AC) 1343 table[18] = fatal_exception; // Machine-Check Exception (#MC) 1344 table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) 1345 1346 return B_OK; 1347 } 1348 1349 1350 status_t 1351 arch_int_init_post_vm(struct kernel_args *args) 1352 { 1353 // Always init the local apic as it can be used for timers even if we 1354 // don't end up using the io apic 1355 apic_init(args); 1356 1357 // We need to map in the I/O APIC here, since we would lose the already 1358 // wired mapping before arch_int_init_io() is called. 1359 ioapic_map(args); 1360 1361 // create IDT area for the boot CPU 1362 area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS, 1363 B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 1364 if (area < 0) 1365 return area; 1366 1367 // create IDTs for the off-boot CPU 1368 size_t idtSize = 256 * 8; 1369 // 256 8 bytes-sized descriptors 1370 int32 cpuCount = smp_get_num_cpus(); 1371 if (cpuCount > 0) { 1372 size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE); 1373 desc_table* idt; 1374 area = create_area_etc(B_SYSTEM_TEAM, "idt", (void**)&idt, 1375 B_ANY_KERNEL_ADDRESS, areaSize, B_CONTIGUOUS, 1376 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0, CREATE_AREA_DONT_WAIT); 1377 if (area < 0) 1378 return area; 1379 1380 for (int32 i = 1; i < cpuCount; i++) { 1381 sIDTs[i] = idt; 1382 memcpy(idt, sIDTs[0], idtSize); 1383 idt += 256; 1384 // The CPU's IDTR will be set in arch_cpu_init_percpu(). 1385 } 1386 } 1387 1388 return area >= B_OK ? B_OK : area; 1389 } 1390 1391 1392 status_t 1393 arch_int_init_io(kernel_args* args) 1394 { 1395 ioapic_init(args); 1396 return B_OK; 1397 } 1398 1399 1400 status_t 1401 arch_int_init_post_device_manager(struct kernel_args *args) 1402 { 1403 return B_OK; 1404 } 1405