On Thu, Oct 14, 2021 at 10:14 PM Richard Henderson <
[email protected]> wrote:

> Because of the complexity of setting ESR, re-use the existing
> arm_cpu_do_unaligned_access function.  This means we have to
> handle the exception ourselves in cpu_loop, transforming it
> to the appropriate signal.
>
> Signed-off-by: Richard Henderson <[email protected]>
> ---
>  target/arm/internals.h        |  2 ++
>  linux-user/aarch64/cpu_loop.c | 12 +++++++++---
>  linux-user/arm/cpu_loop.c     | 30 ++++++++++++++++++++++++++----
>  target/arm/cpu.c              |  1 +
>  target/arm/cpu_tcg.c          |  1 +
>  target/arm/tlb_helper.c       |  6 ++++++
>  6 files changed, 45 insertions(+), 7 deletions(-)
>

Reviewed-by: Warner Losh <[email protected]>

This will definitely have an impact on the bsd-user fork, and my plans to
add arm and aarch64 to
upstream before 6.2, but I believe most of the changes will port over so
I'm not too worried.


> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 5a7aaf0f51..89f7610ebc 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -548,6 +548,8 @@ static inline bool arm_extabort_type(MemTxResult
> result)
>  void arm_cpu_record_sigsegv(CPUState *cpu, vaddr addr,
>                              MMUAccessType access_type,
>                              bool maperr, uintptr_t ra);
> +void arm_cpu_record_sigbus(CPUState *cpu, vaddr addr,
> +                           MMUAccessType access_type, uintptr_t ra);
>  #else
>  bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>                        MMUAccessType access_type, int mmu_idx,
> diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
> index 034b737435..97e0728b67 100644
> --- a/linux-user/aarch64/cpu_loop.c
> +++ b/linux-user/aarch64/cpu_loop.c
> @@ -79,7 +79,7 @@
>  void cpu_loop(CPUARMState *env)
>  {
>      CPUState *cs = env_cpu(env);
> -    int trapnr, ec, fsc, si_code;
> +    int trapnr, ec, fsc, si_code, si_signo;
>      abi_long ret;
>
>      for (;;) {
> @@ -121,20 +121,26 @@ void cpu_loop(CPUARMState *env)
>              fsc = extract32(env->exception.syndrome, 0, 6);
>              switch (fsc) {
>              case 0x04 ... 0x07: /* Translation fault, level {0-3} */
> +                si_signo = TARGET_SIGSEGV;
>                  si_code = TARGET_SEGV_MAPERR;
>                  break;
>              case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
>              case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
> +                si_signo = TARGET_SIGSEGV;
>                  si_code = TARGET_SEGV_ACCERR;
>                  break;
>              case 0x11: /* Synchronous Tag Check Fault */
> +                si_signo = TARGET_SIGSEGV;
>                  si_code = TARGET_SEGV_MTESERR;
>                  break;
> +            case 0x21: /* Alignment fault */
> +                si_signo = TARGET_SIGBUS;
> +                si_code = TARGET_BUS_ADRALN;
> +                break;
>              default:
>                  g_assert_not_reached();
>              }
> -
> -            force_sig_fault(TARGET_SIGSEGV, si_code,
> env->exception.vaddress);
> +            force_sig_fault(si_signo, si_code, env->exception.vaddress);
>              break;
>          case EXCP_DEBUG:
>          case EXCP_BKPT:
> diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
> index ae09adcb95..01cb6eb534 100644
> --- a/linux-user/arm/cpu_loop.c
> +++ b/linux-user/arm/cpu_loop.c
> @@ -25,6 +25,7 @@
>  #include "cpu_loop-common.h"
>  #include "signal-common.h"
>  #include "semihosting/common-semi.h"
> +#include "target/arm/syndrome.h"
>
>  #define get_user_code_u32(x, gaddr, env)                \
>      ({ abi_long __r = get_user_u32((x), (gaddr));       \
> @@ -280,7 +281,7 @@ static bool emulate_arm_fpa11(CPUARMState *env,
> uint32_t opcode)
>  void cpu_loop(CPUARMState *env)
>  {
>      CPUState *cs = env_cpu(env);
> -    int trapnr;
> +    int trapnr, si_signo, si_code;
>      unsigned int n, insn;
>      abi_ulong ret;
>
> @@ -423,9 +424,30 @@ void cpu_loop(CPUARMState *env)
>              break;
>          case EXCP_PREFETCH_ABORT:
>          case EXCP_DATA_ABORT:
> -            /* XXX: check env->error_code */
> -            force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
> -                            env->exception.vaddress);
> +            /* For user-only we don't set TTBCR_EAE, so look at the FSR.
> */
> +            switch (env->exception.fsr & 0x1f) {
> +            case 0x1: /* Alignment */
> +                si_signo = TARGET_SIGBUS;
> +                si_code = TARGET_BUS_ADRALN;
> +                break;
> +            case 0x3: /* Access flag fault, level 1 */
> +            case 0x6: /* Access flag fault, level 2 */
> +            case 0x9: /* Domain fault, level 1 */
> +            case 0xb: /* Domain fault, level 2 */
> +            case 0xd: /* Permision fault, level 1 */
> +            case 0xf: /* Permision fault, level 2 */
> +                si_signo = TARGET_SIGSEGV;
> +                si_code = TARGET_SEGV_ACCERR;
> +                break;
> +            case 0x5: /* Translation fault, level 1 */
> +            case 0x7: /* Translation fault, level 2 */
> +                si_signo = TARGET_SIGSEGV;
> +                si_code = TARGET_SEGV_MAPERR;
> +                break;
> +            default:
> +                g_assert_not_reached();
> +            }
> +            force_sig_fault(si_signo, si_code, env->exception.vaddress);
>              break;
>          case EXCP_DEBUG:
>          case EXCP_BKPT:
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 7a18a58ca0..a211804fd3 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -2035,6 +2035,7 @@ static const struct TCGCPUOps arm_tcg_ops = {
>
>  #ifdef CONFIG_USER_ONLY
>      .record_sigsegv = arm_cpu_record_sigsegv,
> +    .record_sigbus = arm_cpu_record_sigbus,
>  #else
>      .tlb_fill = arm_cpu_tlb_fill,
>      .cpu_exec_interrupt = arm_cpu_exec_interrupt,
> diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
> index 7b3bea2fbb..13d0e9b195 100644
> --- a/target/arm/cpu_tcg.c
> +++ b/target/arm/cpu_tcg.c
> @@ -902,6 +902,7 @@ static const struct TCGCPUOps arm_v7m_tcg_ops = {
>
>  #ifdef CONFIG_USER_ONLY
>      .record_sigsegv = arm_cpu_record_sigsegv,
> +    .record_sigbus = arm_cpu_record_sigbus,
>  #else
>      .tlb_fill = arm_cpu_tlb_fill,
>      .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
> diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
> index dc5860180f..12a934e924 100644
> --- a/target/arm/tlb_helper.c
> +++ b/target/arm/tlb_helper.c
> @@ -213,4 +213,10 @@ void arm_cpu_record_sigsegv(CPUState *cs, vaddr addr,
>      cpu_restore_state(cs, ra, true);
>      arm_deliver_fault(cpu, addr, access_type, MMU_USER_IDX, &fi);
>  }
> +
> +void arm_cpu_record_sigbus(CPUState *cs, vaddr addr,
> +                           MMUAccessType access_type, uintptr_t ra)
> +{
> +    arm_cpu_do_unaligned_access(cs, addr, access_type, MMU_USER_IDX, ra);
> +}
>  #endif /* !defined(CONFIG_USER_ONLY) */
> --
> 2.25.1
>
>

Reply via email to