hardware/liverpool: Separate GMC engine into its own device

This commit is contained in:
Alexandro Sanchez Bach 2021-10-29 22:33:13 +02:00
parent 2fa44ed119
commit 7ddd0d1d6e
5 changed files with 295 additions and 0 deletions

View file

@ -45,6 +45,7 @@ ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/aeolia)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/aeolia/uart)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/hardware/liverpool/gmc)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/software)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/software/sbl)
ORBITAL_SOURCES_APPEND(${ORBITAL_DIR_SOURCES}/orbital/ui)

View file

@ -0,0 +1,214 @@
/**
* AMD Graphics Memory Controller (GMC).
*
* Copyright 2017-2021. Orbital project.
* Released under MIT license. Read LICENSE for more details.
*
* Authors:
* - Alexandro Sanchez Bach <alexandro@phi.nz>
*/
#include "gmc.h"
#include "gmc_7_1_d.h"
#include "gmc_7_1_sh_mask.h"
constexpr U64 VM_PTE_VALID = (1ULL << 0);
constexpr U64 VM_PTE_SYSTEM = (1ULL << 1);
constexpr U64 VM_PTE_SNOOPED = (1ULL << 2);
constexpr U64 VM_PTE_TMZ = (1ULL << 3);
constexpr U64 VM_PTE_PROT_X = (1ULL << 4);
constexpr U64 VM_PTE_PROT_R = (1ULL << 5);
constexpr U64 VM_PTE_PROT_W = (1ULL << 6);
constexpr U64 VM_MAX_ADDR = 0xFFF'FFFFFFFF;
GmcVmSpace::GmcVmSpace(GmcDevice* gmc)
: TranslatorSpace(gmc, VM_MAX_ADDR + 1, nullptr), gmc(*gmc) {}
TranslatorResult GmcVmSpace::translate(Offset offset) {
TranslatorResult res = {};
#if 0
if (!this->base) {
return res;
}
uint64_t pde_base, pde_index, pde;
uint64_t pte_base, pte_index, pte;
pde_base = this->base;
pde_index = (offset >> 23) & 0xFFFFF; // TODO: What's the mask?
pte_index = (offset >> 12) & 0x7FF;
pde = gmc.mem()->read<U64>(pde_base + pde_index * 8);
pte_base = pde & ~UINT64_C(0xFF);
pte = mem->read<U64>(pte_base + pte_index * 8);
// Make translation result
res.base_pa = offset & ~UINT64_C(0xFFF);
res.base_va = offset & +UINT64_C(0xFFF) | (pte & ~UINT64_C(0xFFF));
res.size = 0x1000; // TODO: How to decode this? (set for now to 4 KB pages)
if (pte & VM_PTE_PROT_X) {
res.protection |= TranslatorResult::PROT_X;
}
if (pte & VM_PTE_PROT_R) {
res.protection |= TranslatorResult::PROT_R;
}
if (pte & VM_PTE_PROT_W) {
res.protection |= TranslatorResult::PROT_W;
}
#endif
return res;
}
GmcDevice::GmcDevice(Space* mem, const GmcDeviceConfig& config) : Device(nullptr, config) {
}
void GmcDevice::reset() {
vm_invalidate_request = 0;
}
U32 GmcDevice::mmio_read(U32 index) {
U32 value = 0;
switch (index) {
// VM
case mmVM_INVALIDATE_RESPONSE:
value = vm_invalidate_request;
break;
// MC
case mmMC_BIST_MISMATCH_ADDR:
value = mc_bist_mismatch_addr;
break;
default:
//assert_always("Unimplemented");
break;
}
return value;
}
void GmcDevice::mmio_write(U32 index, U32 value) {
switch (index) {
// VM
case mmVM_L2_CG:
break;
case mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR:
vm_context_base[0] = value << 12;
break;
case mmVM_CONTEXT1_PAGE_TABLE_BASE_ADDR:
vm_context_base[1] = value << 12;
break;
case mmVM_CONTEXT2_PAGE_TABLE_BASE_ADDR:
vm_context_base[2] = value << 12;
break;
case mmVM_CONTEXT3_PAGE_TABLE_BASE_ADDR:
vm_context_base[3] = value << 12;
break;
case mmVM_CONTEXT4_PAGE_TABLE_BASE_ADDR:
vm_context_base[4] = value << 12;
break;
case mmVM_CONTEXT5_PAGE_TABLE_BASE_ADDR:
vm_context_base[5] = value << 12;
break;
case mmVM_CONTEXT6_PAGE_TABLE_BASE_ADDR:
vm_context_base[6] = value << 12;
break;
case mmVM_CONTEXT7_PAGE_TABLE_BASE_ADDR:
vm_context_base[7] = value << 12;
break;
case mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR:
vm_context_base[8] = value << 12;
break;
case mmVM_CONTEXT9_PAGE_TABLE_BASE_ADDR:
vm_context_base[9] = value << 12;
break;
case mmVM_CONTEXT10_PAGE_TABLE_BASE_ADDR:
vm_context_base[10] = value << 12;
break;
case mmVM_CONTEXT11_PAGE_TABLE_BASE_ADDR:
vm_context_base[11] = value << 12;
break;
case mmVM_CONTEXT12_PAGE_TABLE_BASE_ADDR:
vm_context_base[12] = value << 12;
break;
case mmVM_CONTEXT13_PAGE_TABLE_BASE_ADDR:
vm_context_base[13] = value << 12;
break;
case mmVM_CONTEXT14_PAGE_TABLE_BASE_ADDR:
vm_context_base[14] = value << 12;
break;
case mmVM_CONTEXT15_PAGE_TABLE_BASE_ADDR:
vm_context_base[15] = value << 12;
break;
// MC
case mmMC_SHARED_BLACKOUT_CNTL:
case mmMC_SEQ_RESERVE_0_S:
case mmMC_SEQ_RESERVE_1_S:
case mmMC_RPB_ARB_CNTL:
case mmMC_RPB_CID_QUEUE_WR:
case mmMC_RPB_WR_COMBINE_CNTL:
case mmMC_RPB_DBG1:
case mmMC_HUB_WDP_IH:
case mmMC_HUB_WDP_CPF:
case mmMC_HUB_RDREQ_CPC:
case mmMC_HUB_WDP_RLC:
case mmMC_HUB_RDREQ_UVD:
case mmMC_HUB_WRRET_MCDW:
case mmMC_HUB_RDREQ_DMIF:
case mmMC_HUB_RDREQ_CNTL:
case mmMC_HUB_RDREQ_MCDW:
case mmMC_HUB_RDREQ_MCDX:
case mmMC_HUB_RDREQ_MCDY:
case mmMC_HUB_RDREQ_MCDZ:
case mmMC_CITF_CREDITS_ARB_RD:
case mmMC_CITF_CREDITS_ARB_WR:
case mmMC_RD_GRP_EXT:
case mmMC_WR_GRP_EXT:
case mmMC_RD_GRP_LCL:
case mmMC_WR_GRP_LCL:
case mmMC_ARB_TM_CNTL_RD:
case mmMC_ARB_TM_CNTL_WR:
case mmMC_ARB_LAZY0_RD:
case mmMC_ARB_LAZY0_WR:
case mmMC_ARB_AGE_RD:
case mmMC_ARB_AGE_WR:
case mmMC_RD_GRP_GFX:
case mmMC_WR_GRP_GFX:
case mmMC_RD_GRP_SYS:
case mmMC_WR_GRP_SYS:
case mmMC_RD_GRP_OTH:
case mmMC_WR_GRP_OTH:
case mmMC_HUB_RDREQ_CPF:
case mmMC_HUB_WDP_ACPO:
case mmMC_ARB_WTM_CNTL_WR:
case mmMC_HUB_RDREQ_VMC:
case mmMC_ARB_WTM_CNTL_RD:
case mmMC_ARB_RET_CREDITS_WR:
case mmMC_ARB_LM_WR:
case mmMC_ARB_LM_RD:
case mmMC_ARB_RET_CREDITS_RD:
case mmMC_HUB_WDP_VCEU:
case mmMC_HUB_WDP_XDMAM:
case mmMC_HUB_WDP_XDMA:
case mmMC_HUB_RDREQ_XDMAM:
case mmMC_ARB_RET_CREDITS2:
case mmMC_SHARED_CHMAP:
case mmMC_ARB_SQM_CNTL:
case mmMC_XPB_CLK_GAT:
case mmMC_HUB_MISC_SIP_CG:
case mmMC_HUB_MISC_HUB_CG:
case mmMC_HUB_MISC_VM_CG:
case mmMC_CITF_MISC_RD_CG:
case mmMC_CITF_MISC_WR_CG:
case mmMC_CITF_MISC_VM_CG:
break;
case mmMC_BIST_MISMATCH_ADDR:
mc_bist_mismatch_addr = value;
break;
default:
break;
}
}

