diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2019-01-13 19:16:18 -0800 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2019-01-13 23:34:57 -0800 |
commit | 7e5e5a630245727854ac17a973bff1f3b3d87743 (patch) | |
tree | 4ff312d52dea37d1488cd9322dc941cad057a1e0 /target/xtensa/op_helper.c | |
parent | c9ed50e82d640f164b06c9170382622a9adf9906 (diff) |
target/xtensa: extract MMU helpers
Move MMU-related helper functions from op_helper.c and helper.c to
mmu_helper.c. No functional changes.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target/xtensa/op_helper.c')
-rw-r--r-- | target/xtensa/op_helper.c | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 946ae1f91b..1d3d87012c 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -242,15 +242,6 @@ void HELPER(check_interrupts)(CPUXtensaState *env) qemu_mutex_unlock_iothread(); } -void HELPER(itlb_hit_test)(CPUXtensaState *env, uint32_t vaddr) -{ - /* - * Attempt the memory load; we don't care about the result but - * only the side-effects (ie any MMU or other exception) - */ - cpu_ldub_code_ra(env, vaddr, GETPC()); -} - /*! * Check vaddr accessibility/cache attributes and raise an exception if * specified by the ATOMCTL SR. @@ -334,290 +325,6 @@ void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v) env->sregs[MEMCTL] = v & env->config->memctl_mask; } -void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v) -{ - XtensaCPU *cpu = xtensa_env_get_cpu(env); - - v = (v & 0xffffff00) | 0x1; - if (v != env->sregs[RASID]) { - env->sregs[RASID] = v; - tlb_flush(CPU(cpu)); - } -} - -static uint32_t get_page_size(const CPUXtensaState *env, bool dtlb, uint32_t way) -{ - uint32_t tlbcfg = env->sregs[dtlb ? DTLBCFG : ITLBCFG]; - - switch (way) { - case 4: - return (tlbcfg >> 16) & 0x3; - - case 5: - return (tlbcfg >> 20) & 0x1; - - case 6: - return (tlbcfg >> 24) & 0x1; - - default: - return 0; - } -} - -/*! - * Get bit mask for the virtual address bits translated by the TLB way - */ -uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way) -{ - if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - bool varway56 = dtlb ? - env->config->dtlb.varway56 : - env->config->itlb.varway56; - - switch (way) { - case 4: - return 0xfff00000 << get_page_size(env, dtlb, way) * 2; - - case 5: - if (varway56) { - return 0xf8000000 << get_page_size(env, dtlb, way); - } else { - return 0xf8000000; - } - - case 6: - if (varway56) { - return 0xf0000000 << (1 - get_page_size(env, dtlb, way)); - } else { - return 0xf0000000; - } - - default: - return 0xfffff000; - } - } else { - return REGION_PAGE_MASK; - } -} - -/*! - * Get bit mask for the 'VPN without index' field. - * See ISA, 4.6.5.6, data format for RxTLB0 - */ -static uint32_t get_vpn_mask(const CPUXtensaState *env, bool dtlb, uint32_t way) -{ - if (way < 4) { - bool is32 = (dtlb ? - env->config->dtlb.nrefillentries : - env->config->itlb.nrefillentries) == 32; - return is32 ? 0xffff8000 : 0xffffc000; - } else if (way == 4) { - return xtensa_tlb_get_addr_mask(env, dtlb, way) << 2; - } else if (way <= 6) { - uint32_t mask = xtensa_tlb_get_addr_mask(env, dtlb, way); - bool varway56 = dtlb ? - env->config->dtlb.varway56 : - env->config->itlb.varway56; - - if (varway56) { - return mask << (way == 5 ? 2 : 3); - } else { - return mask << 1; - } - } else { - return 0xfffff000; - } -} - -/*! - * Split virtual address into VPN (with index) and entry index - * for the given TLB way - */ -void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb, - uint32_t *vpn, uint32_t wi, uint32_t *ei) -{ - bool varway56 = dtlb ? - env->config->dtlb.varway56 : - env->config->itlb.varway56; - - if (!dtlb) { - wi &= 7; - } - - if (wi < 4) { - bool is32 = (dtlb ? - env->config->dtlb.nrefillentries : - env->config->itlb.nrefillentries) == 32; - *ei = (v >> 12) & (is32 ? 0x7 : 0x3); - } else { - switch (wi) { - case 4: - { - uint32_t eibase = 20 + get_page_size(env, dtlb, wi) * 2; - *ei = (v >> eibase) & 0x3; - } - break; - - case 5: - if (varway56) { - uint32_t eibase = 27 + get_page_size(env, dtlb, wi); - *ei = (v >> eibase) & 0x3; - } else { - *ei = (v >> 27) & 0x1; - } - break; - - case 6: - if (varway56) { - uint32_t eibase = 29 - get_page_size(env, dtlb, wi); - *ei = (v >> eibase) & 0x7; - } else { - *ei = (v >> 28) & 0x1; - } - break; - - default: - *ei = 0; - break; - } - } - *vpn = v & xtensa_tlb_get_addr_mask(env, dtlb, wi); -} - -/*! - * Split TLB address into TLB way, entry index and VPN (with index). - * See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format - */ -static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb, - uint32_t *vpn, uint32_t *wi, uint32_t *ei) -{ - if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - *wi = v & (dtlb ? 0xf : 0x7); - split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei); - } else { - *vpn = v & REGION_PAGE_MASK; - *wi = 0; - *ei = (v >> 29) & 0x7; - } -} - -static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env, - uint32_t v, bool dtlb, uint32_t *pwi) -{ - uint32_t vpn; - uint32_t wi; - uint32_t ei; - - split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei); - if (pwi) { - *pwi = wi; - } - return xtensa_tlb_get_entry(env, dtlb, wi, ei); -} - -uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) -{ - if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - uint32_t wi; - const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi); - return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid; - } else { - return v & REGION_PAGE_MASK; - } -} - -uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) -{ - const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL); - return entry->paddr | entry->attr; -} - -void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) -{ - if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - uint32_t wi; - xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi); - if (entry->variable && entry->asid) { - tlb_flush_page(CPU(xtensa_env_get_cpu(env)), entry->vaddr); - entry->asid = 0; - } - } -} - -uint32_t HELPER(ptlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) -{ - if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - uint32_t wi; - uint32_t ei; - uint8_t ring; - int res = xtensa_tlb_lookup(env, v, dtlb, &wi, &ei, &ring); - - switch (res) { - case 0: - if (ring >= xtensa_get_ring(env)) { - return (v & 0xfffff000) | wi | (dtlb ? 0x10 : 0x8); - } - break; - - case INST_TLB_MULTI_HIT_CAUSE: - case LOAD_STORE_TLB_MULTI_HIT_CAUSE: - HELPER(exception_cause_vaddr)(env, env->pc, res, v); - break; - } - return 0; - } else { - return (v & REGION_PAGE_MASK) | 0x1; - } -} - -void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, - xtensa_tlb_entry *entry, bool dtlb, - unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte) -{ - entry->vaddr = vpn; - entry->paddr = pte & xtensa_tlb_get_addr_mask(env, dtlb, wi); - entry->asid = (env->sregs[RASID] >> ((pte >> 1) & 0x18)) & 0xff; - entry->attr = pte & 0xf; -} - -void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb, - unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte) -{ - XtensaCPU *cpu = xtensa_env_get_cpu(env); - CPUState *cs = CPU(cpu); - xtensa_tlb_entry *entry = xtensa_tlb_get_entry(env, dtlb, wi, ei); - - if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { - if (entry->variable) { - if (entry->asid) { - tlb_flush_page(cs, entry->vaddr); - } - xtensa_tlb_set_entry_mmu(env, entry, dtlb, wi, ei, vpn, pte); - tlb_flush_page(cs, entry->vaddr); - } else { - qemu_log_mask(LOG_GUEST_ERROR, "%s %d, %d, %d trying to set immutable entry\n", - __func__, dtlb, wi, ei); - } - } else { - tlb_flush_page(cs, entry->vaddr); - if (xtensa_option_enabled(env->config, - XTENSA_OPTION_REGION_TRANSLATION)) { - entry->paddr = pte & REGION_PAGE_MASK; - } - entry->attr = pte & 0xf; - } -} - -void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb) -{ - uint32_t vpn; - uint32_t wi; - uint32_t ei; - split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei); - xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p); -} - - void HELPER(wsr_ibreakenable)(CPUXtensaState *env, uint32_t v) { uint32_t change = v ^ env->sregs[IBREAKENABLE]; |