Richard Henderson <r...@twiddle.net> writes:

> Rather than using helpers for physical accesses, use a mmu index.
> The primary cleanup is with store-conditional on physical addresses.
>
> Signed-off-by: Richard Henderson <r...@twiddle.net>
> ---
>  target-alpha/cpu.h        | 18 +++++-------
>  target-alpha/helper.c     | 10 ++++++-
>  target-alpha/helper.h     |  9 ------
>  target-alpha/mem_helper.c | 73 
> -----------------------------------------------
>  target-alpha/translate.c  | 50 ++++++++++++++++++--------------
>  5 files changed, 45 insertions(+), 115 deletions(-)
>
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index ac5e801..9d9489c 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -201,7 +201,7 @@ enum {
>
>  /* MMU modes definitions */
>
> -/* Alpha has 5 MMU modes: PALcode, kernel, executive, supervisor, and user.
> +/* Alpha has 5 MMU modes: PALcode, Kernel, Executive, Supervisor, and User.
>     The Unix PALcode only exposes the kernel and user modes; presumably
>     executive and supervisor are used by VMS.
>
> @@ -209,22 +209,18 @@ enum {
>     there are PALmode instructions that can access data via physical mode
>     or via an os-installed "alternate mode", which is one of the 4 above.
>
> -   QEMU does not currently properly distinguish between code/data when
> -   looking up addresses.  To avoid having to address this issue, our
> -   emulated PALcode will cheat and use the KSEG mapping for its code+data
> -   rather than physical addresses.
> +   That said, we're only emulating Unix PALcode, and not attempting VMS,
> +   so we don't need to implement Executive and Supervisor.  QEMU's own
> +   PALcode cheats and usees the KSEG mapping for its code+data rather than
> +   physical addresses.  */
>
> -   Moreover, we're only emulating Unix PALcode, and not attempting VMS.
> -
> -   All of which allows us to drop all but kernel and user modes.
> -   Elide the unused MMU modes to save space.  */
> -
> -#define NB_MMU_MODES 2
> +#define NB_MMU_MODES 3
>
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _user
>  #define MMU_KERNEL_IDX   0
>  #define MMU_USER_IDX     1
> +#define MMU_PHYS_IDX     2
>
>  typedef struct CPUAlphaState CPUAlphaState;
>
> diff --git a/target-alpha/helper.c b/target-alpha/helper.c
> index 85168b7..1ed0725 100644
> --- a/target-alpha/helper.c
> +++ b/target-alpha/helper.c
> @@ -126,6 +126,14 @@ static int get_physical_address(CPUAlphaState *env, 
> target_ulong addr,
>      int prot = 0;
>      int ret = MM_K_ACV;
>
> +    /* Handle physical accesses.  */
> +    if (mmu_idx == MMU_PHYS_IDX) {
> +        phys = addr;
> +        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> +        ret = -1;
> +        goto exit;
> +    }
> +
>      /* Ensure that the virtual address is properly sign-extended from
>         the last implemented virtual address bit.  */
>      if (saddr >> TARGET_VIRT_ADDR_SPACE_BITS != saddr >> 63) {
> @@ -137,7 +145,7 @@ static int get_physical_address(CPUAlphaState *env, 
> target_ulong addr,
>         determine which KSEG is actually active.  */
>      if (saddr < 0 && ((saddr >> 41) & 3) == 2) {
>          /* User-space cannot access KSEG addresses.  */
> -        if (mmu_idx != MMU_KERNEL_IDX) {
> +        if (mmu_idx < MMU_KERNEL_IDX) {
>              goto exit;
>          }

I'm confused by this change. It's not the same test and when is mmu_idx ever
< 0?

>
> diff --git a/target-alpha/helper.h b/target-alpha/helper.h
> index c3d8a3e..004221d 100644
> --- a/target-alpha/helper.h
> +++ b/target-alpha/helper.h
> @@ -92,15 +92,6 @@ DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, 
> env, i64)
>  DEF_HELPER_FLAGS_2(ieee_input_s, TCG_CALL_NO_WG, void, env, i64)
>
>  #if !defined (CONFIG_USER_ONLY)
> -DEF_HELPER_2(ldl_phys, i64, env, i64)
> -DEF_HELPER_2(ldq_phys, i64, env, i64)
> -DEF_HELPER_2(ldl_l_phys, i64, env, i64)
> -DEF_HELPER_2(ldq_l_phys, i64, env, i64)
> -DEF_HELPER_3(stl_phys, void, env, i64, i64)
> -DEF_HELPER_3(stq_phys, void, env, i64, i64)
> -DEF_HELPER_3(stl_c_phys, i64, env, i64, i64)
> -DEF_HELPER_3(stq_c_phys, i64, env, i64, i64)
> -
>  DEF_HELPER_FLAGS_1(tbia, TCG_CALL_NO_RWG, void, env)
>  DEF_HELPER_FLAGS_2(tbis, TCG_CALL_NO_RWG, void, env, i64)
>  DEF_HELPER_FLAGS_1(tb_flush, TCG_CALL_NO_RWG, void, env)
> diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
> index 1b2be50..78a7d45 100644
> --- a/target-alpha/mem_helper.c
> +++ b/target-alpha/mem_helper.c
> @@ -25,79 +25,6 @@
>
>  /* Softmmu support */
>  #ifndef CONFIG_USER_ONLY
> -
> -uint64_t helper_ldl_phys(CPUAlphaState *env, uint64_t p)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    return (int32_t)ldl_phys(cs->as, p);
> -}
> -
> -uint64_t helper_ldq_phys(CPUAlphaState *env, uint64_t p)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    return ldq_phys(cs->as, p);
> -}
> -
> -uint64_t helper_ldl_l_phys(CPUAlphaState *env, uint64_t p)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    env->lock_addr = p;
> -    return env->lock_value = (int32_t)ldl_phys(cs->as, p);
> -}
> -
> -uint64_t helper_ldq_l_phys(CPUAlphaState *env, uint64_t p)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    env->lock_addr = p;
> -    return env->lock_value = ldq_phys(cs->as, p);
> -}
> -
> -void helper_stl_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    stl_phys(cs->as, p, v);
> -}
> -
> -void helper_stq_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    stq_phys(cs->as, p, v);
> -}
> -
> -uint64_t helper_stl_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    uint64_t ret = 0;
> -
> -    if (p == env->lock_addr) {
> -        int32_t old = ldl_phys(cs->as, p);
> -        if (old == (int32_t)env->lock_value) {
> -            stl_phys(cs->as, p, v);
> -            ret = 1;
> -        }
> -    }
> -    env->lock_addr = -1;
> -
> -    return ret;
> -}
> -
> -uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
> -{
> -    CPUState *cs = CPU(alpha_env_get_cpu(env));
> -    uint64_t ret = 0;
> -
> -    if (p == env->lock_addr) {
> -        uint64_t old = ldq_phys(cs->as, p);
> -        if (old == env->lock_value) {
> -            stq_phys(cs->as, p, v);
> -            ret = 1;
> -        }
> -    }
> -    env->lock_addr = -1;
> -
> -    return ret;
> -}
> -
>  void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
>                                     MMUAccessType access_type,
>                                     int mmu_idx, uintptr_t retaddr)
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index 0ea0e6e..2941159 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -392,7 +392,8 @@ static inline void gen_store_mem(DisasContext *ctx,
>  }
>
>  static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
> -                                        int32_t disp16, int quad)
> +                                        int32_t disp16, int mem_idx,
> +                                        TCGMemOp op)
>  {
>      TCGv addr;
>
> @@ -414,7 +415,7 @@ static ExitStatus gen_store_conditional(DisasContext 
> *ctx, int ra, int rb,
>      /* ??? This is handled via a complicated version of compare-and-swap
>         in the cpu_loop.  Hopefully one day we'll have a real CAS opcode
>         in TCG so that this isn't necessary.  */
> -    return gen_excp(ctx, quad ? EXCP_STQ_C : EXCP_STL_C, ra);
> +    return gen_excp(ctx, (op & MO_SIZE) == MO_64 ? EXCP_STQ_C : EXCP_STL_C, 
> ra);
>  #else
>      /* ??? In system mode we are never multi-threaded, so CAS can be
>         implemented via a non-atomic load-compare-store sequence.  */
> @@ -427,11 +428,10 @@ static ExitStatus gen_store_conditional(DisasContext 
> *ctx, int ra, int rb,
>          tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
>
>          val = tcg_temp_new();
> -        tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : 
> MO_LESL);
> +        tcg_gen_qemu_ld_i64(val, addr, mem_idx, op);
>          tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
>
> -        tcg_gen_qemu_st_i64(ctx->ir[ra], addr, ctx->mem_idx,
> -                            quad ? MO_LEQ : MO_LEUL);
> +        tcg_gen_qemu_st_i64(ctx->ir[ra], addr, mem_idx, op);
>          tcg_gen_movi_i64(ctx->ir[ra], 1);
>          tcg_gen_br(lab_done);
>
> @@ -2423,19 +2423,19 @@ static ExitStatus translate_one(DisasContext *ctx, 
> uint32_t insn)
>              switch ((insn >> 12) & 0xF) {
>              case 0x0:
>                  /* Longword physical access (hw_ldl/p) */
> -                gen_helper_ldl_phys(va, cpu_env, addr);
> +                tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL);
>                  break;
>              case 0x1:
>                  /* Quadword physical access (hw_ldq/p) */
> -                gen_helper_ldq_phys(va, cpu_env, addr);
> +                tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ);
>                  break;
>              case 0x2:
>                  /* Longword physical access with lock (hw_ldl_l/p) */
> -                gen_helper_ldl_l_phys(va, cpu_env, addr);
> +                gen_qemu_ldl_l(va, addr, MMU_PHYS_IDX);
>                  break;
>              case 0x3:
>                  /* Quadword physical access with lock (hw_ldq_l/p) */
> -                gen_helper_ldq_l_phys(va, cpu_env, addr);
> +                gen_qemu_ldq_l(va, addr, MMU_PHYS_IDX);
>                  break;
>              case 0x4:
>                  /* Longword virtual PTE fetch (hw_ldl/v) */
> @@ -2674,27 +2674,34 @@ static ExitStatus translate_one(DisasContext *ctx, 
> uint32_t insn)
>  #ifndef CONFIG_USER_ONLY
>          REQUIRE_TB_FLAG(TB_FLAGS_PAL_MODE);
>          {
> -            TCGv addr = tcg_temp_new();
> -            va = load_gpr(ctx, ra);
> -            vb = load_gpr(ctx, rb);
> -
> -            tcg_gen_addi_i64(addr, vb, disp12);
>              switch ((insn >> 12) & 0xF) {
>              case 0x0:
>                  /* Longword physical access */
> -                gen_helper_stl_phys(cpu_env, addr, va);
> +                va = load_gpr(ctx, ra);
> +                vb = load_gpr(ctx, rb);
> +                tmp = tcg_temp_new();
> +                tcg_gen_addi_i64(tmp, vb, disp12);
> +                tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL);
> +                tcg_temp_free(tmp);
>                  break;
>              case 0x1:
>                  /* Quadword physical access */
> -                gen_helper_stq_phys(cpu_env, addr, va);
> +                va = load_gpr(ctx, ra);
> +                vb = load_gpr(ctx, rb);
> +                tmp = tcg_temp_new();
> +                tcg_gen_addi_i64(tmp, vb, disp12);
> +                tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEQ);
> +                tcg_temp_free(tmp);
>                  break;
>              case 0x2:
>                  /* Longword physical access with lock */
> -                gen_helper_stl_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
> +                ret = gen_store_conditional(ctx, ra, rb, disp12,
> +                                            MMU_PHYS_IDX, MO_LESL);
>                  break;
>              case 0x3:
>                  /* Quadword physical access with lock */
> -                gen_helper_stq_c_phys(dest_gpr(ctx, ra), cpu_env, addr, va);
> +                ret = gen_store_conditional(ctx, ra, rb, disp12,
> +                                            MMU_PHYS_IDX, MO_LEQ);
>                  break;
>              case 0x4:
>                  /* Longword virtual access */
> @@ -2733,7 +2740,6 @@ static ExitStatus translate_one(DisasContext *ctx, 
> uint32_t insn)
>                  /* Invalid */
>                  goto invalid_opc;
>              }
> -            tcg_temp_free(addr);
>              break;
>          }
>  #else
> @@ -2797,11 +2803,13 @@ static ExitStatus translate_one(DisasContext *ctx, 
> uint32_t insn)
>          break;
>      case 0x2E:
>          /* STL_C */
> -        ret = gen_store_conditional(ctx, ra, rb, disp16, 0);
> +        ret = gen_store_conditional(ctx, ra, rb, disp16,
> +                                    ctx->mem_idx, MO_LESL);
>          break;
>      case 0x2F:
>          /* STQ_C */
> -        ret = gen_store_conditional(ctx, ra, rb, disp16, 1);
> +        ret = gen_store_conditional(ctx, ra, rb, disp16,
> +                                    ctx->mem_idx, MO_LEQ);
>          break;
>      case 0x30:
>          /* BR */


--
Alex Bennée

Reply via email to