From 38bb440383722b031b061f6f3b71daaa270621ae Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 20 Jan 2022 22:27:25 -0800 Subject: [PATCH] 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 Maintainer: Gabe Black Tested-by: kokoro --- src/arch/x86/x86_traits.hh | 3 +++ src/dev/x86/i8259.cc | 19 +++++++++++++++++-- src/dev/x86/i8259.hh | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index 9e9882063b..e4a639277c 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -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) { diff --git a/src/dev/x86/i8259.cc b/src/dev/x86/i8259.cc index bd6d18c814..c78e12967f 100644 --- a/src/dev/x86/i8259.cc +++ b/src/dev/x86/i8259.cc @@ -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(getVector()); + } + switch(pkt->getAddr() - pioAddr) { case 0x0: if (readIRR) { DPRINTF(I8259, "Reading IRR as %#x.\n", IRR); diff --git a/src/dev/x86/i8259.hh b/src/dev/x86/i8259.hh index dcc59875cc..afd4894532 100644 --- a/src/dev/x86/i8259.hh +++ b/src/dev/x86/i8259.hh @@ -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;