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

Reply via email to