1 /* 2 * Copyright 2008-2011, Michael Lotz, mmlr@mlotz.ch. 3 * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de. 4 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 5 * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. 6 * Distributed under the terms of the MIT License. 7 * 8 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 9 * Distributed under the terms of the NewOS License. 10 */ 11 12 13 #include <cpu.h> 14 #include <int.h> 15 #include <kscheduler.h> 16 #include <ksyscalls.h> 17 #include <smp.h> 18 #include <team.h> 19 #include <thread.h> 20 #include <util/AutoLock.h> 21 #include <vm/vm.h> 22 #include <vm/vm_priv.h> 23 24 #include <arch/cpu.h> 25 #include <arch/int.h> 26 #include <arch/smp.h> 27 #include <arch/user_debugger.h> 28 #include <arch/vm.h> 29 30 #include <arch/x86/apic.h> 31 #include <arch/x86/descriptors.h> 32 #include <arch/x86/msi.h> 33 #include <arch/x86/vm86.h> 34 35 #include "interrupts.h" 36 37 #include <stdio.h> 38 39 // interrupt controllers 40 #include <arch/x86/ioapic.h> 41 #include <arch/x86/pic.h> 42 43 44 //#define TRACE_ARCH_INT 45 #ifdef TRACE_ARCH_INT 46 # define TRACE(x) dprintf x 47 #else 48 # define TRACE(x) ; 49 #endif 50 51 52 static const interrupt_controller *sCurrentPIC = NULL; 53 54 static const char *kInterruptNames[] = { 55 /* 0 */ "Divide Error Exception", 56 /* 1 */ "Debug Exception", 57 /* 2 */ "NMI Interrupt", 58 /* 3 */ "Breakpoint Exception", 59 /* 4 */ "Overflow Exception", 60 /* 5 */ "BOUND Range Exceeded Exception", 61 /* 6 */ "Invalid Opcode Exception", 62 /* 7 */ "Device Not Available Exception", 63 /* 8 */ "Double Fault Exception", 64 /* 9 */ "Coprocessor Segment Overrun", 65 /* 10 */ "Invalid TSS Exception", 66 /* 11 */ "Segment Not Present", 67 /* 12 */ "Stack Fault Exception", 68 /* 13 */ "General Protection Exception", 69 /* 14 */ "Page-Fault Exception", 70 /* 15 */ "-", 71 /* 16 */ "x87 FPU Floating-Point Error", 72 /* 17 */ "Alignment Check Exception", 73 /* 18 */ "Machine-Check Exception", 74 /* 19 */ "SIMD Floating-Point Exception", 75 }; 76 static const int kInterruptNameCount = 20; 77 78 #define MAX_ARGS 16 79 80 typedef struct { 81 uint32 a, b; 82 } desc_table; 83 static desc_table* sIDTs[B_MAX_CPU_COUNT]; 84 85 // table with functions handling respective interrupts 86 typedef void interrupt_handler_function(struct iframe* frame); 87 88 #define INTERRUPT_HANDLER_TABLE_SIZE 256 89 interrupt_handler_function* gInterruptHandlerTable[ 90 INTERRUPT_HANDLER_TABLE_SIZE]; 91 92 93 /*! Initializes a descriptor in an IDT. 94 */ 95 static void 96 set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl) 97 { 98 unsigned int gate1; // first byte of gate desc 99 unsigned int gate2; // second byte of gate desc 100 101 gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr); 102 gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8); 103 104 gate_addr->a = gate1; 105 gate_addr->b = gate2; 106 } 107 108 109 /*! Initializes the descriptor for interrupt vector \a n in the IDT of the 110 specified CPU to an interrupt-gate descriptor with the given procedure 111 address. 112 For CPUs other than the boot CPU it must not be called before 113 arch_int_init_post_vm(). 114 */ 115 static void 116 set_interrupt_gate(int32 cpu, int n, void (*addr)()) 117 { 118 set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL); 119 } 120 121 122 /*! Initializes the descriptor for interrupt vector \a n in the IDT of the 123 specified CPU to an trap-gate descriptor with the given procedure address. 124 For CPUs other than the boot CPU it must not be called before 125 arch_int_init_post_vm(). 126 */ 127 static void 128 set_trap_gate(int32 cpu, int n, void (*addr)()) 129 { 130 set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER); 131 } 132 133 134 /*! Initializes the descriptor for interrupt vector \a n in the IDT of CPU 135 \a cpu to a task-gate descripter referring to the TSS segment identified 136 by TSS segment selector \a segment. 137 For CPUs other than the boot CPU it must not be called before 138 arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine). 139 */ 140 void 141 x86_set_task_gate(int32 cpu, int32 n, int32 segment) 142 { 143 sIDTs[cpu][n].a = (segment << 16); 144 sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5 145 } 146 147 148 /*! Returns the virtual IDT address for CPU \a cpu. */ 149 void* 150 x86_get_idt(int32 cpu) 151 { 152 return sIDTs[cpu]; 153 } 154 155 156 // #pragma mark - 157 158 159 void 160 arch_int_enable_io_interrupt(int irq) 161 { 162 sCurrentPIC->enable_io_interrupt(irq); 163 } 164 165 166 void 167 arch_int_disable_io_interrupt(int irq) 168 { 169 sCurrentPIC->disable_io_interrupt(irq); 170 } 171 172 173 void 174 arch_int_configure_io_interrupt(int irq, uint32 config) 175 { 176 sCurrentPIC->configure_io_interrupt(irq, config); 177 } 178 179 180 #undef arch_int_enable_interrupts 181 #undef arch_int_disable_interrupts 182 #undef arch_int_restore_interrupts 183 #undef arch_int_are_interrupts_enabled 184 185 186 void 187 arch_int_enable_interrupts(void) 188 { 189 arch_int_enable_interrupts_inline(); 190 } 191 192 193 int 194 arch_int_disable_interrupts(void) 195 { 196 return arch_int_disable_interrupts_inline(); 197 } 198 199 200 void 201 arch_int_restore_interrupts(int oldState) 202 { 203 arch_int_restore_interrupts_inline(oldState); 204 } 205 206 207 bool 208 arch_int_are_interrupts_enabled(void) 209 { 210 return arch_int_are_interrupts_enabled_inline(); 211 } 212 213 214 static const char * 215 exception_name(int number, char *buffer, int32 bufferSize) 216 { 217 if (number >= 0 && number < kInterruptNameCount) 218 return kInterruptNames[number]; 219 220 snprintf(buffer, bufferSize, "exception %d", number); 221 return buffer; 222 } 223 224 225 static void 226 invalid_exception(struct iframe* frame) 227 { 228 Thread* thread = thread_get_current_thread(); 229 char name[32]; 230 panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", 231 frame->vector, exception_name(frame->vector, name, sizeof(name)), 232 frame->eip, thread ? thread->id : -1); 233 } 234 235 236 static void 237 fatal_exception(struct iframe *frame) 238 { 239 char name[32]; 240 panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", 241 exception_name(frame->vector, name, sizeof(name)), frame->error_code); 242 } 243 244 245 static void 246 unexpected_exception(struct iframe* frame) 247 { 248 debug_exception_type type; 249 uint32 signalNumber; 250 int32 signalCode; 251 addr_t signalAddress = 0; 252 int32 signalError = B_ERROR; 253 254 if (IFRAME_IS_VM86(frame)) { 255 x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ? 256 B_OK : B_ERROR); 257 // won't get here 258 } 259 260 switch (frame->vector) { 261 case 0: // Divide Error Exception (#DE) 262 type = B_DIVIDE_ERROR; 263 signalNumber = SIGFPE; 264 signalCode = FPE_INTDIV; 265 signalAddress = frame->eip; 266 break; 267 268 case 4: // Overflow Exception (#OF) 269 type = B_OVERFLOW_EXCEPTION; 270 signalNumber = SIGFPE; 271 signalCode = FPE_INTOVF; 272 signalAddress = frame->eip; 273 break; 274 275 case 5: // BOUND Range Exceeded Exception (#BR) 276 type = B_BOUNDS_CHECK_EXCEPTION; 277 signalNumber = SIGTRAP; 278 signalCode = SI_USER; 279 break; 280 281 case 6: // Invalid Opcode Exception (#UD) 282 type = B_INVALID_OPCODE_EXCEPTION; 283 signalNumber = SIGILL; 284 signalCode = ILL_ILLOPC; 285 signalAddress = frame->eip; 286 break; 287 288 case 13: // General Protection Exception (#GP) 289 type = B_GENERAL_PROTECTION_FAULT; 290 signalNumber = SIGILL; 291 signalCode = ILL_PRVOPC; // or ILL_PRVREG 292 signalAddress = frame->eip; 293 break; 294 295 case 16: // x87 FPU Floating-Point Error (#MF) 296 type = B_FLOATING_POINT_EXCEPTION; 297 signalNumber = SIGFPE; 298 signalCode = FPE_FLTDIV; 299 // TODO: Determine the correct cause via the FPU status 300 // register! 301 signalAddress = frame->eip; 302 break; 303 304 case 17: // Alignment Check Exception (#AC) 305 type = B_ALIGNMENT_EXCEPTION; 306 signalNumber = SIGBUS; 307 signalCode = BUS_ADRALN; 308 // TODO: Also get the address (from where?). Since we don't enable 309 // alignment checking this exception should never happen, though. 310 signalError = EFAULT; 311 break; 312 313 case 19: // SIMD Floating-Point Exception (#XF) 314 type = B_FLOATING_POINT_EXCEPTION; 315 signalNumber = SIGFPE; 316 signalCode = FPE_FLTDIV; 317 // TODO: Determine the correct cause via the MXCSR register! 318 signalAddress = frame->eip; 319 break; 320 321 default: 322 invalid_exception(frame); 323 return; 324 } 325 326 if (IFRAME_IS_USER(frame)) { 327 struct sigaction action; 328 Thread* thread = thread_get_current_thread(); 329 330 enable_interrupts(); 331 332 // If the thread has a signal handler for the signal, we simply send it 333 // the signal. Otherwise we notify the user debugger first. 334 if ((sigaction(signalNumber, NULL, &action) == 0 335 && action.sa_handler != SIG_DFL 336 && action.sa_handler != SIG_IGN) 337 || user_debug_exception_occurred(type, signalNumber)) { 338 Signal signal(signalNumber, signalCode, signalError, 339 thread->team->id); 340 signal.SetAddress((void*)signalAddress); 341 send_signal_to_thread(thread, signal, 0); 342 } 343 } else { 344 char name[32]; 345 panic("Unexpected exception \"%s\" occurred in kernel mode! " 346 "Error code: 0x%lx\n", 347 exception_name(frame->vector, name, sizeof(name)), 348 frame->error_code); 349 } 350 } 351 352 353 void 354 x86_double_fault_exception(struct iframe* frame) 355 { 356 int cpu = x86_double_fault_get_cpu(); 357 358 // The double fault iframe contains no useful information (as 359 // per Intel's architecture spec). Thus we simply save the 360 // information from the (unhandlable) exception which caused the 361 // double in our iframe. This will result even in useful stack 362 // traces. Only problem is that we trust that at least the 363 // TSS is still accessible. 364 struct tss *tss = &gCPU[cpu].arch.tss; 365 366 frame->cs = tss->cs; 367 frame->es = tss->es; 368 frame->ds = tss->ds; 369 frame->fs = tss->fs; 370 frame->gs = tss->gs; 371 frame->eip = tss->eip; 372 frame->ebp = tss->ebp; 373 frame->esp = tss->esp; 374 frame->eax = tss->eax; 375 frame->ebx = tss->ebx; 376 frame->ecx = tss->ecx; 377 frame->edx = tss->edx; 378 frame->esi = tss->esi; 379 frame->edi = tss->edi; 380 frame->flags = tss->eflags; 381 382 // Use a special handler for page faults which avoids the triple fault 383 // pitfalls. 384 set_interrupt_gate(cpu, 14, &trap14_double_fault); 385 386 debug_double_fault(cpu); 387 } 388 389 390 void 391 x86_page_fault_exception_double_fault(struct iframe* frame) 392 { 393 uint32 cr2; 394 asm("movl %%cr2, %0" : "=r" (cr2)); 395 396 // Only if this CPU has a fault handler, we're allowed to be here. 397 cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; 398 addr_t faultHandler = cpu.fault_handler; 399 if (faultHandler != 0) { 400 debug_set_page_fault_info(cr2, frame->eip, 401 (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); 402 frame->eip = faultHandler; 403 frame->ebp = cpu.fault_handler_stack_pointer; 404 return; 405 } 406 407 // No fault handler. This is bad. Since we originally came from a double 408 // fault, we don't try to reenter the kernel debugger. Instead we just 409 // print the info we've got and enter an infinite loop. 410 kprintf("Page fault in double fault debugger without fault handler! " 411 "Touching address %p from eip %p. Entering infinite loop...\n", 412 (void*)cr2, (void*)frame->eip); 413 414 while (true); 415 } 416 417 418 static void 419 page_fault_exception(struct iframe* frame) 420 { 421 Thread *thread = thread_get_current_thread(); 422 uint32 cr2; 423 addr_t newip; 424 425 asm("movl %%cr2, %0" : "=r" (cr2)); 426 427 if (debug_debugger_running()) { 428 // If this CPU or this thread has a fault handler, we're allowed to be 429 // here. 430 if (thread != NULL) { 431 cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; 432 if (cpu->fault_handler != 0) { 433 debug_set_page_fault_info(cr2, frame->eip, 434 (frame->error_code & 0x2) != 0 435 ? DEBUG_PAGE_FAULT_WRITE : 0); 436 frame->eip = cpu->fault_handler; 437 frame->ebp = cpu->fault_handler_stack_pointer; 438 return; 439 } 440 441 if (thread->fault_handler != 0) { 442 kprintf("ERROR: thread::fault_handler used in kernel " 443 "debugger!\n"); 444 debug_set_page_fault_info(cr2, frame->eip, 445 (frame->error_code & 0x2) != 0 446 ? DEBUG_PAGE_FAULT_WRITE : 0); 447 frame->eip = thread->fault_handler; 448 return; 449 } 450 } 451 452 // otherwise, not really 453 panic("page fault in debugger without fault handler! Touching " 454 "address %p from eip %p\n", (void *)cr2, (void *)frame->eip); 455 return; 456 } else if ((frame->flags & 0x200) == 0) { 457 // interrupts disabled 458 459 // If a page fault handler is installed, we're allowed to be here. 460 // TODO: Now we are generally allowing user_memcpy() with interrupts 461 // disabled, which in most cases is a bug. We should add some thread 462 // flag allowing to explicitly indicate that this handling is desired. 463 if (thread && thread->fault_handler != 0) { 464 if (frame->eip != thread->fault_handler) { 465 frame->eip = thread->fault_handler; 466 return; 467 } 468 469 // The fault happened at the fault handler address. This is a 470 // certain infinite loop. 471 panic("page fault, interrupts disabled, fault handler loop. " 472 "Touching address %p from eip %p\n", (void*)cr2, 473 (void*)frame->eip); 474 } 475 476 // If we are not running the kernel startup the page fault was not 477 // allowed to happen and we must panic. 478 panic("page fault, but interrupts were disabled. Touching address " 479 "%p from eip %p\n", (void *)cr2, (void *)frame->eip); 480 return; 481 } else if (thread != NULL && thread->page_faults_allowed < 1) { 482 panic("page fault not allowed at this place. Touching address " 483 "%p from eip %p\n", (void *)cr2, (void *)frame->eip); 484 return; 485 } 486 487 enable_interrupts(); 488 489 vm_page_fault(cr2, frame->eip, 490 (frame->error_code & 0x2) != 0, // write access 491 (frame->error_code & 0x4) != 0, // userland 492 &newip); 493 if (newip != 0) { 494 // the page fault handler wants us to modify the iframe to set the 495 // IP the cpu will return to to be this ip 496 frame->eip = newip; 497 } 498 } 499 500 501 static void 502 hardware_interrupt(struct iframe* frame) 503 { 504 int32 vector = frame->vector - ARCH_INTERRUPT_BASE; 505 bool levelTriggered = false; 506 Thread* thread = thread_get_current_thread(); 507 508 if (sCurrentPIC->is_spurious_interrupt(vector)) { 509 TRACE(("got spurious interrupt at vector %ld\n", vector)); 510 return; 511 } 512 513 levelTriggered = sCurrentPIC->is_level_triggered_interrupt(vector); 514 515 if (!levelTriggered) { 516 // if it's not handled by the current pic then it's an apic generated 517 // interrupt like local interrupts, msi or ipi. 518 if (!sCurrentPIC->end_of_interrupt(vector)) 519 apic_end_of_interrupt(); 520 } 521 522 int_io_interrupt_handler(vector, levelTriggered); 523 524 if (levelTriggered) { 525 if (!sCurrentPIC->end_of_interrupt(vector)) 526 apic_end_of_interrupt(); 527 } 528 529 cpu_status state = disable_interrupts(); 530 if (thread->cpu->invoke_scheduler) { 531 SpinLocker schedulerLocker(gSchedulerLock); 532 scheduler_reschedule(); 533 schedulerLocker.Unlock(); 534 restore_interrupts(state); 535 } else if (thread->post_interrupt_callback != NULL) { 536 void (*callback)(void*) = thread->post_interrupt_callback; 537 void* data = thread->post_interrupt_data; 538 539 thread->post_interrupt_callback = NULL; 540 thread->post_interrupt_data = NULL; 541 542 restore_interrupts(state); 543 544 callback(data); 545 } 546 } 547 548 549 status_t 550 arch_int_init(struct kernel_args *args) 551 { 552 int i; 553 interrupt_handler_function** table; 554 555 // set the global sIDT variable 556 sIDTs[0] = (desc_table *)args->arch_args.vir_idt; 557 558 // setup the standard programmable interrupt controller 559 pic_init(); 560 561 set_interrupt_gate(0, 0, &trap0); 562 set_interrupt_gate(0, 1, &trap1); 563 set_interrupt_gate(0, 2, &trap2); 564 set_trap_gate(0, 3, &trap3); 565 set_interrupt_gate(0, 4, &trap4); 566 set_interrupt_gate(0, 5, &trap5); 567 set_interrupt_gate(0, 6, &trap6); 568 set_interrupt_gate(0, 7, &trap7); 569 // trap8 (double fault) is set in arch_cpu.c 570 set_interrupt_gate(0, 9, &trap9); 571 set_interrupt_gate(0, 10, &trap10); 572 set_interrupt_gate(0, 11, &trap11); 573 set_interrupt_gate(0, 12, &trap12); 574 set_interrupt_gate(0, 13, &trap13); 575 set_interrupt_gate(0, 14, &trap14); 576 // set_interrupt_gate(0, 15, &trap15); 577 set_interrupt_gate(0, 16, &trap16); 578 set_interrupt_gate(0, 17, &trap17); 579 set_interrupt_gate(0, 18, &trap18); 580 set_interrupt_gate(0, 19, &trap19); 581 582 // legacy or ioapic interrupts 583 set_interrupt_gate(0, 32, &trap32); 584 set_interrupt_gate(0, 33, &trap33); 585 set_interrupt_gate(0, 34, &trap34); 586 set_interrupt_gate(0, 35, &trap35); 587 set_interrupt_gate(0, 36, &trap36); 588 set_interrupt_gate(0, 37, &trap37); 589 set_interrupt_gate(0, 38, &trap38); 590 set_interrupt_gate(0, 39, &trap39); 591 set_interrupt_gate(0, 40, &trap40); 592 set_interrupt_gate(0, 41, &trap41); 593 set_interrupt_gate(0, 42, &trap42); 594 set_interrupt_gate(0, 43, &trap43); 595 set_interrupt_gate(0, 44, &trap44); 596 set_interrupt_gate(0, 45, &trap45); 597 set_interrupt_gate(0, 46, &trap46); 598 set_interrupt_gate(0, 47, &trap47); 599 600 // additional ioapic interrupts 601 set_interrupt_gate(0, 48, &trap48); 602 set_interrupt_gate(0, 49, &trap49); 603 set_interrupt_gate(0, 50, &trap50); 604 set_interrupt_gate(0, 51, &trap51); 605 set_interrupt_gate(0, 52, &trap52); 606 set_interrupt_gate(0, 53, &trap53); 607 set_interrupt_gate(0, 54, &trap54); 608 set_interrupt_gate(0, 55, &trap55); 609 610 // configurable msi or msi-x interrupts 611 set_interrupt_gate(0, 56, &trap56); 612 set_interrupt_gate(0, 57, &trap57); 613 set_interrupt_gate(0, 58, &trap58); 614 set_interrupt_gate(0, 59, &trap59); 615 set_interrupt_gate(0, 60, &trap60); 616 set_interrupt_gate(0, 61, &trap61); 617 set_interrupt_gate(0, 62, &trap62); 618 set_interrupt_gate(0, 63, &trap63); 619 set_interrupt_gate(0, 64, &trap64); 620 set_interrupt_gate(0, 65, &trap65); 621 set_interrupt_gate(0, 66, &trap66); 622 set_interrupt_gate(0, 67, &trap67); 623 set_interrupt_gate(0, 68, &trap68); 624 set_interrupt_gate(0, 69, &trap69); 625 set_interrupt_gate(0, 70, &trap70); 626 set_interrupt_gate(0, 71, &trap71); 627 set_interrupt_gate(0, 72, &trap72); 628 set_interrupt_gate(0, 73, &trap73); 629 set_interrupt_gate(0, 74, &trap74); 630 set_interrupt_gate(0, 75, &trap75); 631 set_interrupt_gate(0, 76, &trap76); 632 set_interrupt_gate(0, 77, &trap77); 633 set_interrupt_gate(0, 78, &trap78); 634 set_interrupt_gate(0, 79, &trap79); 635 set_interrupt_gate(0, 80, &trap80); 636 set_interrupt_gate(0, 81, &trap81); 637 set_interrupt_gate(0, 82, &trap82); 638 set_interrupt_gate(0, 83, &trap83); 639 set_interrupt_gate(0, 84, &trap84); 640 set_interrupt_gate(0, 85, &trap85); 641 set_interrupt_gate(0, 86, &trap86); 642 set_interrupt_gate(0, 87, &trap87); 643 set_interrupt_gate(0, 88, &trap88); 644 set_interrupt_gate(0, 89, &trap89); 645 set_interrupt_gate(0, 90, &trap90); 646 set_interrupt_gate(0, 91, &trap91); 647 set_interrupt_gate(0, 92, &trap92); 648 set_interrupt_gate(0, 93, &trap93); 649 set_interrupt_gate(0, 94, &trap94); 650 set_interrupt_gate(0, 95, &trap95); 651 set_interrupt_gate(0, 96, &trap96); 652 set_interrupt_gate(0, 97, &trap97); 653 654 set_trap_gate(0, 98, &trap98); // for performance testing only 655 set_trap_gate(0, 99, &trap99); // syscall interrupt 656 657 reserve_io_interrupt_vectors(2, 98); 658 659 // configurable msi or msi-x interrupts 660 set_interrupt_gate(0, 100, &trap100); 661 set_interrupt_gate(0, 101, &trap101); 662 set_interrupt_gate(0, 102, &trap102); 663 set_interrupt_gate(0, 103, &trap103); 664 set_interrupt_gate(0, 104, &trap104); 665 set_interrupt_gate(0, 105, &trap105); 666 set_interrupt_gate(0, 106, &trap106); 667 set_interrupt_gate(0, 107, &trap107); 668 set_interrupt_gate(0, 108, &trap108); 669 set_interrupt_gate(0, 109, &trap109); 670 set_interrupt_gate(0, 110, &trap110); 671 set_interrupt_gate(0, 111, &trap111); 672 set_interrupt_gate(0, 112, &trap112); 673 set_interrupt_gate(0, 113, &trap113); 674 set_interrupt_gate(0, 114, &trap114); 675 set_interrupt_gate(0, 115, &trap115); 676 set_interrupt_gate(0, 116, &trap116); 677 set_interrupt_gate(0, 117, &trap117); 678 set_interrupt_gate(0, 118, &trap118); 679 set_interrupt_gate(0, 119, &trap119); 680 set_interrupt_gate(0, 120, &trap120); 681 set_interrupt_gate(0, 121, &trap121); 682 set_interrupt_gate(0, 122, &trap122); 683 set_interrupt_gate(0, 123, &trap123); 684 set_interrupt_gate(0, 124, &trap124); 685 set_interrupt_gate(0, 125, &trap125); 686 set_interrupt_gate(0, 126, &trap126); 687 set_interrupt_gate(0, 127, &trap127); 688 set_interrupt_gate(0, 128, &trap128); 689 set_interrupt_gate(0, 129, &trap129); 690 set_interrupt_gate(0, 130, &trap130); 691 set_interrupt_gate(0, 131, &trap131); 692 set_interrupt_gate(0, 132, &trap132); 693 set_interrupt_gate(0, 133, &trap133); 694 set_interrupt_gate(0, 134, &trap134); 695 set_interrupt_gate(0, 135, &trap135); 696 set_interrupt_gate(0, 136, &trap136); 697 set_interrupt_gate(0, 137, &trap137); 698 set_interrupt_gate(0, 138, &trap138); 699 set_interrupt_gate(0, 139, &trap139); 700 set_interrupt_gate(0, 140, &trap140); 701 set_interrupt_gate(0, 141, &trap141); 702 set_interrupt_gate(0, 142, &trap142); 703 set_interrupt_gate(0, 143, &trap143); 704 set_interrupt_gate(0, 144, &trap144); 705 set_interrupt_gate(0, 145, &trap145); 706 set_interrupt_gate(0, 146, &trap146); 707 set_interrupt_gate(0, 147, &trap147); 708 set_interrupt_gate(0, 148, &trap148); 709 set_interrupt_gate(0, 149, &trap149); 710 set_interrupt_gate(0, 150, &trap150); 711 set_interrupt_gate(0, 151, &trap151); 712 set_interrupt_gate(0, 152, &trap152); 713 set_interrupt_gate(0, 153, &trap153); 714 set_interrupt_gate(0, 154, &trap154); 715 set_interrupt_gate(0, 155, &trap155); 716 set_interrupt_gate(0, 156, &trap156); 717 set_interrupt_gate(0, 157, &trap157); 718 set_interrupt_gate(0, 158, &trap158); 719 set_interrupt_gate(0, 159, &trap159); 720 set_interrupt_gate(0, 160, &trap160); 721 set_interrupt_gate(0, 161, &trap161); 722 set_interrupt_gate(0, 162, &trap162); 723 set_interrupt_gate(0, 163, &trap163); 724 set_interrupt_gate(0, 164, &trap164); 725 set_interrupt_gate(0, 165, &trap165); 726 set_interrupt_gate(0, 166, &trap166); 727 set_interrupt_gate(0, 167, &trap167); 728 set_interrupt_gate(0, 168, &trap168); 729 set_interrupt_gate(0, 169, &trap169); 730 set_interrupt_gate(0, 170, &trap170); 731 set_interrupt_gate(0, 171, &trap171); 732 set_interrupt_gate(0, 172, &trap172); 733 set_interrupt_gate(0, 173, &trap173); 734 set_interrupt_gate(0, 174, &trap174); 735 set_interrupt_gate(0, 175, &trap175); 736 set_interrupt_gate(0, 176, &trap176); 737 set_interrupt_gate(0, 177, &trap177); 738 set_interrupt_gate(0, 178, &trap178); 739 set_interrupt_gate(0, 179, &trap179); 740 set_interrupt_gate(0, 180, &trap180); 741 set_interrupt_gate(0, 181, &trap181); 742 set_interrupt_gate(0, 182, &trap182); 743 set_interrupt_gate(0, 183, &trap183); 744 set_interrupt_gate(0, 184, &trap184); 745 set_interrupt_gate(0, 185, &trap185); 746 set_interrupt_gate(0, 186, &trap186); 747 set_interrupt_gate(0, 187, &trap187); 748 set_interrupt_gate(0, 188, &trap188); 749 set_interrupt_gate(0, 189, &trap189); 750 set_interrupt_gate(0, 190, &trap190); 751 set_interrupt_gate(0, 191, &trap191); 752 set_interrupt_gate(0, 192, &trap192); 753 set_interrupt_gate(0, 193, &trap193); 754 set_interrupt_gate(0, 194, &trap194); 755 set_interrupt_gate(0, 195, &trap195); 756 set_interrupt_gate(0, 196, &trap196); 757 set_interrupt_gate(0, 197, &trap197); 758 set_interrupt_gate(0, 198, &trap198); 759 set_interrupt_gate(0, 199, &trap199); 760 set_interrupt_gate(0, 200, &trap200); 761 set_interrupt_gate(0, 201, &trap201); 762 set_interrupt_gate(0, 202, &trap202); 763 set_interrupt_gate(0, 203, &trap203); 764 set_interrupt_gate(0, 204, &trap204); 765 set_interrupt_gate(0, 205, &trap205); 766 set_interrupt_gate(0, 206, &trap206); 767 set_interrupt_gate(0, 207, &trap207); 768 set_interrupt_gate(0, 208, &trap208); 769 set_interrupt_gate(0, 209, &trap209); 770 set_interrupt_gate(0, 210, &trap210); 771 set_interrupt_gate(0, 211, &trap211); 772 set_interrupt_gate(0, 212, &trap212); 773 set_interrupt_gate(0, 213, &trap213); 774 set_interrupt_gate(0, 214, &trap214); 775 set_interrupt_gate(0, 215, &trap215); 776 set_interrupt_gate(0, 216, &trap216); 777 set_interrupt_gate(0, 217, &trap217); 778 set_interrupt_gate(0, 218, &trap218); 779 set_interrupt_gate(0, 219, &trap219); 780 set_interrupt_gate(0, 220, &trap220); 781 set_interrupt_gate(0, 221, &trap221); 782 set_interrupt_gate(0, 222, &trap222); 783 set_interrupt_gate(0, 223, &trap223); 784 set_interrupt_gate(0, 224, &trap224); 785 set_interrupt_gate(0, 225, &trap225); 786 set_interrupt_gate(0, 226, &trap226); 787 set_interrupt_gate(0, 227, &trap227); 788 set_interrupt_gate(0, 228, &trap228); 789 set_interrupt_gate(0, 229, &trap229); 790 set_interrupt_gate(0, 230, &trap230); 791 set_interrupt_gate(0, 231, &trap231); 792 set_interrupt_gate(0, 232, &trap232); 793 set_interrupt_gate(0, 233, &trap233); 794 set_interrupt_gate(0, 234, &trap234); 795 set_interrupt_gate(0, 235, &trap235); 796 set_interrupt_gate(0, 236, &trap236); 797 set_interrupt_gate(0, 237, &trap237); 798 set_interrupt_gate(0, 238, &trap238); 799 set_interrupt_gate(0, 239, &trap239); 800 set_interrupt_gate(0, 240, &trap240); 801 set_interrupt_gate(0, 241, &trap241); 802 set_interrupt_gate(0, 242, &trap242); 803 set_interrupt_gate(0, 243, &trap243); 804 set_interrupt_gate(0, 244, &trap244); 805 set_interrupt_gate(0, 245, &trap245); 806 set_interrupt_gate(0, 246, &trap246); 807 set_interrupt_gate(0, 247, &trap247); 808 set_interrupt_gate(0, 248, &trap248); 809 set_interrupt_gate(0, 249, &trap249); 810 set_interrupt_gate(0, 250, &trap250); 811 812 // smp / apic local interrupts 813 set_interrupt_gate(0, 251, &trap251); 814 set_interrupt_gate(0, 252, &trap252); 815 set_interrupt_gate(0, 253, &trap253); 816 set_interrupt_gate(0, 254, &trap254); 817 set_interrupt_gate(0, 255, &trap255); 818 819 // init interrupt handler table 820 table = gInterruptHandlerTable; 821 822 // defaults 823 for (i = 0; i < ARCH_INTERRUPT_BASE; i++) 824 table[i] = invalid_exception; 825 for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) 826 table[i] = hardware_interrupt; 827 828 table[0] = unexpected_exception; // Divide Error Exception (#DE) 829 table[1] = x86_handle_debug_exception; // Debug Exception (#DB) 830 table[2] = fatal_exception; // NMI Interrupt 831 table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) 832 table[4] = unexpected_exception; // Overflow Exception (#OF) 833 table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) 834 table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) 835 table[7] = fatal_exception; // Device Not Available Exception (#NM) 836 table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) 837 table[9] = fatal_exception; // Coprocessor Segment Overrun 838 table[10] = fatal_exception; // Invalid TSS Exception (#TS) 839 table[11] = fatal_exception; // Segment Not Present (#NP) 840 table[12] = fatal_exception; // Stack Fault Exception (#SS) 841 table[13] = unexpected_exception; // General Protection Exception (#GP) 842 table[14] = page_fault_exception; // Page-Fault Exception (#PF) 843 table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) 844 table[17] = unexpected_exception; // Alignment Check Exception (#AC) 845 table[18] = fatal_exception; // Machine-Check Exception (#MC) 846 table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) 847 848 return B_OK; 849 } 850 851 852 status_t 853 arch_int_init_post_vm(struct kernel_args *args) 854 { 855 // Always init the local apic as it can be used for timers even if we 856 // don't end up using the io apic 857 apic_init(args); 858 859 // create IDT area for the boot CPU 860 area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS, 861 B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 862 if (area < 0) 863 return area; 864 865 // create IDTs for the off-boot CPU 866 size_t idtSize = 256 * 8; 867 // 256 8 bytes-sized descriptors 868 int32 cpuCount = smp_get_num_cpus(); 869 if (cpuCount > 0) { 870 size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE); 871 desc_table* idt; 872 virtual_address_restrictions virtualRestrictions = {}; 873 virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; 874 physical_address_restrictions physicalRestrictions = {}; 875 area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS, 876 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 877 &virtualRestrictions, &physicalRestrictions, (void**)&idt); 878 if (area < 0) 879 return area; 880 881 for (int32 i = 1; i < cpuCount; i++) { 882 sIDTs[i] = idt; 883 memcpy(idt, sIDTs[0], idtSize); 884 idt += 256; 885 // The CPU's IDTR will be set in arch_cpu_init_percpu(). 886 } 887 } 888 889 return area >= B_OK ? B_OK : area; 890 } 891 892 893 status_t 894 arch_int_init_io(kernel_args* args) 895 { 896 ioapic_init(args); 897 msi_init(); 898 return B_OK; 899 } 900 901 902 status_t 903 arch_int_init_post_device_manager(struct kernel_args *args) 904 { 905 return B_OK; 906 } 907 908 909 void 910 arch_int_set_interrupt_controller(const interrupt_controller &controller) 911 { 912 sCurrentPIC = &controller; 913 } 914