aboutsummaryrefslogtreecommitdiff
path: root/target/xtensa/op_helper.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2019-01-13 19:16:18 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2019-01-13 23:34:57 -0800
commit7e5e5a630245727854ac17a973bff1f3b3d87743 (patch)
tree4ff312d52dea37d1488cd9322dc941cad057a1e0 /target/xtensa/op_helper.c
parentc9ed50e82d640f164b06c9170382622a9adf9906 (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.c293
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];