Reviewed-by: Mark Cave-Ayland <mark.cave-ayl...@ilande.co.uk> Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/sparc/mmu_helper.c | 72 +++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 26 deletions(-)
diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index 2ad47391d0..014601e701 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -502,16 +502,60 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb, return 0; } +static uint64_t build_sfsr(CPUSPARCState *env, int mmu_idx, int rw) +{ + uint64_t sfsr = SFSR_VALID_BIT; + + switch (mmu_idx) { + case MMU_PHYS_IDX: + sfsr |= SFSR_CT_NOTRANS; + break; + case MMU_USER_IDX: + case MMU_KERNEL_IDX: + sfsr |= SFSR_CT_PRIMARY; + break; + case MMU_USER_SECONDARY_IDX: + case MMU_KERNEL_SECONDARY_IDX: + sfsr |= SFSR_CT_SECONDARY; + break; + case MMU_NUCLEUS_IDX: + sfsr |= SFSR_CT_NUCLEUS; + break; + default: + g_assert_not_reached(); + } + + if (rw == 1) { + sfsr |= SFSR_WRITE_BIT; + } else if (rw == 4) { + sfsr |= SFSR_NF_BIT; + } + + if (env->pstate & PS_PRIV) { + sfsr |= SFSR_PR_BIT; + } + + if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */ + sfsr |= SFSR_OW_BIT; /* overflow (not read before another fault) */ + } + + /* FIXME: ASI field in SFSR must be set */ + + return sfsr; +} + static int get_physical_address_data(CPUSPARCState *env, hwaddr *physical, int *prot, MemTxAttrs *attrs, target_ulong address, int rw, int mmu_idx) { CPUState *cs = env_cpu(env); unsigned int i; + uint64_t sfsr; uint64_t context; - uint64_t sfsr = 0; bool is_user = false; + sfsr = build_sfsr(env, mmu_idx, rw); + switch (mmu_idx) { case MMU_PHYS_IDX: g_assert_not_reached(); @@ -520,29 +564,18 @@ static int get_physical_address_data(CPUSPARCState *env, hwaddr *physical, /* fallthru */ case MMU_KERNEL_IDX: context = env->dmmu.mmu_primary_context & 0x1fff; - sfsr |= SFSR_CT_PRIMARY; break; case MMU_USER_SECONDARY_IDX: is_user = true; /* fallthru */ case MMU_KERNEL_SECONDARY_IDX: context = env->dmmu.mmu_secondary_context & 0x1fff; - sfsr |= SFSR_CT_SECONDARY; break; - case MMU_NUCLEUS_IDX: - sfsr |= SFSR_CT_NUCLEUS; - /* FALLTHRU */ default: context = 0; break; } - if (rw == 1) { - sfsr |= SFSR_WRITE_BIT; - } else if (rw == 4) { - sfsr |= SFSR_NF_BIT; - } - for (i = 0; i < 64; i++) { /* ctx match, vaddr match, valid? */ if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) { @@ -592,22 +625,9 @@ static int get_physical_address_data(CPUSPARCState *env, hwaddr *physical, return 0; } - if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */ - sfsr |= SFSR_OW_BIT; /* overflow (not read before - another fault) */ - } - - if (env->pstate & PS_PRIV) { - sfsr |= SFSR_PR_BIT; - } - - /* FIXME: ASI field in SFSR must be set */ - env->dmmu.sfsr = sfsr | SFSR_VALID_BIT; - + env->dmmu.sfsr = sfsr; env->dmmu.sfar = address; /* Fault address register */ - env->dmmu.tag_access = (address & ~0x1fffULL) | context; - return 1; } } -- 2.25.1