1/*
2 * Copyright (c) 2008 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *

--- 460 unchanged lines hidden (view full) ---

469 regs[reg] = newVal;
470 return;
471}
472
473bool
474X86ISA::Interrupts::check_interrupts(ThreadContext * tc) const
475{
476 RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS);
477 if (pendingUnmaskableInt)
477 if (pendingUnmaskableInt) {
478 DPRINTF(LocalApic, "Reported pending unmaskable interrupt.\n");
479 return true;
480 }
481 if (rflags.intf) {
480 if (pendingExtInt)
482 if (pendingExtInt) {
483 DPRINTF(LocalApic, "Reported pending external interrupt.\n");
484 return true;
485 }
486 if (IRRV > ISRV && bits(IRRV, 7, 4) >
483 bits(regs[APIC_TASK_PRIORITY], 7, 4))
487 bits(regs[APIC_TASK_PRIORITY], 7, 4)) {
488 DPRINTF(LocalApic, "Reported pending regular interrupt.\n");
489 return true;
490 }
491 }
492 return false;
493}
494
495Fault
496X86ISA::Interrupts::getInterrupt(ThreadContext * tc)
497{
498 assert(check_interrupts(tc));
499 // These are all probably fairly uncommon, so we'll make them easier to
500 // check for.
501 if (pendingUnmaskableInt) {
502 if (pendingSmi) {
503 DPRINTF(LocalApic, "Generated SMI fault object.\n");
504 return new SystemManagementInterrupt();
505 } else if (pendingNmi) {
506 DPRINTF(LocalApic, "Generated NMI fault object.\n");
507 return new NonMaskableInterrupt(nmiMessage.vector);
508 } else if (pendingInit) {
509 DPRINTF(LocalApic, "Generated INIT fault object.\n");
510 return new InitInterrupt(initMessage.vector);
511 } else {
512 panic("pendingUnmaskableInt set, but no unmaskable "
513 "ints were pending.\n");
514 return NoFault;
515 }
516 } else if (pendingExtInt) {
517 DPRINTF(LocalApic, "Generated external interrupt fault object.\n");
518 return new ExternalInterrupt(extIntMessage.vector);
519 } else {
520 DPRINTF(LocalApic, "Generated regular interrupt fault object.\n");
521 // The only thing left are fixed and lowest priority interrupts.
522 return new ExternalInterrupt(IRRV);
523 }
524}
525
526void
527X86ISA::Interrupts::updateIntrInfo(ThreadContext * tc)
528{
529 assert(check_interrupts(tc));
530 if (pendingUnmaskableInt) {
531 if (pendingSmi) {
532 DPRINTF(LocalApic, "SMI sent to core.\n");
533 pendingSmi = false;
534 } else if (pendingNmi) {
535 DPRINTF(LocalApic, "NMI sent to core.\n");
536 pendingNmi = false;
537 } else if (pendingInit) {
538 DPRINTF(LocalApic, "Init sent to core.\n");
539 pendingInit = false;
540 }
541 if (!(pendingSmi || pendingNmi || pendingInit))
542 pendingUnmaskableInt = false;
543 } else if (pendingExtInt) {
544 pendingExtInt = false;
545 } else {
546 DPRINTF(LocalApic, "Interrupt %d sent to core.\n", IRRV);
547 // Mark the interrupt as "in service".
548 ISRV = IRRV;
549 setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
550 // Clear it out of the IRR.
551 clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
552 updateIRRV();
553 }
554}
555
556X86ISA::Interrupts *
557X86LocalApicParams::create()
558{
559 return new X86ISA::Interrupts(this);
560}