[for-6.2,09/43] target/riscv: Implement do_unaligned_access for user-only

Message ID 20210729004647.282017-10-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: qemu-riscv@nongnu.org
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 linux-user/riscv/cpu_loop.c | 7 +++++++
 target/riscv/cpu.c          | 2 +-
 target/riscv/cpu_helper.c   | 8 +++++++-
 3 files changed, 15 insertions(+), 2 deletions(-)

-- 
2.25.1

Comments

Alistair Francis July 30, 2021, 6:13 a.m. | #1
On Thu, Jul 29, 2021 at 10:55 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> Cc: qemu-riscv@nongnu.org

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


Reviewed-by: Alistair Francis <alistair.francis@wdc.com>


Alistair

> ---

>  linux-user/riscv/cpu_loop.c | 7 +++++++

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

>  target/riscv/cpu_helper.c   | 8 +++++++-

>  3 files changed, 15 insertions(+), 2 deletions(-)

>

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

> index 74a9628dc9..0428140d86 100644

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

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

> @@ -92,6 +92,13 @@ void cpu_loop(CPURISCVState *env)

>              sigcode = TARGET_SEGV_MAPERR;

>              sigaddr = env->badaddr;

>              break;

> +        case RISCV_EXCP_INST_ADDR_MIS:

> +        case RISCV_EXCP_LOAD_ADDR_MIS:

> +        case RISCV_EXCP_STORE_AMO_ADDR_MIS:

> +            signum = TARGET_SIGBUS;

> +            sigcode = TARGET_BUS_ADRALN;

> +            sigaddr = env->badaddr;

> +            break;

>          case RISCV_EXCP_SEMIHOST:

>              env->gpr[xA0] = do_common_semihosting(cs);

>              env->pc += 4;

> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c

> index 991a6bb760..591d17e62d 100644

> --- a/target/riscv/cpu.c

> +++ b/target/riscv/cpu.c

> @@ -644,11 +644,11 @@ static const struct TCGCPUOps riscv_tcg_ops = {

>      .synchronize_from_tb = riscv_cpu_synchronize_from_tb,

>      .cpu_exec_interrupt = riscv_cpu_exec_interrupt,

>      .tlb_fill = riscv_cpu_tlb_fill,

> +    .do_unaligned_access = riscv_cpu_do_unaligned_access,

>

>  #ifndef CONFIG_USER_ONLY

>      .do_interrupt = riscv_cpu_do_interrupt,

>      .do_transaction_failed = riscv_cpu_do_transaction_failed,

> -    .do_unaligned_access = riscv_cpu_do_unaligned_access,

>  #endif /* !CONFIG_USER_ONLY */

>  };

>

> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c

> index 968cb8046f..a440b2834f 100644

> --- a/target/riscv/cpu_helper.c

> +++ b/target/riscv/cpu_helper.c

> @@ -727,6 +727,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,

>                              riscv_cpu_two_stage_lookup(mmu_idx);

>      riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);

>  }

> +#endif /* !CONFIG_USER_ONLY */

>

>  void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,

>                                     MMUAccessType access_type, int mmu_idx,

> @@ -734,6 +735,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,

>  {

>      RISCVCPU *cpu = RISCV_CPU(cs);

>      CPURISCVState *env = &cpu->env;

> +

>      switch (access_type) {

>      case MMU_INST_FETCH:

>          cs->exception_index = RISCV_EXCP_INST_ADDR_MIS;

> @@ -748,11 +750,15 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,

>          g_assert_not_reached();

>      }

>      env->badaddr = addr;

> +

> +#ifdef CONFIG_USER_ONLY

> +    cpu_loop_exit_restore(cs, retaddr);

> +#else

>      env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||

>                              riscv_cpu_two_stage_lookup(mmu_idx);

>      riscv_raise_exception(env, cs->exception_index, retaddr);

> +#endif

>  }

> -#endif /* !CONFIG_USER_ONLY */

>

>  bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,

>                          MMUAccessType access_type, int mmu_idx,

> --

> 2.25.1

>

>

Patch

diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index 74a9628dc9..0428140d86 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -92,6 +92,13 @@  void cpu_loop(CPURISCVState *env)
             sigcode = TARGET_SEGV_MAPERR;
             sigaddr = env->badaddr;
             break;
+        case RISCV_EXCP_INST_ADDR_MIS:
+        case RISCV_EXCP_LOAD_ADDR_MIS:
+        case RISCV_EXCP_STORE_AMO_ADDR_MIS:
+            signum = TARGET_SIGBUS;
+            sigcode = TARGET_BUS_ADRALN;
+            sigaddr = env->badaddr;
+            break;
         case RISCV_EXCP_SEMIHOST:
             env->gpr[xA0] = do_common_semihosting(cs);
             env->pc += 4;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 991a6bb760..591d17e62d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -644,11 +644,11 @@  static const struct TCGCPUOps riscv_tcg_ops = {
     .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
     .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
     .tlb_fill = riscv_cpu_tlb_fill,
+    .do_unaligned_access = riscv_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
     .do_interrupt = riscv_cpu_do_interrupt,
     .do_transaction_failed = riscv_cpu_do_transaction_failed,
-    .do_unaligned_access = riscv_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 968cb8046f..a440b2834f 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -727,6 +727,7 @@  void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
                             riscv_cpu_two_stage_lookup(mmu_idx);
     riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);
 }
+#endif /* !CONFIG_USER_ONLY */
 
 void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
                                    MMUAccessType access_type, int mmu_idx,
@@ -734,6 +735,7 @@  void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
+
     switch (access_type) {
     case MMU_INST_FETCH:
         cs->exception_index = RISCV_EXCP_INST_ADDR_MIS;
@@ -748,11 +750,15 @@  void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
         g_assert_not_reached();
     }
     env->badaddr = addr;
+
+#ifdef CONFIG_USER_ONLY
+    cpu_loop_exit_restore(cs, retaddr);
+#else
     env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
                             riscv_cpu_two_stage_lookup(mmu_idx);
     riscv_raise_exception(env, cs->exception_index, retaddr);
+#endif
 }
-#endif /* !CONFIG_USER_ONLY */
 
 bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                         MMUAccessType access_type, int mmu_idx,