qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support


From: James Hogan
Subject: Re: [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support
Date: Tue, 28 Apr 2015 16:08:23 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0

Hi Leon,

On 28/04/15 13:41, Leon Alrae wrote:
> CP0.PageGrain.ELPA enables support for large physical addresses. This field
> is encoded as follows:
> 0: Large physical address support is disabled.
> 1: Large physical address support is enabled.
> 
> If this bit is a 1, the following changes occur to coprocessor 0 registers:
> - The PFNX field of the EntryLo0 and EntryLo1 registers is writable and
>   concatenated with the PFN field to form the full page frame number.
> - Access to optional COP0 registers with PA extension, LLAddr, TagLo is
>   defined.
> 
> P5600 can operate in 32-bit or 40-bit Physical Address Mode. Therefore if
> XPA is disabled (CP0.PageGrain.ELPA = 0) then assuming 32-bit Address Mode.
> For MIPS64 default PABITS are 36.
> 
> env->PABITS value is constant and indicates maximum PABITS available on
> a core, whereas env->PAMask is calculated from env->PABITS and is also
> affected by CP0.PageGrain.ELPA.
> 
> Signed-off-by: Leon Alrae <address@hidden>
> ---
>  target-mips/cpu.h       | 27 +++++++++++++++++++++++++--
>  target-mips/machine.c   |  1 +
>  target-mips/mips-defs.h |  4 ++--
>  target-mips/op_helper.c | 24 +++++++++++++++++-------
>  target-mips/translate.c |  3 ++-
>  5 files changed, 47 insertions(+), 12 deletions(-)
> 
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 2dfa139..bcd1e2b 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -224,8 +224,14 @@ struct CPUMIPSState {
>  
>      uint32_t SEGBITS;
>      uint32_t PABITS;
> +#if defined(TARGET_MIPS64)
> +# define DEFAULT_PABITS 36
> +#else
> +# define DEFAULT_PABITS 32
> +#endif
>      target_ulong SEGMask;
>      uint64_t PAMask;
> +#define DEFAULT_PAMASK ((1ULL << DEFAULT_PABITS) - 1)
>  
>      int32_t msair;
>  #define MSAIR_ProcID    8
> @@ -289,6 +295,7 @@ struct CPUMIPSState {
>      int32_t CP0_PageGrain;
>  #define CP0PG_RIE 31
>  #define CP0PG_XIE 30
> +#define CP0PG_ELPA 29
>  #define CP0PG_IEC 27
>      int32_t CP0_Wired;
>      int32_t CP0_SRSConf0_rw_bitmask;
> @@ -517,7 +524,7 @@ struct CPUMIPSState {
>  #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
>      uint32_t hflags;    /* CPU State */
>      /* TMASK defines different execution modes */
> -#define MIPS_HFLAG_TMASK  0x35807FF
> +#define MIPS_HFLAG_TMASK  0x75807FF
>  #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
>      /* The KSU flags must be the lowest bits in hflags. The flag order
>         must be the same as defined for CP0 Status. This allows to use
> @@ -565,6 +572,7 @@ struct CPUMIPSState {
>  #define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot                   */
>  #define MIPS_HFLAG_MSA   0x1000000
>  #define MIPS_HFLAG_FRE   0x2000000 /* FRE enabled */
> +#define MIPS_HFLAG_ELPA  0x4000000
>      target_ulong btarget;        /* Jump / branch target               */
>      target_ulong bcond;          /* Branch condition (if needed)       */
>  
> @@ -800,6 +808,15 @@ static inline void restore_msa_fp_status(CPUMIPSState 
> *env)
>      set_flush_inputs_to_zero(flush_to_zero, status);
>  }
>  
> +static inline void restore_pamask(CPUMIPSState *env)
> +{
> +    if (env->hflags & MIPS_HFLAG_ELPA) {
> +        env->PAMask = (1ULL << env->PABITS) - 1;
> +    } else {
> +        env->PAMask = DEFAULT_PAMASK;
> +    }
> +}
> +
>  static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
>                                          target_ulong *cs_base, int *flags)
>  {
> @@ -847,7 +864,8 @@ static inline void compute_hflags(CPUMIPSState *env)
>      env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
>                       MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
>                       MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
> -                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
> +                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
> +                     MIPS_HFLAG_ELPA);
>      if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
>          !(env->CP0_Status & (1 << CP0St_ERL)) &&
>          !(env->hflags & MIPS_HFLAG_DM)) {
> @@ -933,6 +951,11 @@ static inline void compute_hflags(CPUMIPSState *env)
>              env->hflags |= MIPS_HFLAG_FRE;
>          }
>      }
> +    if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
> +        if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
> +            env->hflags |= MIPS_HFLAG_ELPA;
> +        }
> +    }
>  }
>  
>  #ifndef CONFIG_USER_ONLY
> diff --git a/target-mips/machine.c b/target-mips/machine.c
> index 559402c..8fa755c 100644
> --- a/target-mips/machine.c
> +++ b/target-mips/machine.c
> @@ -10,6 +10,7 @@ static int cpu_post_load(void *opaque, int version_id)
>      restore_fp_status(env);
>      restore_msa_fp_status(env);
>      compute_hflags(env);
> +    restore_pamask(env);
>  
>      return 0;
>  }
> diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
> index 1784227..20aa87c 100644
> --- a/target-mips/mips-defs.h
> +++ b/target-mips/mips-defs.h
> @@ -10,11 +10,11 @@
>  
>  #if defined(TARGET_MIPS64)
>  #define TARGET_LONG_BITS 64
> -#define TARGET_PHYS_ADDR_SPACE_BITS 36
> +#define TARGET_PHYS_ADDR_SPACE_BITS 48
>  #define TARGET_VIRT_ADDR_SPACE_BITS 42
>  #else
>  #define TARGET_LONG_BITS 32
> -#define TARGET_PHYS_ADDR_SPACE_BITS 36
> +#define TARGET_PHYS_ADDR_SPACE_BITS 40