View file

@ -0,0 +1,54 @@
/**
* AMD Graphics Memory Controller (GMC).
*
* Copyright 2017-2021. Orbital project.
* Released under MIT license. Read LICENSE for more details.
*
* Authors:
* - Alexandro Sanchez Bach <alexandro@phi.nz>
*/
#pragma once
#include <orbital/core.h>
#include <orbital/offset_range.h>
#include <array>
// Forward declarations
class GmcDevice;
constexpr auto GMC_VM_COUNT = 16;
constexpr auto GMC_MMIO_VM = OffsetRange(0x500, 0x78);
constexpr auto GMC_MMIO_MC = OffsetRange(0x800, 0x300);
class GmcVmSpace : public TranslatorSpace {
public:
GmcVmSpace(GmcDevice* gmc);
virtual TranslatorResult translate(Offset off) = 0;
private:
U64 base = 0;
GmcDevice& gmc;
};
struct GmcDeviceConfig : DeviceConfig {
};
class GmcDevice final : public Device {
public:
GmcDevice(Space* mem, const GmcDeviceConfig& config = {});
void reset() override;
U32 mmio_read(U32 index);
void mmio_write(U32 index, U32 value);
private:
U32 vm_invalidate_request;
U64 vm_context_base[GMC_VM_COUNT];
U32 mc_bist_mismatch_addr;
Space* mem;
};

