mirror of
https://github.com/AlexAltea/orbital.git
synced 2024-06-16 03:07:58 -04:00
hardware/liverpool: Separate GMC engine into its own device
This commit is contained in:
parent
2fa44ed119
commit
7ddd0d1d6e
|
@ -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)
|
||||
|
|
214
src/orbital/hardware/liverpool/gmc/gmc.cpp
Normal file
214
src/orbital/hardware/liverpool/gmc/gmc.cpp
Normal 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;
|
||||
}
|
||||
}
|
54
src/orbital/hardware/liverpool/gmc/gmc.h
Normal file
54
src/orbital/hardware/liverpool/gmc/gmc.h
Normal 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;
|
||||
};
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue