[for-6.2,12/43] target/sh4: Implement do_unaligned_access for user-only

Message ID 20210729004647.282017-13-richard.henderson@linaro.org
State Superseded
Headers show
Series
  • Unaligned accesses for user-only
Related show

Commit Message

Richard Henderson July 29, 2021, 12:46 a.m.
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 linux-user/sh4/cpu_loop.c | 8 ++++++++
 target/sh4/cpu.c          | 2 +-
 target/sh4/op_helper.c    | 3 ---
 3 files changed, 9 insertions(+), 4 deletions(-)

-- 
2.25.1

Comments

Peter Maydell July 29, 2021, 1:52 p.m. | #1
On Thu, 29 Jul 2021 at 02:01, Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> ---

>  linux-user/sh4/cpu_loop.c | 8 ++++++++

>  target/sh4/cpu.c          | 2 +-

>  target/sh4/op_helper.c    | 3 ---

>  3 files changed, 9 insertions(+), 4 deletions(-)

>

> diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c

> index 222ed1c670..21d97250a8 100644

> --- a/linux-user/sh4/cpu_loop.c

> +++ b/linux-user/sh4/cpu_loop.c

> @@ -71,6 +71,14 @@ void cpu_loop(CPUSH4State *env)

>              info._sifields._sigfault._addr = env->tea;

>              queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);

>              break;

> +        case 0xe0:

> +        case 0x100:

> +            info.si_signo = TARGET_SIGBUS;

> +            info.si_errno = 0;

> +            info.si_code = TARGET_BUS_ADRALN;

> +            info._sifields._sigfault._addr = env->tea;

> +            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);

> +            break;


sh4 kernel default for unaligned accesses seems to be "warn and fixup",
not SIGBUS, unless the user changes that by writing to /proc/cpu/alignment
or the process changes it via prctl().

-- PMM
Richard Henderson July 30, 2021, 12:01 a.m. | #2
On 7/29/21 3:52 AM, Peter Maydell wrote:
> sh4 kernel default for unaligned accesses seems to be "warn and fixup",

> not SIGBUS, unless the user changes that by writing to /proc/cpu/alignment

> or the process changes it via prctl().


We will still need this for load-locked/store-conditional (MOVLI/MOVCO).

It appears that the sh4 kernel fails to decode these properly, and will do something ugly, 
like interpreting MOVLI as a multiple-store instead of a load.

There are also other instructions that the kernel does not attempt to handle, such as MAC. 
  I suppose we could begin with turning off TARGET_ALIGNED_ONLY for sh4-linux-user, then 
re-enabling MO_ALIGN for the atomics (at least).


r~
Rob Landley July 30, 2021, 8:54 p.m. | #3
On 7/29/21 8:52 AM, Peter Maydell wrote:
> On Thu, 29 Jul 2021 at 02:01, Richard Henderson

> <richard.henderson@linaro.org> wrote:

>>

>> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>

>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

>> ---

>>  linux-user/sh4/cpu_loop.c | 8 ++++++++

>>  target/sh4/cpu.c          | 2 +-

>>  target/sh4/op_helper.c    | 3 ---

>>  3 files changed, 9 insertions(+), 4 deletions(-)

>>

>> diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c

>> index 222ed1c670..21d97250a8 100644

>> --- a/linux-user/sh4/cpu_loop.c

>> +++ b/linux-user/sh4/cpu_loop.c

>> @@ -71,6 +71,14 @@ void cpu_loop(CPUSH4State *env)

>>              info._sifields._sigfault._addr = env->tea;

>>              queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);

>>              break;

>> +        case 0xe0:

>> +        case 0x100:

>> +            info.si_signo = TARGET_SIGBUS;

>> +            info.si_errno = 0;

>> +            info.si_code = TARGET_BUS_ADRALN;

>> +            info._sifields._sigfault._addr = env->tea;

>> +            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);

>> +            break;

> 

> sh4 kernel default for unaligned accesses seems to be "warn and fixup",

> not SIGBUS, unless the user changes that by writing to /proc/cpu/alignment

> or the process changes it via prctl().


It's still good to know, qemu-sh4 runs j-core binaries but that target doesn't
have unaligned interrupts yet. (I think it just masks off the bottom 2 bits to
do the next lowest aligned access? It's an sh2 variant and the plumbing to let
interrupts restart multi-clock instructions is only in the j32 branch so far, so
the j2 and ice40 targets don't generate interrupts for it. Todo item, in the
meantime we need to clean unaligned access out of application code so faulting
on it is good.)

> -- PMM


Thanks,

Rob

Patch

diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c
index 222ed1c670..21d97250a8 100644
--- a/linux-user/sh4/cpu_loop.c
+++ b/linux-user/sh4/cpu_loop.c
@@ -71,6 +71,14 @@  void cpu_loop(CPUSH4State *env)
             info._sifields._sigfault._addr = env->tea;
             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
             break;
+        case 0xe0:
+        case 0x100:
+            info.si_signo = TARGET_SIGBUS;
+            info.si_errno = 0;
+            info.si_code = TARGET_BUS_ADRALN;
+            info._sifields._sigfault._addr = env->tea;
+            queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            break;
         case EXCP_ATOMIC:
             cpu_exec_step_atomic(cs);
             arch_interrupt = false;
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 8326922942..b60234cd31 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -238,10 +238,10 @@  static const struct TCGCPUOps superh_tcg_ops = {
     .synchronize_from_tb = superh_cpu_synchronize_from_tb,
     .cpu_exec_interrupt = superh_cpu_exec_interrupt,
     .tlb_fill = superh_cpu_tlb_fill,
+    .do_unaligned_access = superh_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
     .do_interrupt = superh_cpu_do_interrupt,
-    .do_unaligned_access = superh_cpu_do_unaligned_access,
     .io_recompile_replay_branch = superh_io_recompile_replay_branch,
 #endif /* !CONFIG_USER_ONLY */
 };
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index d6d70c339f..b46fc1bf11 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -23,7 +23,6 @@ 
 #include "exec/cpu_ldst.h"
 #include "fpu/softfloat.h"
 
-#ifndef CONFIG_USER_ONLY
 
 void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
                                     MMUAccessType access_type,
@@ -46,8 +45,6 @@  void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
     cpu_loop_exit_restore(cs, retaddr);
 }
 
-#endif
-
 void helper_ldtlb(CPUSH4State *env)
 {
 #ifdef CONFIG_USER_ONLY