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:
Gabe Black
2022-01-20 22:27:25 -08:00
parent 64d1297d86
commit 38bb440383
3 changed files with 22 additions and 2 deletions

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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;