arch-x86,dev: Add an INTA like transaction for I8259.
In a real system, once a CPU receives an interrupt of type ExtInt, it will send an INTA message out to the I8259 sytle interrupt controllers to read the vector for that interrupt. In ye-olden-times, that would literally mean the I8259 would be in charge of the bus and would write the eight bit vector for the CPU to read. In more modern systems, the vector is transported on the system interconnect using a special message. To better approximate a real system, and to make the interrupt controllers more modular and agnostic (so the IO APIC doesn't have a I8259 pointer within it, for instance), this change adds a new special address which the I8259 can respond to on reads which will act as if it received an INTA message, and the read data will be the interrupt vector. Only the master controller, or a single device, will respond to this address, and because of its value and the fact that it's beyond the end of the 16 bit IO port address space's effective range but still within it, that address won't be generated by any other activity other than possibly a bogus address. Also by putting the special address in the IO port address space, that will make it easier to ensure that it's within the range of addresses which are routed towards the I8259 which operates off the IO port bus. This address is not yet actually used by the IO APIC or local APIC but will be shortly. Change-Id: Ib73ab4ee08531028d3540570594c552f39053a40 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/55694 Reviewed-by: Gabe Black <gabe.black@gmail.com> Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -72,6 +72,9 @@ namespace X86ISA
|
||||
// accesses from the CPU, and the other is for all APICs to communicate.
|
||||
const Addr PhysAddrAPICRangeSize = 1 << 12;
|
||||
|
||||
// Put this in an unused part of the 16 bit IO port address space.
|
||||
const Addr PhysAddrIntA = 0x8000000100000000ULL;
|
||||
|
||||
static inline Addr
|
||||
x86IOAddress(const uint32_t port)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "dev/x86/i8259.hh"
|
||||
|
||||
#include "arch/x86/x86_traits.hh"
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "debug/I8259.hh"
|
||||
@@ -62,6 +63,17 @@ X86ISA::I8259::I8259(const Params &p)
|
||||
state = false;
|
||||
}
|
||||
|
||||
AddrRangeList
|
||||
X86ISA::I8259::getAddrRanges() const
|
||||
{
|
||||
AddrRangeList ranges = BasicPioDevice::getAddrRanges();
|
||||
if (mode == enums::I8259Master || mode == enums::I8259Single) {
|
||||
// Listen for INTA messages.
|
||||
ranges.push_back(RangeSize(PhysAddrIntA, 1));
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void
|
||||
X86ISA::I8259::init()
|
||||
{
|
||||
@@ -75,8 +87,11 @@ Tick
|
||||
X86ISA::I8259::read(PacketPtr pkt)
|
||||
{
|
||||
assert(pkt->getSize() == 1);
|
||||
switch(pkt->getAddr() - pioAddr)
|
||||
{
|
||||
if (pkt->getAddr() == PhysAddrIntA) {
|
||||
assert(mode == enums::I8259Master || mode == enums::I8259Single);
|
||||
pkt->setLE<uint8_t>(getVector());
|
||||
}
|
||||
switch(pkt->getAddr() - pioAddr) {
|
||||
case 0x0:
|
||||
if (readIRR) {
|
||||
DPRINTF(I8259, "Reading IRR as %#x.\n", IRR);
|
||||
|
||||
@@ -99,6 +99,8 @@ class I8259 : public BasicPioDevice
|
||||
return BasicPioDevice::getPort(if_name, idx);
|
||||
}
|
||||
|
||||
AddrRangeList getAddrRanges() const override;
|
||||
|
||||
Tick read(PacketPtr pkt) override;
|
||||
Tick write(PacketPtr pkt) override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user