From e117f52636d04502fab28bd3abe93347c29f39a5 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Tue, 14 Apr 2015 10:09:38 +0100 Subject: [PATCH] target-mips: add CP0.PageGrain.ELPA support 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 assume 32-bit Address Mode. In MIPS64 assume 36 as default PABITS (when CP0.PageGrain.ELPA = 0). 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 Reviewed-by: Aurelien Jarno --- target-mips/cpu.h | 27 +++++++++++++++++++++++++-- target-mips/machine.c | 1 + target-mips/mips-defs.h | 4 ++-- target-mips/op_helper.c | 19 ++++++++++++------- target-mips/translate.c | 3 ++- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 4b81798a18..c266e9ff71 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 PABITS_BASE 36 +#else +# define PABITS_BASE 32 +#endif target_ulong SEGMask; uint64_t PAMask; +#define PAMASK_BASE ((1ULL << PABITS_BASE) - 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; @@ -518,7 +525,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 @@ -566,6 +573,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) */ @@ -801,6 +809,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 = PAMASK_BASE; + } +} + static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { @@ -848,7 +865,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)) { @@ -934,6 +952,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 559402ccc2..8fa755cd39 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 1784227494..20aa87c24c 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 #define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 31bafcf954..2a9ddff70f 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1068,19 +1068,23 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1) env->CP0_VPEOpt = arg1 & 0x0000ffff; } +#define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF) + 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 & MTC0_ENTRYLO_MASK(env)) + | (rxi << (CP0EnLo_XI - 30)); } #if defined(TARGET_MIPS64) +#define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6) + 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 & DMTC0_ENTRYLO_MASK(env)) | rxi; } #endif @@ -1246,17 +1250,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 & 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 & DMTC0_ENTRYLO_MASK(env)) | rxi; } #endif @@ -1279,10 +1283,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 f722e95b0c..6a39ef0e5a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -5699,6 +5699,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; @@ -19578,7 +19579,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; @@ -19699,6 +19699,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; } -- GitLab