X86: Start implementing the interrupt command register in the local APIC.

This commit is contained in:
Gabe Black 2009-04-19 02:43:22 -07:00
parent 9549694ecd
commit 641513fe08
3 changed files with 52 additions and 14 deletions

View file

@ -31,6 +31,8 @@
#ifndef __ARCH_X86_APICREGS_HH__ #ifndef __ARCH_X86_APICREGS_HH__
#define __ARCH_X86_APICREGS_HH__ #define __ARCH_X86_APICREGS_HH__
#include "base/bitunion.hh"
namespace X86ISA namespace X86ISA
{ {
enum ApicRegIndex enum ApicRegIndex
@ -86,6 +88,20 @@ namespace X86ISA
{ {
return (ApicRegIndex)(APIC_INTERRUPT_REQUEST_BASE + index); return (ApicRegIndex)(APIC_INTERRUPT_REQUEST_BASE + index);
} }
BitUnion32(InterruptCommandRegLow)
Bitfield<7, 0> vector;
Bitfield<10, 8> deliveryMode;
Bitfield<11> destMode;
Bitfield<12> deliveryStatus;
Bitfield<14> level;
Bitfield<15> trigger;
Bitfield<19, 18> destShorthand;
EndBitUnion(InterruptCommandRegLow)
BitUnion32(InterruptCommandRegHigh)
Bitfield<31, 24> destination;
EndBitUnion(InterruptCommandRegHigh)
} }
#endif #endif

View file

@ -60,6 +60,7 @@
#include "arch/x86/intmessage.hh" #include "arch/x86/intmessage.hh"
#include "cpu/base.hh" #include "cpu/base.hh"
#include "mem/packet_access.hh" #include "mem/packet_access.hh"
#include "sim/system.hh"
int int
divideFromConf(uint32_t conf) divideFromConf(uint32_t conf)
@ -366,14 +367,6 @@ X86ISA::Interrupts::readReg(ApicRegIndex reg)
case APIC_ERROR_STATUS: case APIC_ERROR_STATUS:
regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
break; break;
case APIC_INTERRUPT_COMMAND_LOW:
panic("Local APIC Interrupt Command low"
" register unimplemented.\n");
break;
case APIC_INTERRUPT_COMMAND_HIGH:
panic("Local APIC Interrupt Command high"
" register unimplemented.\n");
break;
case APIC_CURRENT_COUNT: case APIC_CURRENT_COUNT:
{ {
if (apicTimerEvent.scheduled()) { if (apicTimerEvent.scheduled()) {
@ -459,12 +452,40 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
} }
break; break;
case APIC_INTERRUPT_COMMAND_LOW: case APIC_INTERRUPT_COMMAND_LOW:
panic("Local APIC Interrupt Command low" {
" register unimplemented.\n"); InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
// Check if we're already sending an IPI.
if (low.deliveryStatus) {
newVal = low;
break; break;
case APIC_INTERRUPT_COMMAND_HIGH: }
panic("Local APIC Interrupt Command high" low = val;
" register unimplemented.\n"); InterruptCommandRegHigh high = regs[APIC_INTERRUPT_COMMAND_HIGH];
// Record that an IPI is being sent.
low.deliveryStatus = 1;
TriggerIntMessage message;
message.destination = high.destination;
message.vector = low.vector;
message.deliveryMode = low.deliveryMode;
message.destMode = low.destMode;
message.level = low.level;
message.trigger = low.trigger;
bool timing = sys->getMemoryMode() == Enums::timing;
switch (low.destShorthand) {
case 0:
intPort->sendMessage(message, timing);
break;
case 1:
panic("Self IPIs aren't implemented.\n");
break;
case 2:
panic("Broadcast including self IPIs aren't implemented.\n");
break;
case 3:
panic("Broadcast excluding self IPIs aren't implemented.\n");
break;
}
}
break; break;
case APIC_LVT_TIMER: case APIC_LVT_TIMER:
case APIC_LVT_THERMAL_SENSOR: case APIC_LVT_THERMAL_SENSOR:

View file

@ -34,6 +34,7 @@
#include "arch/x86/x86_traits.hh" #include "arch/x86/x86_traits.hh"
#include "base/bitunion.hh" #include "base/bitunion.hh"
#include "mem/packet.hh" #include "mem/packet.hh"
#include "mem/packet_access.hh"
#include "mem/request.hh" #include "mem/request.hh"
#include "sim/host.hh" #include "sim/host.hh"