Out of interest, is there a particular reason not to put this up to 59,
the max supported by the architecture, rather than just what P5600 supports?

>  #define TARGET_VIRT_ADDR_SPACE_BITS 32
>  #endif
>  
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 6bff927..4b1b0ec 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1067,19 +1067,28 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, 
> target_ulong arg1)
>      env->CP0_VPEOpt = arg1 & 0x0000ffff;
>  }
>  
> +static inline target_ulong get_mtc0_entrylo_mask(const CPUMIPSState *env)
> +{
> +#if defined(TARGET_MIPS64)
> +    return env->PAMask >> 6;

I think this case is suitable for dmtc0 EntryLo regardless of MIPS64/MIPS32?

> +#else
> +    return (env->PAMask >> 6) & 0x3FFFFFFF;

mtc0 sets bits 61:30 of EntryLo to 0 on MIPS64 too, so this case is
suitable for mtc0 regardless of MIPS64/MIPS32?

Cheers
James

> +#endif
> +}
> +
>  void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
>  {
> -    /* Large physaddr (PABITS) not implemented */
>      /* 1k pages not implemented */
>      target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
> -    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
> +    env->CP0_EntryLo0 = (arg1 & get_mtc0_entrylo_mask(env))
> +                        | (rxi << (CP0EnLo_XI - 30));
>  }
>  
>  #if defined(TARGET_MIPS64)
>  void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
>  {
>      uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
> -    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
> +    env->CP0_EntryLo0 = (arg1 & get_mtc0_entrylo_mask(env)) | rxi;
>  }
>  #endif
>  
> @@ -1245,17 +1254,17 @@ void helper_mttc0_tcschefback(CPUMIPSState *env, 
> target_ulong arg1)
>  
>  void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
>  {
> -    /* Large physaddr (PABITS) not implemented */
>      /* 1k pages not implemented */
>      target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
> -    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
> +    env->CP0_EntryLo1 = (arg1 & get_mtc0_entrylo_mask(env))
> +                        | (rxi << (CP0EnLo_XI - 30));
>  }
>  
>  #if defined(TARGET_MIPS64)
>  void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
>  {
>      uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
> -    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
> +    env->CP0_EntryLo1 = (arg1 & get_mtc0_entrylo_mask(env)) | rxi;
>  }
>  #endif
>  
> @@ -1278,10 +1287,11 @@ void helper_mtc0_pagemask(CPUMIPSState *env, 
> target_ulong arg1)
>  void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
>  {
>      /* SmartMIPS not implemented */
> -    /* Large physaddr (PABITS) not implemented */
>      /* 1k pages not implemented */
>      env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
>                           (env->CP0_PageGrain & 
> ~env->CP0_PageGrain_rw_bitmask);
> +    compute_hflags(env);
> +    restore_pamask(env);
>  }
>  
>  void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 0f875be..bb219ea 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -5666,6 +5666,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int 
> reg, int sel)
>              check_insn(ctx, ISA_MIPS32R2);
>              gen_helper_mtc0_pagegrain(cpu_env, arg);
>              rn = "PageGrain";
> +            ctx->bstate = BS_STOP;
>              break;
>          default:
>              goto cp0_unimplemented;
> @@ -19526,7 +19527,6 @@ void cpu_state_reset(CPUMIPSState *env)
>      }
>  #endif
>      env->PABITS = env->cpu_model->PABITS;
> -    env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
>      env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
>      env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
>      env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
> @@ -19647,6 +19647,7 @@ void cpu_state_reset(CPUMIPSState *env)
>      compute_hflags(env);
>      restore_rounding_mode(env);
>      restore_flush_mode(env);
> +    restore_pamask(env);
>      cs->exception_index = EXCP_NONE;
>  }
>  
> 

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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