Gabe Black has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/57017 )
Change subject: arch-x86,dev: Handle PCI config addresses in an x86 PCI
host.
......................................................................
arch-x86,dev: Handle PCI config addresses in an x86 PCI host.
Stop handling it in the x86 TLB.
Change-Id: I9d5d44e614e29cd6bcdac9b0efe75ffe08af2f5f
---
M src/arch/amdgpu/common/tlb.cc
M src/arch/x86/kvm/x86_cpu.cc
M src/arch/x86/regs/misc.hh
M src/arch/x86/tlb.cc
M src/arch/x86/x86_traits.hh
M src/dev/x86/Pc.py
M src/dev/x86/SConscript
A src/dev/x86/pci_host.cc
A src/dev/x86/pci_host.hh
9 files changed, 191 insertions(+), 129 deletions(-)
diff --git a/src/arch/amdgpu/common/tlb.cc b/src/arch/amdgpu/common/tlb.cc
index 127aa02..6b98363 100644
--- a/src/arch/amdgpu/common/tlb.cc
+++ b/src/arch/amdgpu/common/tlb.cc
@@ -276,26 +276,6 @@
- namespace
- {
-
- Cycles
- localMiscRegAccess(bool read, MiscRegIndex regNum,
- ThreadContext *tc, PacketPtr pkt)
- {
- if (read) {
- RegVal data = htole(tc->readMiscReg(regNum));
- // Make sure we don't trot off the end of data.
- pkt->setData((uint8_t *)&data);
- } else {
- RegVal data = htole(tc->readMiscRegNoEffect(regNum));
- tc->setMiscReg(regNum, letoh(data));
- }
- return Cycles(1);
- }
-
- } // anonymous namespace
-
Fault
GpuTLB::translateInt(bool read, const RequestPtr &req, ThreadContext
*tc)
{
@@ -311,29 +291,8 @@
// Make sure the address fits in the expected 16 bit IO address
// space.
assert(!(IOPort & ~0xFFFF));
- if (IOPort == 0xCF8 && req->getSize() == 4) {
- req->setLocalAccessor(
- [read](ThreadContext *tc, PacketPtr pkt)
- {
- return localMiscRegAccess(
- read, MISCREG_PCI_CONFIG_ADDRESS, tc, pkt);
- }
- );
- } else if ((IOPort & ~mask(2)) == 0xCFC) {
- req->setFlags(Request::UNCACHEABLE |
Request::STRICT_ORDER);
- Addr configAddress =
- tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
- if (bits(configAddress, 31, 31)) {
- req->setPaddr(PhysAddrPrefixPciConfig |
- mbits(configAddress, 30, 2) |
- (IOPort & mask(2)));
- } else {
- req->setPaddr(PhysAddrPrefixIO | IOPort);
- }
- } else {
- req->setFlags(Request::UNCACHEABLE |
Request::STRICT_ORDER);
- req->setPaddr(PhysAddrPrefixIO | IOPort);
- }
+ req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
+ req->setPaddr(PhysAddrPrefixIO | IOPort);
return NoFault;
} else {
panic("Access to unrecognized internal address space %#x.\n",
diff --git a/src/arch/x86/kvm/x86_cpu.cc b/src/arch/x86/kvm/x86_cpu.cc
index af041a5..fbfda62 100644
--- a/src/arch/x86/kvm/x86_cpu.cc
+++ b/src/arch/x86/kvm/x86_cpu.cc
@@ -55,9 +55,6 @@
#define MSR_TSC 0x10
-#define IO_PCI_CONF_ADDR 0xCF8
-#define IO_PCI_CONF_DATA_BASE 0xCFC
-
// Task segment type of an inactive 32-bit or 64-bit task
#define SEG_SYS_TYPE_TSS_AVAILABLE 9
// Task segment type of an active 32-bit or 64-bit task
@@ -1319,30 +1316,7 @@
DPRINTF(KvmIO, "KVM-x86: Handling IO instruction (%s) (port: 0x%x)\n",
(isWrite ? "out" : "in"), kvm_run.io.port);
- /* Vanilla gem5 handles PCI discovery in the TLB(!). Since we
- * don't use the TLB component, we need to intercept and handle
- * the PCI configuration space IO ports here.
- *
- * The IO port PCI discovery mechanism uses one address register
- * and one data register. We map the address register to a misc
- * reg and use that to re-route data register accesses to the
- * right location in the PCI configuration space.
- */
- if (port == IO_PCI_CONF_ADDR) {
- handleIOMiscReg32(MISCREG_PCI_CONFIG_ADDRESS);
- return 0;
- } else if ((port & ~0x3) == IO_PCI_CONF_DATA_BASE) {
- Addr pciConfigAddr(tc->readMiscRegNoEffect(
- MISCREG_PCI_CONFIG_ADDRESS));
- if (pciConfigAddr & 0x80000000) {
- pAddr = X86ISA::x86PciConfigAddress((pciConfigAddr &
0x7ffffffc) |
- (port & 0x3));
- } else {
- pAddr = X86ISA::x86IOAddress(port);
- }
- } else {
- pAddr = X86ISA::x86IOAddress(port);
- }
+ pAddr = X86ISA::x86IOAddress(port);
const MemCmd cmd(isWrite ? MemCmd::WriteReq : MemCmd::ReadReq);
// Temporarily lock and migrate to the device event queue to
diff --git a/src/arch/x86/regs/misc.hh b/src/arch/x86/regs/misc.hh
index 89997dc..1923ff2 100644
--- a/src/arch/x86/regs/misc.hh
+++ b/src/arch/x86/regs/misc.hh
@@ -398,9 +398,6 @@
MISCREG_APIC_BASE,
- // "Fake" MSRs for internally implemented devices
- MISCREG_PCI_CONFIG_ADDRESS,
-
NUM_MISCREGS
};
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 0db17e5..6ef29dd 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -172,28 +172,6 @@
}
}
-namespace
-{
-
-Cycles
-localMiscRegAccess(bool read, MiscRegIndex regNum,
- ThreadContext *tc, PacketPtr pkt)
-{
- if (read) {
- RegVal data = htole(tc->readMiscReg(regNum));
- assert(pkt->getSize() <= sizeof(RegVal));
- pkt->setData((uint8_t *)&data);
- } else {
- RegVal data = htole(tc->readMiscRegNoEffect(regNum));
- assert(pkt->getSize() <= sizeof(RegVal));
- pkt->writeData((uint8_t *)&data);
- tc->setMiscReg(regNum, letoh(data));
- }
- return Cycles(1);
-}
-
-} // anonymous namespace
-
Fault
TLB::translateInt(bool read, RequestPtr req, ThreadContext *tc)
{
@@ -208,30 +186,8 @@
// Make sure the address fits in the expected 16 bit IO address
// space.
assert(!(IOPort & ~0xFFFF));
- if (IOPort == 0xCF8 && req->getSize() == 4) {
- req->setPaddr(req->getVaddr());
- req->setLocalAccessor(
- [read](ThreadContext *tc, PacketPtr pkt)
- {
- return localMiscRegAccess(
- read, MISCREG_PCI_CONFIG_ADDRESS, tc, pkt);
- }
- );
- } else if ((IOPort & ~mask(2)) == 0xCFC) {
- req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
- Addr configAddress =
- tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
- if (bits(configAddress, 31, 31)) {
- req->setPaddr(PhysAddrPrefixPciConfig |
- mbits(configAddress, 30, 2) |
- (IOPort & mask(2)));
- } else {
- req->setPaddr(PhysAddrPrefixIO | IOPort);
- }
- } else {
- req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
- req->setPaddr(PhysAddrPrefixIO | IOPort);
- }
+ req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
+ req->setPaddr(PhysAddrPrefixIO | IOPort);
return NoFault;
} else {
panic("Access to unrecognized internal address space %#x.\n",
diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh
index 113326e..a0cac21 100644
--- a/src/arch/x86/x86_traits.hh
+++ b/src/arch/x86/x86_traits.hh
@@ -61,7 +61,6 @@
constexpr Addr IntAddrPrefixIO = 0x300000000ULL;
constexpr Addr PhysAddrPrefixIO = 0x8000000000000000ULL;
-constexpr Addr PhysAddrPrefixPciConfig = 0xC000000000000000ULL;
constexpr Addr PhysAddrPrefixLocalAPIC = 0x2000000000000000ULL;
constexpr Addr PhysAddrPrefixInterrupts = 0xA000000000000000ULL;
// Each APIC gets two pages. One page is used for local apics to field
@@ -78,12 +77,6 @@
}
static constexpr inline Addr
-x86PciConfigAddress(const uint32_t addr)
-{
- return PhysAddrPrefixPciConfig | addr;
-}
-
-static constexpr inline Addr
x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
{
assert(addr < (1 << 12));
diff --git a/src/dev/x86/Pc.py b/src/dev/x86/Pc.py
index 42c35c1..1e72925 100644
--- a/src/dev/x86/Pc.py
+++ b/src/dev/x86/Pc.py
@@ -40,11 +40,16 @@
return IO_address_space_base + port;
class PcPciHost(GenericPciHost):
- conf_base = 0xC000000000000000
- conf_size = "16MiB"
+ type = 'PcPciHost'
+ cxx_header = 'dev/x86/pci_host.hh'
+ cxx_class = 'gem5::PcPciHost'
pci_pio_base = 0x8000000000000000
+ # Dummy values. Our config space isn't memory mapped currently.
+ conf_base = 0
+ conf_size = 0
+
class Pc(Platform):
type = 'Pc'
cxx_header = "dev/x86/pc.hh"
diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript
index a58c22e..46f39a0 100644
--- a/src/dev/x86/SConscript
+++ b/src/dev/x86/SConscript
@@ -28,8 +28,9 @@
Import('*')
-SimObject('Pc.py', sim_objects=['Pc'], tags='x86 isa')
+SimObject('Pc.py', sim_objects=['Pc', 'PcPciHost'], tags='x86 isa')
Source('pc.cc', tags='x86 isa')
+Source('pci_host.cc', tags='x86 isa')
SimObject('SouthBridge.py', sim_objects=['SouthBridge'], tags='x86 isa')
Source('south_bridge.cc', tags='x86 isa')
diff --git a/src/dev/x86/pci_host.cc b/src/dev/x86/pci_host.cc
new file mode 100644
index 0000000..81c8b97
--- /dev/null
+++ b/src/dev/x86/pci_host.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2022 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "dev/x86/pci_host.hh"
+
+#include <utility>
+
+#include "arch/x86/x86_traits.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+
+namespace gem5
+{
+
+AddrRangeList
+PcPciHost::getAddrRanges() const
+{
+ // Don't include the config range the GenericPciHost wants to include.
+ AddrRangeList ranges;
+ ranges.emplace_back(ConfAddrRange);
+ if (bits(confAddr, 31))
+ ranges.emplace_back(ConfDataRange);
+ return ranges;
+}
+
+Tick
+PcPciHost::read(PacketPtr pkt)
+{
+ const Addr addr = pkt->getAddr();
+ const Addr size = pkt->getSize();
+
+ if (addr == ConfAddrAddr && size == 4) {
+ pkt->makeAtomicResponse();
+ pkt->setLE<uint32_t>(confAddr);
+ return 0;
+ } else if (ConfDataRange.contains(addr)) {
+ Addr config_address = bits(confAddr, 30, 0);
+ replaceBits(config_address, 1, 0, addr);
+ const auto &[bdf, offset] = decodeAddress(config_address);
+ return readConfig(bdf, offset, pkt);
+ } else {
+ pkt->makeAtomicResponse();
+ auto *pkt_data = pkt->getPtr<uint8_t>();
+ std::fill(pkt_data, pkt_data + size, 0xFF);
+ return 0;
+ }
+}
+
+Tick
+PcPciHost::write(PacketPtr pkt)
+{
+ const Addr addr = pkt->getAddr();
+ const Addr size = pkt->getSize();
+
+ if (addr == ConfAddrAddr && size == 4) {
+ pkt->makeAtomicResponse();
+ uint32_t old_conf_addr = confAddr;
+ confAddr = pkt->getLE<uint32_t>();
+
+ // If the config space window opened or closed, let upstream know.
+ if (bits(old_conf_addr, 31) != bits(confAddr, 31))
+ pioPort.sendRangeChange();
+
+ return 0;
+ } else if (ConfDataRange.contains(addr)) {
+ Addr config_address = bits(confAddr, 30, 0);
+ replaceBits(config_address, 1, 0, addr);
+ const auto &[bdf, offset] = decodeAddress(config_address);
+ return writeConfig(bdf, offset, pkt);
+ } else {
+ pkt->makeAtomicResponse();
+ return 0;
+ }
+}
+
+} // namespace gem5
diff --git a/src/dev/x86/pci_host.hh b/src/dev/x86/pci_host.hh
new file mode 100644
index 0000000..bff1e6c
--- /dev/null
+++ b/src/dev/x86/pci_host.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_X86_PCI_HOST_HH__
+#define __DEV_X86_PCI_HOST_HH__
+
+#include "arch/x86/x86_traits.hh"
+#include "base/addr_range.hh"
+#include "dev/pci/host.hh"
+#include "params/PcPciHost.hh"
+
+namespace gem5
+{
+
+class PcPciHost : public GenericPciHost
+{
+ private:
+ uint32_t confAddr = 0;
+
+ static constexpr Addr ConfAddrAddr = X86ISA::x86IOAddress(0xCF8);
+ // This should technically only respond to 4 byte accesses.
+ static const inline AddrRange ConfAddrRange =
+ {ConfAddrAddr, ConfAddrAddr + 4};
+
+ static constexpr Addr ConfDataAddr = X86ISA::x86IOAddress(0xCFC);
+ static const inline AddrRange ConfDataRange =
+ {ConfDataAddr, ConfDataAddr + 4};
+
+ public:
+ PARAMS(PcPciHost);
+
+ PcPciHost(const Params &p) : GenericPciHost(p) {}
+
+ AddrRangeList getAddrRanges() const override;
+
+ Tick read(PacketPtr pkt) override;
+ Tick write(PacketPtr pkt) override;
+};
+
+} // namespace gem5
+
+#endif // __DEV_X86_PCI_HOST_HH__
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/57017
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I9d5d44e614e29cd6bcdac9b0efe75ffe08af2f5f
Gerrit-Change-Number: 57017
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s