diff mbox

[2/3] target-mips: Misaligned Memory Accesses for R6

Message ID 1430493868-21452-3-git-send-email-yongbok.kim@imgtec.com
State New
Headers show

Commit Message

Yongbok Kim May 1, 2015, 3:24 p.m. UTC
Release 6 requires misaligned memory access support for all ordinary memory
access instructions (for example, LW/SW, LWC1/SWC1).
However misaligned support is not provided for certain special memory accesses
such as atomics (for example, LL/SC).

In the mips_cpu_do_unaligned_access() callback, if it is R6 core it checks further
whether the address is valid.

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
---
 target-mips/cpu.h            |    2 ++
 target-mips/helper.c         |   36 ++++++++++++++++++++++++++++++++++++
 target-mips/op_helper.c      |   13 +++++++++++++
 target-mips/translate_init.c |    2 +-
 4 files changed, 52 insertions(+), 1 deletions(-)

Comments

Peter Maydell May 1, 2015, 3:39 p.m. UTC | #1
On 1 May 2015 at 16:24, Yongbok Kim <yongbok.kim@imgtec.com> wrote:
> Release 6 requires misaligned memory access support for all ordinary memory
> access instructions (for example, LW/SW, LWC1/SWC1).
> However misaligned support is not provided for certain special memory accesses
> such as atomics (for example, LL/SC).
>
> In the mips_cpu_do_unaligned_access() callback, if it is R6 core it checks further
> whether the address is valid.
>
> Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
> ---
>  target-mips/cpu.h            |    2 ++
>  target-mips/helper.c         |   36 ++++++++++++++++++++++++++++++++++++
>  target-mips/op_helper.c      |   13 +++++++++++++
>  target-mips/translate_init.c |    2 +-
>  4 files changed, 52 insertions(+), 1 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index f9d2b4c..6586d89 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -760,6 +760,8 @@ int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
>  void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
>  hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
>                                                int rw);
> +bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address,
> +                            target_ulong badvaddr, unsigned data_size, int rw);
>  #endif
>  target_ulong exception_resume_pc (CPUMIPSState *env);
>
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index 8e3204a..6c44124 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -391,6 +391,42 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r
>      }
>  }
>
> +bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address,
> +                            target_ulong badvaddr, unsigned data_size, int rw)
> +{
> +    hwaddr physical;
> +    int prot;
> +    int access_type = ACCESS_INT;
> +    int ret;
> +    target_ulong addr;
> +
> +    addr = address & ~((target_ulong) data_size - 1);
> +    ret = get_physical_address(env, &physical, &prot,
> +            addr, rw, access_type);

Isn't a recheck of the TLB on every unaligned access going
to have poor performance? If we know from the type of the
insn whether an unaligned access is OK or not there ought
to be some way to avoid doing the check at all...

-- PMM
diff mbox

Patch

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index f9d2b4c..6586d89 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -760,6 +760,8 @@  int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
 hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
 		                               int rw);
+bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address,
+                            target_ulong badvaddr, unsigned data_size, int rw);
 #endif
 target_ulong exception_resume_pc (CPUMIPSState *env);
 
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 8e3204a..6c44124 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -391,6 +391,42 @@  hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r
     }
 }
 
+bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address,
+                            target_ulong badvaddr, unsigned data_size, int rw)
+{
+    hwaddr physical;
+    int prot;
+    int access_type = ACCESS_INT;
+    int ret;
+    target_ulong addr;
+
+    addr = address & ~((target_ulong) data_size - 1);
+    ret = get_physical_address(env, &physical, &prot,
+            addr, rw, access_type);
+    if (ret != TLBRET_MATCH) {
+        if (ret != TLBRET_BADADDR && addr > badvaddr) {
+            badvaddr = addr;
+        }
+        raise_mmu_exception(env, badvaddr, rw, ret);
+        return false;
+    }
+    if ((data_size > 1)
+        && unlikely(((address & ~TARGET_PAGE_MASK) + data_size - 1)
+                    >= TARGET_PAGE_SIZE)) {
+        addr += data_size;
+        ret = get_physical_address(env, &physical, &prot, addr, rw,
+              access_type);
+        if (ret != TLBRET_MATCH) {
+            if (ret != TLBRET_BADADDR) {
+                badvaddr = addr;
+            }
+            raise_mmu_exception(env, badvaddr, rw, ret);
+            return false;
+        }
+    }
+    return true;
+}
+
 static const char * const excp_names[EXCP_LAST + 1] = {
     [EXCP_RESET] = "reset",
     [EXCP_SRESET] = "soft reset",
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index ca5fe43..dacc92b 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2215,6 +2215,19 @@  void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
     int error_code = 0;
     int excp;
 
+    if (env->insn_flags & ISA_MIPS32R6) {
+        /* Release 6 provides support for misaligned memory access for
+         * all ordinary memory reference instructions
+         * */
+        if (!cpu_mips_validate_access(env, addr, addr, size, access_type)) {
+            CPUState *cs = CPU(mips_env_get_cpu(env));
+            do_raise_exception_err(env, cs->exception_index,
+                                   env->error_code, retaddr);
+            return;
+        }
+        return;
+    }
+
     env->CP0_BadVAddr = addr;
 
     if (access_type == MMU_DATA_STORE) {
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 85a65e7..ec54fef 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -607,7 +607,7 @@  static const mips_def_t mips_defs[] =
     },
     {
         /* A generic CPU supporting MIPS64 Release 6 ISA.
-           FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
+           FIXME: Support IEEE 754-2008 FP.
                   Eventually this should be replaced by a real CPU model. */
         .name = "MIPS64R6-generic",
         .CP0_PRid = 0x00010000,