[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;
> }
>
>
signature.asc
Description: OpenPGP digital signature
[Qemu-devel] [PATCH 7/7] target-mips: enable XPA and LPA features, Leon Alrae, 2015/04/28
[Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c, Leon Alrae, 2015/04/28