qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 1/9] target-mips: Add CP0_Ebase.WG (write gate)


From: Yongbok Kim
Subject: Re: [Qemu-devel] [PATCH 1/9] target-mips: Add CP0_Ebase.WG (write gate) support
Date: Fri, 7 Oct 2016 14:42:15 +0100
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0


On 06/09/2016 12:03, James Hogan wrote:
> Add support for the CP0_EBase.WG bit, which allows upper bits to be
> written (bits 31:30 on MIPS32, or bits 63:30 on MIPS64), along with the
> CP0_Config5.CV bit to control whether the exception vector for Cache
> Error exceptions is forced into KSeg1.
> 
> This is necessary on MIPS32 to support Segmentation Control and Enhanced
> Virtual Addressing (EVA) extensions (where KSeg1 addresses may not
> represent an unmapped uncached segment).
> 
> It is also useful on MIPS64 to allow the exception base to reside in
> XKPhys, and possibly out of range of KSEG0 and KSEG1.
> 
> Signed-off-by: James Hogan <address@hidden>
> Cc: Leon Alrae <address@hidden>
> Cc: Aurelien Jarno <address@hidden>
> ---
>  target-mips/cpu.h            |  4 +++-
>  target-mips/helper.c         | 13 +++++++------
>  target-mips/machine.c        |  6 +++---
>  target-mips/op_helper.c      | 13 +++++++++++--
>  target-mips/translate.c      |  8 +++++---
>  target-mips/translate_init.c |  1 +
>  6 files changed, 30 insertions(+), 15 deletions(-)
> 
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 5182dc74ffa3..6ea2bf14c817 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -399,7 +399,9 @@ struct CPUMIPSState {
>  #define CP0Ca_EC    2
>      target_ulong CP0_EPC;
>      int32_t CP0_PRid;
> -    int32_t CP0_EBase;
> +    target_ulong CP0_EBase;
> +    target_ulong CP0_EBase_rw_bitmask;
> +#define CP0EBase_WG 11
>      target_ulong CP0_CMGCRBase;
>      int32_t CP0_Config0;
>  #define CP0C0_M    31
> diff --git a/target-mips/helper.c b/target-mips/helper.c
> index c864b15b97a8..29ebf391cb94 100644
> --- a/target-mips/helper.c
> +++ b/target-mips/helper.c
> @@ -821,11 +821,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
>          goto set_EPC;
>      case EXCP_CACHE:
>          cause = 30;
> -        if (env->CP0_Status & (1 << CP0St_BEV)) {
> -            offset = 0x100;
> -        } else {
> -            offset = 0x20000100;
> -        }
> +        offset = 0x100;
>   set_EPC:
>          if (!(env->CP0_Status & (1 << CP0St_EXL))) {
>              env->CP0_EPC = exception_resume_pc(env);
> @@ -851,9 +847,14 @@ void mips_cpu_do_interrupt(CPUState *cs)
>          env->hflags &= ~MIPS_HFLAG_BMASK;
>          if (env->CP0_Status & (1 << CP0St_BEV)) {
>              env->active_tc.PC = env->exception_base + 0x200;
> +        } else if (cause == 30 && !(env->CP0_Config5 & (1 << CP0C5_CV))) {

&& !Config3SC? per MIPS32PRA 4.10.1.6.
It is not able to check Config3SC yet as it has not been defined but it can
be added later after the patch #7

> +            /* Force KSeg1 for cache errors */
> +            env->active_tc.PC = (int32_t)KSEG1_BASE |
> +                                (env->CP0_EBase & 0x1FFFF000);
>          } else {
> -            env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
> +            env->active_tc.PC = env->CP0_EBase & ~0xfff;
>          }
> +
>          env->active_tc.PC += offset;
>          set_hflags_for_handler(env);
>          env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << 
> CP0Ca_EC);
> diff --git a/target-mips/machine.c b/target-mips/machine.c
> index a27f2f156da9..e795fecaa0d6 100644
> --- a/target-mips/machine.c
> +++ b/target-mips/machine.c
> @@ -206,8 +206,8 @@ const VMStateDescription vmstate_tlb = {
>  
>  const VMStateDescription vmstate_mips_cpu = {
>      .name = "cpu",
> -    .version_id = 8,
> -    .minimum_version_id = 8,
> +    .version_id = 9,
> +    .minimum_version_id = 9,
>      .post_load = cpu_post_load,
>      .fields = (VMStateField[]) {
>          /* Active TC */
> @@ -267,7 +267,7 @@ const VMStateDescription vmstate_mips_cpu = {
>          VMSTATE_INT32(env.CP0_Cause, MIPSCPU),
>          VMSTATE_UINTTL(env.CP0_EPC, MIPSCPU),
>          VMSTATE_INT32(env.CP0_PRid, MIPSCPU),
> -        VMSTATE_INT32(env.CP0_EBase, MIPSCPU),
> +        VMSTATE_UINTTL(env.CP0_EBase, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config0, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index ea2f2abe198c..71ad16e41dd4 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1526,14 +1526,23 @@ target_ulong helper_mftc0_ebase(CPUMIPSState *env)
>  
>  void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
>  {
> -    env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
> +    if (arg1 & (1 << CP0EBase_WG) & env->CP0_EBase_rw_bitmask) {

I guess it has to check the WG bit of EBase register rather than the new WG
bit value. "To ensure backward compatibility with MIPS32, the write-gate
bit must be set before the upper bits can be changed."

CP0_EBase_rw_bitmask is now added but it is not really used other than WG
bit. Perhaps rename it into something like CP0_EBaseWG_rw_bitmask would be
better to avoid any confusion. Otherwise assign those hard-coded mask into
the bitmask variable in the cpu_state_reset().

> +        env->CP0_EBase = (env->CP0_EBase & 0x7ff) | (arg1 & ~0x7ff);
> +    } else {
> +        env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF800) | (arg1 & 
> 0x3FFFF800);
> +    }
>  }
>  
>  void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
>  {
>      int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
>      CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
> -    other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 
> 0x3FFFF000);
> +    if (arg1 & (1 << CP0EBase_WG) & env->CP0_EBase_rw_bitmask) {

Same here.

> +        other->CP0_EBase = (other->CP0_EBase & 0x7ff) | (arg1 & ~0x7ff);
> +    } else {
> +        other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF800) |
> +                           (arg1 & 0x3FFFF800);
> +    }
>  }
>  
>  target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index bab52cb25498..e224c2f09af4 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -5316,7 +5316,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int 
> reg, int sel)
>              break;
>          case 1:
>              check_insn(ctx, ISA_MIPS32R2);
> -            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
> +            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
> +            tcg_gen_ext32s_tl(arg, arg);
>              rn = "EBase";
>              break;
>          case 3:
> @@ -6630,7 +6631,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int 
> reg, int sel)
>              break;
>          case 1:
>              check_insn(ctx, ISA_MIPS32R2);
> -            gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
> +            tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
>              rn = "EBase";
>              break;
>          case 3:
> @@ -20247,6 +20248,7 @@ void cpu_state_reset(CPUMIPSState *env)
>      env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
>      env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
>      env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
> +    env->CP0_EBase_rw_bitmask = env->cpu_model->CP0_EBase_rw_bitmask;
>      env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
>      env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
>      env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
> @@ -20297,7 +20299,7 @@ void cpu_state_reset(CPUMIPSState *env)
>      if (kvm_enabled()) {
>          env->CP0_EBase |= 0x40000000;
>      } else {
> -        env->CP0_EBase |= 0x80000000;
> +        env->CP0_EBase |= (int32_t)0x80000000;
>      }
>      if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
>          env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
> diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
> index 39ed5c4c1b12..f327e6e7de6c 100644
> --- a/target-mips/translate_init.c
> +++ b/target-mips/translate_init.c
> @@ -101,6 +101,7 @@ struct mips_def_t {
>      int32_t CP0_SRSConf4;
>      int32_t CP0_PageGrain_rw_bitmask;
>      int32_t CP0_PageGrain;
> +    target_ulong CP0_EBase_rw_bitmask;
>      int insn_flags;
>      enum mips_mmu_types mmu_type;
>  };
> 


Regards,
Yongbok




reply via email to

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