hardware/liverpool: Finished GMC VM translator space

This commit is contained in:
Alexandro Sanchez Bach 2021-10-30 16:11:18 +02:00
parent eced42c9a0
commit 2aade82d74
2 changed files with 51 additions and 66 deletions

View file

@ -13,6 +13,8 @@
#include "gmc_7_1_d.h"
#include "gmc_7_1_sh_mask.h"
constexpr auto GMC_VM_COUNT = 16;
constexpr U64 VM_PTE_VALID = (1ULL << 0);
constexpr U64 VM_PTE_SYSTEM = (1ULL << 1);
constexpr U64 VM_PTE_SNOOPED = (1ULL << 2);
@ -21,14 +23,14 @@ 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;
constexpr U64 VM_MAX_ADDR = 0xFF'FFFFFFFF;
GmcVmSpace::GmcVmSpace(GmcDevice* gmc)
: TranslatorSpace(gmc, VM_MAX_ADDR + 1, nullptr), gmc(*gmc) {}
GmcVmSpace::GmcVmSpace(Space* gmc_mem)
: TranslatorSpace(nullptr, VM_MAX_ADDR + 1, gmc_mem) {
}
TranslatorResult GmcVmSpace::translate(Offset offset) {
TranslatorResult res = {};
#if 0
if (!this->base) {
return res;
}
@ -38,9 +40,9 @@ TranslatorResult GmcVmSpace::translate(Offset offset) {
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);
pde = child->read<U64>(pde_base + pde_index * 8);
pte_base = pde & ~UINT64_C(0xFF);
pte = mem->read<U64>(pte_base + pte_index * 8);
pte = child->read<U64>(pte_base + pte_index * 8);
// Make translation result
res.base_pa = offset & ~UINT64_C(0xFFF);
@ -55,24 +57,36 @@ TranslatorResult GmcVmSpace::translate(Offset offset) {
if (pte & VM_PTE_PROT_W) {
res.protection |= TranslatorResult::PROT_W;
}
#endif
return res;
}
GmcDevice::GmcDevice(Space* mem, const GmcDeviceConfig& config) : Device(nullptr, config) {
GmcDevice::GmcDevice(Space* mem, const GmcDeviceConfig& config)
: Device(nullptr, config), vm_contexts(GMC_VM_COUNT, { mem }) {
reset();
}
void GmcDevice::reset() {
vm_invalidate_request = 0;
vm_invalidate_response = 0;
}
U32 GmcDevice::mmio_read(U32 index) {
U32 value = 0;
if (index >= mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR &&
index <= mmVM_CONTEXT7_PAGE_TABLE_BASE_ADDR) {
const U32 vmid = index - mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR;
return vm_contexts[vmid].base >> 12;
}
if (index >= mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR &&
index <= mmVM_CONTEXT15_PAGE_TABLE_BASE_ADDR) {
const U32 vmid = 8 + index - mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR;
return vm_contexts[vmid].base >> 12;
}
U32 value = 0;
switch (index) {
// VM
case mmVM_INVALIDATE_RESPONSE:
value = vm_invalidate_request;
value = vm_invalidate_response;
break;
// MC
@ -89,57 +103,25 @@ U32 GmcDevice::mmio_read(U32 index) {
}
void GmcDevice::mmio_write(U32 index, U32 value) {
if (index >= mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR &&
index <= mmVM_CONTEXT7_PAGE_TABLE_BASE_ADDR) {
const U32 vmid = index - mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR;
vm_contexts[vmid].base = value << 12;
return;
}
if (index >= mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR &&
index <= mmVM_CONTEXT15_PAGE_TABLE_BASE_ADDR) {
const U32 vmid = 8 + index - mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR;
vm_contexts[vmid].base = value << 12;
return;
}
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;
case mmVM_INVALIDATE_REQUEST:
vm_invalidate_response = value;
break;
// MC
@ -212,3 +194,7 @@ void GmcDevice::mmio_write(U32 index, U32 value) {
break;
}
}
GmcVmSpace& GmcDevice::get(U32 vmid) {
return vm_contexts[vmid];
}

View file

@ -18,20 +18,18 @@
// 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 {
friend class GmcDevice;
public:
GmcVmSpace(GmcDevice* gmc);
GmcVmSpace(Space* gmc_mem);
virtual TranslatorResult translate(Offset off) = 0;
TranslatorResult translate(Offset off) override;
private:
U64 base = 0;
GmcDevice& gmc;
};
struct GmcDeviceConfig : DeviceConfig {
@ -46,9 +44,10 @@ public:
U32 mmio_read(U32 index);
void mmio_write(U32 index, U32 value);
GmcVmSpace& get(U32 vmid);
private:
U32 vm_invalidate_request;
U64 vm_context_base[GMC_VM_COUNT];
std::vector<GmcVmSpace> vm_contexts;
U32 vm_invalidate_response;
U32 mc_bist_mismatch_addr;
Space* mem;
};