262,263c262,270
< if (DeliveryMode::isUnmaskable(message.deliveryMode)) {
< DPRINTF(LocalApic, "Interrupt is an %s and unmaskable.\n",
---
>
> /*
> * Fixed and lowest-priority delivery mode interrupts are handled
> * using the IRR/ISR registers, checking against the TPR, etc.
> * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through.
> */
> if (message.deliveryMode == DeliveryMode::Fixed ||
> message.deliveryMode == DeliveryMode::LowestPriority) {
> DPRINTF(LocalApic, "Interrupt is an %s.\n",
265,268d271
< panic("Unmaskable interrupts aren't implemented.\n");
< } else if (DeliveryMode::isMaskable(message.deliveryMode)) {
< DPRINTF(LocalApic, "Interrupt is an %s and maskable.\n",
< DeliveryMode::names[message.deliveryMode]);
282c285,305
< }
---
> } else if (!DeliveryMode::isReserved(message.deliveryMode)) {
> DPRINTF(LocalApic, "Interrupt is an %s.\n",
> DeliveryMode::names[message.deliveryMode]);
> if (message.deliveryMode == DeliveryMode::SMI &&
> !pendingSmi) {
> pendingUnmaskableInt = pendingSmi = true;
> smiMessage = message;
> } else if (message.deliveryMode == DeliveryMode::NMI &&
> !pendingNmi) {
> pendingUnmaskableInt = pendingNmi = true;
> nmiMessage = message;
> } else if (message.deliveryMode == DeliveryMode::ExtInt &&
> !pendingExtInt) {
> pendingExtInt = true;
> extIntMessage = message;
> } else if (message.deliveryMode == DeliveryMode::INIT &&
> !pendingInit) {
> pendingUnmaskableInt = pendingInit = true;
> initMessage = message;
> }
> }
454,455c477
< if (IRRV > ISRV && rflags.intf &&
< bits(IRRV, 7, 4) > bits(regs[APIC_TASK_PRIORITY], 7, 4)) {
---
> if (pendingUnmaskableInt)
456a479,484
> if (rflags.intf) {
> if (pendingExtInt)
> return true;
> if (IRRV > ISRV && bits(IRRV, 7, 4) >
> bits(regs[APIC_TASK_PRIORITY], 7, 4))
> return true;
465c493,512
< return new ExternalInterrupt(IRRV);
---
> // These are all probably fairly uncommon, so we'll make them easier to
> // check for.
> if (pendingUnmaskableInt) {
> if (pendingSmi) {
> return new SystemManagementInterrupt();
> } else if (pendingNmi) {
> return new NonMaskableInterrupt(nmiMessage.vector);
> } else if (pendingInit) {
> return new InitInterrupt(initMessage.vector);
> } else {
> panic("pendingUnmaskableInt set, but no unmaskable "
> "ints were pending.\n");
> return NoFault;
> }
> } else if (pendingExtInt) {
> return new ExternalInterrupt(extIntMessage.vector);
> } else {
> // The only thing left are fixed and lowest priority interrupts.
> return new ExternalInterrupt(IRRV);
> }
472,477c519,538
< // Mark the interrupt as "in service".
< ISRV = IRRV;
< setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
< // Clear it out of the IRR.
< clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
< updateIRRV();
---
> if (pendingUnmaskableInt) {
> if (pendingSmi) {
> pendingSmi = false;
> } else if (pendingNmi) {
> pendingNmi = false;
> } else if (pendingInit) {
> pendingInit = false;
> }
> if (!(pendingSmi || pendingNmi || pendingInit))
> pendingUnmaskableInt = false;
> } else if (pendingExtInt) {
> pendingExtInt = false;
> } else {
> // Mark the interrupt as "in service".
> ISRV = IRRV;
> setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
> // Clear it out of the IRR.
> clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
> updateIRRV();
> }