ppcmmu.c: restructure and clean up.

This commit is contained in:
Maxim Poliakovski 2021-08-19 13:31:13 +02:00
parent c5f45c6f9a
commit 2a79c9a63c
3 changed files with 18 additions and 87 deletions

View File

@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/** @file PowerPC Memory management unit emulation. */
/** @file PowerPC Memory Management Unit emulation. */
/* TODO:
- implement TLB
@ -181,13 +181,6 @@ public:
};
#endif
/** Temporary TLB test variables. */
bool MemAccessType; // true - memory, false - I/O
bool Unaligned_crosspage = false;
uint64_t MemAddr = 0;
MMIODevice *Device = 0;
uint32_t DevOffset = 0;
/** remember recently used physical memory regions for quicker translation. */
AddressMapEntry last_read_area = {0xFFFFFFFF, 0xFFFFFFFF};
@ -215,16 +208,6 @@ static inline T read_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr)
dmem_reads_total++;
#endif
if (!MemAccessType) {
LOG_F(ERROR, "TLB real memory access expected!");
}
if ((mru_rgn->mem_ptr + (addr - mru_rgn->start)) != (uint8_t *)MemAddr) {
LOG_F(ERROR, "TLB address mismatch! Expected: 0x%llx, got: 0x%llx",
(uint64_t)(mru_rgn->mem_ptr + (addr - mru_rgn->start)),
(uint64_t)MemAddr);
}
switch(sizeof(T)) {
case 1:
return *(mru_rgn->mem_ptr + (addr - mru_rgn->start));
@ -252,14 +235,6 @@ static inline T read_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr)
#ifdef MMU_PROFILING
iomem_reads_total++;
#endif
if (MemAccessType) {
LOG_F(ERROR, "TLB I/O memory access expected!");
}
if (mru_rgn->devobj != Device || (addr - mru_rgn->start) != DevOffset) {
LOG_F(ERROR, "TLB MMIO access mismatch! Expected: 0x%X, got: 0x%X",
addr - mru_rgn->start, DevOffset);
}
return (mru_rgn->devobj->read(mru_rgn->start,
addr - mru_rgn->start, sizeof(T)));
@ -287,20 +262,6 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val
dmem_writes_total++;
#endif
#if 1
if (!MemAccessType) {
LOG_F(ERROR, "TLB real memory access expected!");
}
if (!is_aligned && Unaligned_crosspage) {
LOG_F(WARNING, "Unaligned cross-page access ignored!");
} else if ((mru_rgn->mem_ptr + (addr - mru_rgn->start)) != (uint8_t *)MemAddr) {
LOG_F(ERROR, "TLB address mismatch! Expected: 0x%llx, got: 0x%llx",
(uint64_t)(mru_rgn->mem_ptr + (addr - mru_rgn->start)),
(uint64_t)MemAddr);
}
#endif
switch(sizeof(T)) {
case 1:
*(mru_rgn->mem_ptr + (addr - mru_rgn->start)) = value;
@ -333,17 +294,6 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val
iomem_writes_total++;
#endif
#if 1
if (MemAccessType) {
LOG_F(ERROR, "TLB I/O memory access expected!");
}
if (mru_rgn->devobj != Device || (addr - mru_rgn->start) != DevOffset) {
LOG_F(ERROR, "TLB MMIO access mismatch! Expected: 0x%X, got: 0x%X",
addr - mru_rgn->start, DevOffset);
}
#endif
mru_rgn->devobj->write(mru_rgn->start, addr - mru_rgn->start, value,
sizeof(T));
} else {
@ -375,6 +325,10 @@ void ppc_set_cur_instruction(const uint8_t* ptr) {
bool gTLBFlushBatEntries = false;
bool gTLBFlushPatEntries = false;
// Forward declarations.
void tlb_flush_bat_entries();
void tlb_flush_pat_entries();
void ibat_update(uint32_t bat_reg) {
int upper_reg_num;
uint32_t bl, hi_mask;
@ -527,7 +481,7 @@ static bool search_pteg(
return false;
}
static PATResult page_address_translate(uint32_t la, bool is_instr_fetch,
static PATResult page_address_translation(uint32_t la, bool is_instr_fetch,
unsigned msr_pr, int is_write)
{
uint32_t sr_val, page_index, pteg_hash1, vsid, pte_word2;
@ -598,7 +552,7 @@ static PATResult page_address_translate(uint32_t la, bool is_instr_fetch,
}
/** PowerPC-style MMU instruction address translation. */
static uint32_t ppc_mmu_instr_translate(uint32_t la) {
static uint32_t mmu_instr_translation(uint32_t la) {
uint32_t pa; /* translated physical address */
bool bat_hit = false;
@ -631,7 +585,7 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la) {
/* page address translation */
if (!bat_hit) {
PATResult pat_res = page_address_translate(la, true, msr_pr, 0);
PATResult pat_res = page_address_translation(la, true, msr_pr, 0);
pa = pat_res.phys;
#ifdef MMU_PROFILING
@ -678,7 +632,7 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write) {
/* page address translation */
if (!bat_hit) {
PATResult pat_res = page_address_translate(la, false, msr_pr, is_write);
PATResult pat_res = page_address_translation(la, false, msr_pr, is_write);
pa = pat_res.phys;
#ifdef MMU_PROFILING
@ -812,7 +766,7 @@ static TLBEntry* tlb2_target_entry(uint32_t gp_va)
tlb_entry[2].lru_bits = 0x2;
tlb_entry[3].lru_bits = 0x3;
return &tlb_entry[3];
} else { // no invalid blocks, replace an existing one according with the hLRU policy
} else { // no free entries, replace an existing one according with the hLRU policy
#ifdef TLB_PROFILING
num_entry_replacements++;
#endif
@ -880,7 +834,7 @@ static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write)
}
} else {
// page address translation
PATResult pat_res = page_address_translate(guest_va, false,
PATResult pat_res = page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), is_write);
phys_addr = pat_res.phys;
flags = TLBFlags::TLBE_FROM_PAT; // tell the world we come from
@ -1018,8 +972,6 @@ static inline uint64_t tlb_translate_addr(uint32_t guest_va)
// look up address in the primary TLB
tlb1_entry = &pCurTLB1[(guest_va >> PAGE_SIZE_BITS) & tlb_size_mask];
if (tlb1_entry->tag == tag) { // primary TLB hit -> fast path
MemAccessType = true;
MemAddr = tlb1_entry->host_va_offset + guest_va;
return tlb1_entry->host_va_offset + guest_va;
} else { // primary TLB miss -> look up address in the secondary TLB
tlb2_entry = &pCurTLB2[((guest_va >> PAGE_SIZE_BITS) & tlb_size_mask) * TLB2_WAYS];
@ -1060,13 +1012,8 @@ static inline uint64_t tlb_translate_addr(uint32_t guest_va)
tlb1_entry->tag = tag;
tlb1_entry->flags = tlb2_entry->flags;
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
MemAccessType = true;
MemAddr = tlb1_entry->host_va_offset + guest_va;
return tlb1_entry->host_va_offset + guest_va;
} else { // an attempt to access a memory-mapped device
MemAccessType = false;
Device = tlb2_entry->reg_desc->devobj;
DevOffset = guest_va - tlb2_entry->reg_desc->start;
return guest_va - tlb2_entry->reg_desc->start;
}
}
@ -1236,7 +1183,6 @@ inline T mmu_read_vmem(uint32_t guest_va) {
}
// explicitely instantiate all required mmu_read_vmem variants
// to avoid linking errors
template uint8_t mmu_read_vmem<uint8_t>(uint32_t guest_va);
template uint16_t mmu_read_vmem<uint16_t>(uint32_t guest_va);
template uint32_t mmu_read_vmem<uint32_t>(uint32_t guest_va);
@ -1262,7 +1208,7 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
}
if (!(tlb1_entry->flags & TLBFlags::PTE_SET_C)) {
// perform full page address translation to update PTE.C bit
PATResult pat_res = page_address_translate(guest_va, false,
PATResult pat_res = page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
tlb1_entry->flags |= TLBFlags::PTE_SET_C;
@ -1273,8 +1219,6 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
}
}
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
MemAccessType = true;
MemAddr = (uint64_t)host_va;
} else {
// primary TLB miss -> look up address in the secondary TLB
tlb2_entry = lookup_secondary_tlb(guest_va, tag);
@ -1293,8 +1237,6 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
#endif
if (!(tlb2_entry->flags & TLBFlags::PAGE_WRITABLE)) {
LOG_F(WARNING, "DSI Exception in mmu_write_vmem! PC=0x%08X", ppc_state.pc);
//return;
ppc_state.spr[SPR::DSISR] = 0x08000000 | (1 << 25);
ppc_state.spr[SPR::DAR] = guest_va;
mmu_exception_handler(Except_Type::EXC_DSI, 0);
@ -1302,7 +1244,7 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
if (!(tlb2_entry->flags & TLBFlags::PTE_SET_C)) {
// perform full page address translation to update PTE.C bit
PATResult pat_res = page_address_translate(guest_va, false,
PATResult pat_res = page_address_translation(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
tlb2_entry->flags |= TLBFlags::PTE_SET_C;
}
@ -1313,17 +1255,12 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
tlb1_entry->flags = tlb2_entry->flags;
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
//MemAccessType = true;
//MemAddr = (uint64_t)host_va;
} else { // otherwise, it's an access to a memory-mapped device
#ifdef MMU_PROFILING
iomem_writes_total++;
#endif
tlb2_entry->reg_desc->devobj->write(tlb2_entry->reg_desc->start,
guest_va - tlb2_entry->reg_desc->start, value, sizeof(T));
//MemAccessType = false;
//Device = tlb2_entry->reg_desc->devobj;
//DevOffset = guest_va - tlb2_entry->reg_desc->start;
return;
}
}
@ -1338,7 +1275,6 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
return;
}
#if 1
// handle aligned memory accesses
switch(sizeof(T)) {
case 1:
@ -1354,11 +1290,9 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
WRITE_QWORD_BE_A(host_va, value);
break;
}
#endif
}
// explicitely instantiate all required mmu_write_vmem variants
// to avoid linking errors
template void mmu_write_vmem<uint8_t>(uint32_t guest_va, uint8_t value);
template void mmu_write_vmem<uint16_t>(uint32_t guest_va, uint16_t value);
template void mmu_write_vmem<uint32_t>(uint32_t guest_va, uint32_t value);
@ -1556,7 +1490,7 @@ uint8_t* quickinstruction_translate(uint32_t addr) {
/* perform instruction address translation if enabled */
if (ppc_state.msr & 0x20) {
addr = ppc_mmu_instr_translate(addr);
addr = mmu_instr_translation(addr);
}
if (addr >= last_exec_area.start && addr <= last_exec_area.end) {

View File

@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// The opcodes for the processor - ppcopcodes.cpp
/** @file PowerPC Memory Management Unit definitions. */
#ifndef PPCMEMORY_H
#define PPCMEMORY_H
#ifndef PPCMMU_H
#define PPCMMU_H
#include <array>
#include <cinttypes>
@ -93,8 +93,6 @@ extern uint8_t* mmu_get_dma_mem(uint32_t addr, uint32_t size);
extern void mmu_change_mode(void);
extern void mmu_pat_ctx_changed();
extern void tlb_flush_entry(uint32_t ea);
extern void tlb_flush_bat_entries();
extern void tlb_flush_pat_entries();
extern void ppc_set_cur_instruction(const uint8_t* ptr);
extern void mem_write_byte(uint32_t addr, uint8_t value);
@ -113,4 +111,4 @@ extern T mmu_read_vmem(uint32_t guest_va);
template <class T>
extern void mmu_write_vmem(uint32_t guest_va, T value);
#endif // PPCMEMORY_H
#endif // PPCMMU_H

View File

@ -873,7 +873,6 @@ void dppc_interpreter::ppc_mtspr() {
}
if (ref_spr == SPR::SDR1) {
LOG_F(INFO, "SDR1 changed to 0x%08X", ppc_state.spr[SPR::SDR1]);
mmu_pat_ctx_changed();
}