diff --git a/src/dev/amdgpu/amdgpu_nbio.cc b/src/dev/amdgpu/amdgpu_nbio.cc index 89b1682631..ec44f16250 100644 --- a/src/dev/amdgpu/amdgpu_nbio.cc +++ b/src/dev/amdgpu/amdgpu_nbio.cc @@ -53,7 +53,21 @@ AMDGPUNbio::setGPUDevice(AMDGPUDevice *gpu_device) void AMDGPUNbio::readMMIO(PacketPtr pkt, Addr offset) { + // For Vega10 we rely on the golden values in an MMIO trace. Return + // immediately as to not clobber those values. + if (gpuDevice->getGfxVersion() == GfxVersion::gfx900) { + if (offset == AMDGPU_PCIE_DATA || offset == AMDGPU_PCIE_DATA2) { + return; + } + } + switch (offset) { + // PCIE_DATA, PCIE_DATA2, PCIE_INDEX, and PCIE_INDEX2 handle "indirect + // "register reads/writes from the driver. This provides a way to read + // any register by providing a 32-bit address to one of the two INDEX + // registers and then reading the corresponding DATA register. See: + // https://github.com/ROCm/ROCK-Kernel-Driver/blob/roc-6.0.x/drivers/ + // gpu/drm/amd/amdgpu/amdgpu_device.c#L459 case AMDGPU_PCIE_DATA: { uint32_t value = gpuDevice->getRegVal(pcie_index_reg); @@ -62,19 +76,20 @@ AMDGPUNbio::readMMIO(PacketPtr pkt, Addr offset) pkt->setLE(value); } break; - // This is a PCIe status register. At some point during driver init - // the driver checks that interrupts are enabled. This is only - // checked once, so if the MMIO trace does not exactly line up with - // what the driver is doing in gem5, this may still have the first - // bit zero causing driver to fail. Therefore, we always set this - // bit to one as there is no harm to do so. case AMDGPU_PCIE_DATA2: { - uint32_t value = pkt->getLE() | 0x1; - DPRINTF(AMDGPUDevice, "Marking interrupts enabled: %#lx\n", value); + uint32_t value = gpuDevice->getRegVal(pcie_index2_reg); + DPRINTF(AMDGPUDevice, "Read PCIe index2 %lx data2 %x\n", + pcie_index2_reg, value); pkt->setLE(value); } break; + case AMDGPU_PCIE_INDEX: + pkt->setLE(pcie_index_reg); + break; + case AMDGPU_PCIE_INDEX2: + pkt->setLE(pcie_index2_reg); + break; case AMDGPU_MM_DATA: pkt->setLE(gpuDevice->getRegVal(mm_index_reg)); break; @@ -130,14 +145,24 @@ AMDGPUNbio::writeMMIO(PacketPtr pkt, Addr offset) DPRINTF(AMDGPUDevice, "MM write to reg %#lx data %#lx\n", mm_index_reg, pkt->getLE()); gpuDevice->setRegVal(AMDGPU_MM_DATA, pkt->getLE()); + // PCIE_DATA, PCIE_DATA2, PCIE_INDEX, and PCIE_INDEX2 handle "indirect + // "register reads/writes from the driver. This provides a way to read + // any register by providing a 32-bit address to one of the two INDEX + // registers and then reading the corresponding DATA register. See: + // https://github.com/ROCm/ROCK-Kernel-Driver/blob/roc-6.0.x/drivers/ + // gpu/drm/amd/amdgpu/amdgpu_device.c#L459 } else if (offset == AMDGPU_PCIE_INDEX) { assert(pkt->getSize() == 4); - pcie_index_reg = insertBits(pcie_index_reg, 31, 0, - pkt->getLE()); + pcie_index_reg = pkt->getLE(); + } else if (offset == AMDGPU_PCIE_DATA) { + assert(pkt->getSize() == 4); + gpuDevice->setRegVal(pcie_index_reg, pkt->getLE()); } else if (offset == AMDGPU_PCIE_INDEX2) { assert(pkt->getSize() == 4); - pcie_index_reg = insertBits(pcie_index_reg, 63, 32, - pkt->getLE()); + pcie_index2_reg = pkt->getLE(); + } else if (offset == AMDGPU_PCIE_DATA2) { + assert(pkt->getSize() == 4); + gpuDevice->setRegVal(pcie_index2_reg, pkt->getLE()); } else if (offset == AMDGPU_MP0_SMN_C2PMSG_35) { // See psp_v3_1_bootloader_load_sos in amdgpu driver code. if (pkt->getLE() == 0x10000) { diff --git a/src/dev/amdgpu/amdgpu_nbio.hh b/src/dev/amdgpu/amdgpu_nbio.hh index 0d839d0e22..87afb02c41 100644 --- a/src/dev/amdgpu/amdgpu_nbio.hh +++ b/src/dev/amdgpu/amdgpu_nbio.hh @@ -110,7 +110,8 @@ class AMDGPUNbio * Driver initialization sequence helper variables. */ uint64_t mm_index_reg = 0; - uint64_t pcie_index_reg = 0; + uint32_t pcie_index_reg = 0; + uint32_t pcie_index2_reg = 0; std::unordered_map triggered_reads; /*