View file

@ -25,6 +25,9 @@
#include "smu/smu_7_1_2_sh_mask.h"
#include "sam/sam.h"
// Engines
#include "gmc/gmc.h"
// Logging
#define DEBUG_GC 0
#define DPRINTF(...) \
@ -62,6 +65,10 @@ LiverpoolGCDevice::LiverpoolGCDevice(PCIeBus* bus, const LiverpoolGCDeviceConfig
register_bar(4, PCI_BASE_ADDRESS_SPACE_IO, space_pio);
register_bar(5, PCI_BASE_ADDRESS_SPACE_MEM, space_mmio);
// Create engines
GmcDeviceConfig gmc_config = {};
gmc = std::make_unique<GmcDevice>(bus->space_mem(), gmc_config);
reset();
}
@ -120,6 +127,14 @@ U64 LiverpoolGCDevice::mmio_read(U64 addr, U64 size) {
value = (U32&)config_data[addr];
return value;
}
else if (GMC_MMIO_VM.contains(index)) {
value = gmc->mmio_read(index);
return value;
}
else if (GMC_MMIO_MC.contains(index)) {
value = gmc->mmio_read(index);
return value;
}
switch (index) {
// SMU
@ -191,6 +206,12 @@ void LiverpoolGCDevice::mmio_write(U64 addr, U64 value, U64 size) {
(U32&)config_data[addr] = value;
return;
}
else if (GMC_MMIO_VM.contains(index)) {
gmc->mmio_write(index, value);
}
else if (GMC_MMIO_MC.contains(index)) {
gmc->mmio_write(index, value);
}
// Indirect registers
switch (index) {
@ -302,6 +323,7 @@ void LiverpoolGCDevice::mmio_write(U64 addr, U64 value, U64 size) {
case mmVM_L2_CG:
break;
#endif
// Simple registers
case mmSAM_IX_INDEX:
case mmSAM_GPR_SCRATCH_0:

View file

@ -16,6 +16,7 @@
#include <memory>
// Forward declarations
class GmcDevice;
class SAMUDevice;
constexpr auto LIVERPOOL_GC_DEV = 0x1;
@ -62,6 +63,9 @@ private:
U64 mmio_read(U64 addr, U64 size);
void mmio_write(U64 addr, U64 value, U64 size);
// GMC
std::unique_ptr<GmcDevice> gmc;
// SAMU
std::unique_ptr<SAMUDevice> sam;
std::array<U32, 0x80> sam_ix;