[PATCH v4 5/6] target/m68k: Implement custom MMU intercept hook
54weasels <[email protected]>
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
High level description: Boards like the Sun-3 use an external custom MMU logic array rather than the standard 68851/68030 embedded MMU. This patch introduces a `custom_mmu_get_physical_address` opaque hook, allowing board initialization code to intercept TLB fills and delegate translation directly to the machine's external MMU implementation. Impact on existing functionality: Zero impact on existing boards. If the hook is not explicitly registered by the board initialization code, the standard 68k MMU translation pipeline executes normally. Context: This patch was originally submitted as part of the monolithic Sun-3 Machine Emulation series (https://patchew.org/QEMU/[email protected]/) and has been split into atomic components. --- target/m68k/cpu.h | 7 ++++ target/m68k/helper.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 42d34502fc..d4ecb1c3ef 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -153,6 +153,13 @@ typedef struct CPUArchState { /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; + /* Custom MMU intercept logic, if any (e.g. for Sun-3) */ + void *custom_mmu_opaque; + int (*custom_mmu_get_physical_address)(void *env, hwaddr *physical, + int *prot, vaddr address, + int access_type, + hwaddr *page_size); + /* Fields from here on are preserved across CPU reset. */ uint64_t features; } CPUM68KState; diff --git a/target/m68k/helper.c b/target/m68k/helper.c index f3ee95441a..1eef6dcaaf 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -920,6 +920,21 @@ hwaddr m68k_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr) int access_type; target_ulong page_size; + access_type = ACCESS_DATA | ACCESS_DEBUG; + if (env->sr & SR_S) { + access_type |= ACCESS_SUPER; + } + + if (env->custom_mmu_get_physical_address) { + hwaddr custom_page_size; + if (env->custom_mmu_get_physical_address(env, &phys_addr, &prot, addr, + access_type, + &custom_page_size) == 0) { + return phys_addr; + } + return -1; + } + if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) { /* MMU disabled */ return addr; @@ -1001,6 +1016,80 @@ bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } } + if (env->custom_mmu_get_physical_address) { + hwaddr custom_page_size; + + /* Delegate translation to external board-specific MMU if registered */ + ret = env->custom_mmu_get_physical_address(env, &physical, &prot, + address, access_type, + &custom_page_size); + + if (likely(ret == 0)) { + tlb_set_page(cs, address & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot, + mmu_idx, custom_page_size); + return true; + } + + if (probe) { + return false; + } + + /* page fault */ + cs->exception_index = EXCP_ACCESS; + env->mmu.ar = address; + + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.ssw = M68K_ATC_040; + switch (size) { + case 1: + env->mmu.ssw |= M68K_BA_SIZE_BYTE; + break; + case 2: + env->mmu.ssw |= M68K_BA_SIZE_WORD; + break; + case 4: + env->mmu.ssw |= M68K_BA_SIZE_LONG; + break; + } + env->mmu.ssw |= M68K_TM_040_DATA; + } else { + /* M68020/030 Special Status Word (SSW) */ + uint16_t ssw = 0x0100; /* DF - Data Fault */ + switch (size) { + case 1: + ssw |= 0x0010; + break; + case 2: + ssw |= 0x0020; + break; + case 3: + ssw |= 0x0030; + break; + case 4: + ssw |= 0x0000; + break; + } + if (qemu_access_type != MMU_DATA_STORE) { + ssw |= 0x0040; /* RW - Read */ + } + /* Function Code */ + uint8_t fc; + if (mmu_idx >= MMU_MOVES_FC_BASE) { + fc = mmu_idx - MMU_MOVES_FC_BASE; + } else { + if (mmu_idx == MMU_KERNEL_IDX) { + fc = (qemu_access_type == MMU_INST_FETCH) ? 6 : 5; + } else { + fc = (qemu_access_type == MMU_INST_FETCH) ? 2 : 1; + } + } + ssw |= (fc & 7); + env->mmu.ssw = ssw; + } + cpu_loop_exit_restore(cs, retaddr); + } + if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) { /* MMU disabled */ tlb_set_page(cs, address & TARGET_PAGE_MASK, -- 2.50.1 (Apple Git-155)