qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-arm] [PATCH v2 2/2] target/arm: A32, T32: Create Instruction S


From: Edgar E. Iglesias
Subject: Re: [Qemu-arm] [PATCH v2 2/2] target/arm: A32, T32: Create Instruction Syndromes for Data Aborts
Date: Sat, 4 Feb 2017 15:31:32 +0100
User-agent: Mutt/1.5.24 (2015-08-30)

On Fri, Feb 03, 2017 at 05:48:55PM +0000, Peter Maydell wrote:
> Add support for generating the ISS (Instruction Specific Syndrome)
> for Data Abort exceptions taken from AArch32. These syndromes are
> used by hypervisors for example to trap and emulate memory accesses.
> 
> This is the equivalent for AArch32 guests of the work done for AArch64
> guests in commit aaa1f954d4cab243.

Hi Peter,


> 
> Signed-off-by: Peter Maydell <address@hidden>
> ---
>  target/arm/translate.c | 198 
> +++++++++++++++++++++++++++++++++++++------------
>  1 file changed, 149 insertions(+), 49 deletions(-)
> 
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 175b4c1..fc0ddcd 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -102,6 +102,63 @@ void arm_translate_init(void)
>      a64_translate_init();
>  }
>  
> +static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
> +{
> +    /* We don't need to save all of the syndrome so we mask and shift
> +     * out uneeded bits to help the sleb128 encoder do a better job.
> +     */
> +    syn &= ARM_INSN_START_WORD2_MASK;
> +    syn >>= ARM_INSN_START_WORD2_SHIFT;
> +
> +    /* We check and clear insn_start_idx to catch multiple updates.  */
> +    assert(s->insn_start_idx != 0);
> +    tcg_set_insn_param(s->insn_start_idx, 2, syn);
> +    s->insn_start_idx = 0;
> +}

Could we move this into translate.h and share it with translate-a64.c?

Other than that this looks good to me!
Reviewed-by: Edgar E. Iglesias <address@hidden>

Thanks,
Edgar


> +
> +/* Flags for the disas_set_da_iss info argument:
> + * lower bits hold the Rt register number, higher bits are flags.
> + */
> +typedef enum ISSInfo {
> +    ISSNone = 0,
> +    ISSRegMask = 0x1f,
> +    ISSInvalid = (1 << 5),
> +    ISSIsAcqRel = (1 << 6),
> +    ISSIsWrite = (1 << 7),
> +    ISSIs16Bit = (1 << 8),
> +} ISSInfo;
> +
> +/* Save the syndrome information for a Data Abort */
> +static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo 
> issinfo)
> +{
> +    uint32_t syn;
> +    int sas = memop & MO_SIZE;
> +    bool sse = memop & MO_SIGN;
> +    bool is_acqrel = issinfo & ISSIsAcqRel;
> +    bool is_write = issinfo & ISSIsWrite;
> +    bool is_16bit = issinfo & ISSIs16Bit;
> +    int srt = issinfo & ISSRegMask;
> +
> +    if (issinfo & ISSInvalid) {
> +        /* Some callsites want to conditionally provide ISS info,
> +         * eg "only if this was not a writeback"
> +         */
> +        return;
> +    }
> +
> +    if (srt == 15) {
> +        /* For AArch32, insns where the src/dest is R15 never generate
> +         * ISS information. Catching that here saves checking at all
> +         * the call sites.
> +         */
> +        return;
> +    }
> +
> +    syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
> +                                  0, 0, 0, is_write, 0, is_16bit);
> +    disas_set_insn_syndrome(s, syn);
> +}
> +
>  static inline ARMMMUIdx get_a32_user_mem_index(DisasContext *s)
>  {
>      /* Return the mmu_idx to use for A32/T32 "unprivileged load/store"
> @@ -933,6 +990,14 @@ static inline void gen_aa32_ld##SUFF(DisasContext *s, 
> TCGv_i32 val,      \
>                                       TCGv_i32 a32, int index)            \
>  {                                                                        \
>      gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data);               \
> +}                                                                        \
> +static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s,              \
> +                                           TCGv_i32 val,                 \
> +                                           TCGv_i32 a32, int index,      \
> +                                           ISSInfo issinfo)              \
> +{                                                                        \
> +    gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data);               \
> +    disas_set_da_iss(s, OPC, issinfo);                                   \
>  }
>  
>  #define DO_GEN_ST(SUFF, OPC)                                             \
> @@ -940,6 +1005,14 @@ static inline void gen_aa32_st##SUFF(DisasContext *s, 
> TCGv_i32 val,      \
>                                       TCGv_i32 a32, int index)            \
>  {                                                                        \
>      gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data);               \
> +}                                                                        \
> +static inline void gen_aa32_st##SUFF##_iss(DisasContext *s,              \
> +                                           TCGv_i32 val,                 \
> +                                           TCGv_i32 a32, int index,      \
> +                                           ISSInfo issinfo)              \
> +{                                                                        \
> +    gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data);               \
> +    disas_set_da_iss(s, OPC, issinfo | ISSIsWrite);                      \
>  }
>  
>  static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
> @@ -8682,16 +8755,19 @@ static void disas_arm_insn(DisasContext *s, unsigned 
> int insn)
>                                  tmp = tcg_temp_new_i32();
>                                  switch (op1) {
>                                  case 0: /* lda */
> -                                    gen_aa32_ld32u(s, tmp, addr,
> -                                                   get_mem_index(s));
> +                                    gen_aa32_ld32u_iss(s, tmp, addr,
> +                                                       get_mem_index(s),
> +                                                       rd | ISSIsAcqRel);
>                                      break;
>                                  case 2: /* ldab */
> -                                    gen_aa32_ld8u(s, tmp, addr,
> -                                                  get_mem_index(s));
> +                                    gen_aa32_ld8u_iss(s, tmp, addr,
> +                                                      get_mem_index(s),
> +                                                      rd | ISSIsAcqRel);
>                                      break;
>                                  case 3: /* ldah */
> -                                    gen_aa32_ld16u(s, tmp, addr,
> -                                                   get_mem_index(s));
> +                                    gen_aa32_ld16u_iss(s, tmp, addr,
> +                                                       get_mem_index(s),
> +                                                       rd | ISSIsAcqRel);
>                                      break;
>                                  default:
>                                      abort();
> @@ -8702,16 +8778,19 @@ static void disas_arm_insn(DisasContext *s, unsigned 
> int insn)
>                                  tmp = load_reg(s, rm);
>                                  switch (op1) {
>                                  case 0: /* stl */
> -                                    gen_aa32_st32(s, tmp, addr,
> -                                                  get_mem_index(s));
> +                                    gen_aa32_st32_iss(s, tmp, addr,
> +                                                      get_mem_index(s),
> +                                                      rm | ISSIsAcqRel);
>                                      break;
>                                  case 2: /* stlb */
> -                                    gen_aa32_st8(s, tmp, addr,
> -                                                 get_mem_index(s));
> +                                    gen_aa32_st8_iss(s, tmp, addr,
> +                                                     get_mem_index(s),
> +                                                     rm | ISSIsAcqRel);
>                                      break;
>                                  case 3: /* stlh */
> -                                    gen_aa32_st16(s, tmp, addr,
> -                                                  get_mem_index(s));
> +                                    gen_aa32_st16_iss(s, tmp, addr,
> +                                                      get_mem_index(s),
> +                                                      rm | ISSIsAcqRel);
>                                      break;
>                                  default:
>                                      abort();
> @@ -8785,10 +8864,15 @@ static void disas_arm_insn(DisasContext *s, unsigned 
> int insn)
>                  bool wbit = insn & (1 << 21);
>                  bool pbit = insn & (1 << 24);
>                  bool doubleword = false;
> +                ISSInfo issinfo;
> +
>                  /* Misc load/store */
>                  rn = (insn >> 16) & 0xf;
>                  rd = (insn >> 12) & 0xf;
>  
> +                /* ISS not valid if writeback */
> +                issinfo = (pbit & !wbit) ? rd : ISSInvalid;
> +
>                  if (!load && (sh & 2)) {
>                      /* doubleword */
>                      ARCH(5TE);
> @@ -8832,20 +8916,23 @@ static void disas_arm_insn(DisasContext *s, unsigned 
> int insn)
>                      tmp = tcg_temp_new_i32();
>                      switch (sh) {
>                      case 1:
> -                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
> +                        gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
> +                                           issinfo);
>                          break;
>                      case 2:
> -                        gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
> +                        gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
> +                                          issinfo);
>                          break;
>                      default:
>                      case 3:
> -                        gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
> +                        gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
> +                                           issinfo);
>                          break;
>                      }
>                  } else {
>                      /* store */
>                      tmp = load_reg(s, rd);
> -                    gen_aa32_st16(s, tmp, addr, get_mem_index(s));
> +                    gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), 
> issinfo);
>                      tcg_temp_free_i32(tmp);
>                  }
>                  /* Perform base writeback before the loaded value to
> @@ -9198,17 +9285,17 @@ static void disas_arm_insn(DisasContext *s, unsigned 
> int insn)
>                  /* load */
>                  tmp = tcg_temp_new_i32();
>                  if (insn & (1 << 22)) {
> -                    gen_aa32_ld8u(s, tmp, tmp2, i);
> +                    gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
>                  } else {
> -                    gen_aa32_ld32u(s, tmp, tmp2, i);
> +                    gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
>                  }
>              } else {
>                  /* store */
>                  tmp = load_reg(s, rd);
>                  if (insn & (1 << 22)) {
> -                    gen_aa32_st8(s, tmp, tmp2, i);
> +                    gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
>                  } else {
> -                    gen_aa32_st32(s, tmp, tmp2, i);
> +                    gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
>                  }
>                  tcg_temp_free_i32(tmp);
>              }
> @@ -9669,13 +9756,16 @@ static int disas_thumb2_insn(CPUARMState *env, 
> DisasContext *s, uint16_t insn_hw
>                          tmp = tcg_temp_new_i32();
>                          switch (op) {
>                          case 0: /* ldab */
> -                            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
> +                            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
> +                                              rs | ISSIsAcqRel);
>                              break;
>                          case 1: /* ldah */
> -                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
> +                            gen_aa32_ld16u_iss(s, tmp, addr, 
> get_mem_index(s),
> +                                               rs | ISSIsAcqRel);
>                              break;
>                          case 2: /* lda */
> -                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
> +                            gen_aa32_ld32u_iss(s, tmp, addr, 
> get_mem_index(s),
> +                                               rs | ISSIsAcqRel);
>                              break;
>                          default:
>                              abort();
> @@ -9685,13 +9775,16 @@ static int disas_thumb2_insn(CPUARMState *env, 
> DisasContext *s, uint16_t insn_hw
>                          tmp = load_reg(s, rs);
>                          switch (op) {
>                          case 0: /* stlb */
> -                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
> +                            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
> +                                             rs | ISSIsAcqRel);
>                              break;
>                          case 1: /* stlh */
> -                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
> +                            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
> +                                              rs | ISSIsAcqRel);
>                              break;
>                          case 2: /* stl */
> -                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
> +                            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
> +                                              rs | ISSIsAcqRel);
>                              break;
>                          default:
>                              abort();
> @@ -10637,6 +10730,8 @@ static int disas_thumb2_insn(CPUARMState *env, 
> DisasContext *s, uint16_t insn_hw
>          int postinc = 0;
>          int writeback = 0;
>          int memidx;
> +        ISSInfo issinfo;
> +
>          if ((insn & 0x01100000) == 0x01000000) {
>              if (disas_neon_ls_insn(s, insn)) {
>                  goto illegal_op;
> @@ -10740,24 +10835,27 @@ static int disas_thumb2_insn(CPUARMState *env, 
> DisasContext *s, uint16_t insn_hw
>                  }
>              }
>          }
> +
> +        issinfo = writeback ? ISSInvalid : rs;
> +
>          if (insn & (1 << 20)) {
>              /* Load.  */
>              tmp = tcg_temp_new_i32();
>              switch (op) {
>              case 0:
> -                gen_aa32_ld8u(s, tmp, addr, memidx);
> +                gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              case 4:
> -                gen_aa32_ld8s(s, tmp, addr, memidx);
> +                gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              case 1:
> -                gen_aa32_ld16u(s, tmp, addr, memidx);
> +                gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              case 5:
> -                gen_aa32_ld16s(s, tmp, addr, memidx);
> +                gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              case 2:
> -                gen_aa32_ld32u(s, tmp, addr, memidx);
> +                gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              default:
>                  tcg_temp_free_i32(tmp);
> @@ -10774,13 +10872,13 @@ static int disas_thumb2_insn(CPUARMState *env, 
> DisasContext *s, uint16_t insn_hw
>              tmp = load_reg(s, rs);
>              switch (op) {
>              case 0:
> -                gen_aa32_st8(s, tmp, addr, memidx);
> +                gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              case 1:
> -                gen_aa32_st16(s, tmp, addr, memidx);
> +                gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              case 2:
> -                gen_aa32_st32(s, tmp, addr, memidx);
> +                gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
>                  break;
>              default:
>                  tcg_temp_free_i32(tmp);
> @@ -10917,7 +11015,8 @@ static void disas_thumb_insn(CPUARMState *env, 
> DisasContext *s)
>              addr = tcg_temp_new_i32();
>              tcg_gen_movi_i32(addr, val);
>              tmp = tcg_temp_new_i32();
> -            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
> +                               rd | ISSIs16Bit);
>              tcg_temp_free_i32(addr);
>              store_reg(s, rd, tmp);
>              break;
> @@ -11120,28 +11219,28 @@ static void disas_thumb_insn(CPUARMState *env, 
> DisasContext *s)
>  
>          switch (op) {
>          case 0: /* str */
> -            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 1: /* strh */
> -            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 2: /* strb */
> -            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 3: /* ldrsb */
> -            gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 4: /* ldr */
> -            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 5: /* ldrh */
> -            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 6: /* ldrb */
> -            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          case 7: /* ldrsh */
> -            gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              break;
>          }
>          if (op >= 3) { /* load */
> @@ -11185,12 +11284,12 @@ static void disas_thumb_insn(CPUARMState *env, 
> DisasContext *s)
>          if (insn & (1 << 11)) {
>              /* load */
>              tmp = tcg_temp_new_i32();
> -            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              store_reg(s, rd, tmp);
>          } else {
>              /* store */
>              tmp = load_reg(s, rd);
> -            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              tcg_temp_free_i32(tmp);
>          }
>          tcg_temp_free_i32(addr);
> @@ -11207,12 +11306,12 @@ static void disas_thumb_insn(CPUARMState *env, 
> DisasContext *s)
>          if (insn & (1 << 11)) {
>              /* load */
>              tmp = tcg_temp_new_i32();
> -            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              store_reg(s, rd, tmp);
>          } else {
>              /* store */
>              tmp = load_reg(s, rd);
> -            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              tcg_temp_free_i32(tmp);
>          }
>          tcg_temp_free_i32(addr);
> @@ -11228,12 +11327,12 @@ static void disas_thumb_insn(CPUARMState *env, 
> DisasContext *s)
>          if (insn & (1 << 11)) {
>              /* load */
>              tmp = tcg_temp_new_i32();
> -            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              store_reg(s, rd, tmp);
>          } else {
>              /* store */
>              tmp = load_reg(s, rd);
> -            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
> +            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | 
> ISSIs16Bit);
>              tcg_temp_free_i32(tmp);
>          }
>          tcg_temp_free_i32(addr);
> @@ -11715,6 +11814,7 @@ void gen_intermediate_code(CPUARMState *env, 
> TranslationBlock *tb)
>          store_cpu_field(tmp, condexec_bits);
>        }
>      do {
> +        dc->insn_start_idx = tcg_op_buf_count();
>          tcg_gen_insn_start(dc->pc,
>                             (dc->condexec_cond << 4) | (dc->condexec_mask >> 
> 1),
>                             0);
> -- 
> 2.7.4
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]