Message ID | 1340223111-13449-9-git-send-email-agraf@suse.de |
---|---|
State | New |
Headers | show |
On 06/20/2012 03:11 PM, Alexander Graf wrote: > + /* XXX better abstract into Emb.xxx features */ > + if (version == fsl_e5500) { > + spr_register(env, SPR_BOOKE_EPCR, "EPCR", > + SPR_NOACCESS, SPR_NOACCESS, > + &spr_read_generic, &spr_write_generic, > + 0x00000000); > + spr_register(env, SPR_BOOKE_MAS7_MAS3, "MAS7_MAS3", > + SPR_NOACCESS, SPR_NOACCESS, > + &spr_read_mas73, &spr_write_mas73, > + 0x00000000); > + env->reset_msr = (1ULL < MSR_CM); That's a funny way of writing "env->reset_msr = 0". :-) Assuming you really meant "env->reset_msr = 1ULL << MSR_CM", why? We enter the kernel in 32-bit mode. It resets in 32-bit mode as well, if we ever implement that for e5500 QEMU. You have the same issue in the previous patch with "1ULL < MSR_SF", though I don't know if those chips actually do reset into 64-bit mode. > + } > > #if !defined(CONFIG_USER_ONLY) > env->nb_tlb = 0; > @@ -4576,6 +4655,14 @@ static void init_proc_e500 (CPUPPCState *env, int version) > #endif > > init_excp_e200(env); > + > +#if !defined(CONFIG_USER_ONLY) > + /* We support 64bit wide IVPR on 64bit platforms */ > + if (version == fsl_e5500) { > + env->ivpr_mask = (target_ulong)~0xFFFFULL; > + } > +#endif So, I'm guessing you don't do this unconditionally because QEMU will generate 64-bit code if compiled that way, regardless of the actual target -- and you don't want stray garbage in the upper 32 bits being written into IVPR. But why isn't this an issue with all the other SPRs? Why don't we have a problem with junk being written into the upper half of MAS3, for example (there's MAS3_RPN_MASK, but it's not used)? Speaking of which, I don't see where you change MAS2_EPN_MASK to take MSR_CM into account (or to accept 64-bit MAS2 at all). -Scott
On 21.06.2012, at 00:26, Scott Wood wrote: > On 06/20/2012 03:11 PM, Alexander Graf wrote: >> + /* XXX better abstract into Emb.xxx features */ >> + if (version == fsl_e5500) { >> + spr_register(env, SPR_BOOKE_EPCR, "EPCR", >> + SPR_NOACCESS, SPR_NOACCESS, >> + &spr_read_generic, &spr_write_generic, >> + 0x00000000); >> + spr_register(env, SPR_BOOKE_MAS7_MAS3, "MAS7_MAS3", >> + SPR_NOACCESS, SPR_NOACCESS, >> + &spr_read_mas73, &spr_write_mas73, >> + 0x00000000); >> + env->reset_msr = (1ULL < MSR_CM); > > That's a funny way of writing "env->reset_msr = 0". :-) > > Assuming you really meant "env->reset_msr = 1ULL << MSR_CM", why? We > enter the kernel in 32-bit mode. It resets in 32-bit mode as well, if > we ever implement that for e5500 QEMU. Hrm. At least my self-compiled kernel did issue an "ld" instruction before going into MSR_CM mode, hence I figured we need it. > You have the same issue in the previous patch with "1ULL < MSR_SF", > though I don't know if those chips actually do reset into 64-bit mode. They do :). > >> + } >> >> #if !defined(CONFIG_USER_ONLY) >> env->nb_tlb = 0; >> @@ -4576,6 +4655,14 @@ static void init_proc_e500 (CPUPPCState *env, int version) >> #endif >> >> init_excp_e200(env); >> + >> +#if !defined(CONFIG_USER_ONLY) >> + /* We support 64bit wide IVPR on 64bit platforms */ >> + if (version == fsl_e5500) { >> + env->ivpr_mask = (target_ulong)~0xFFFFULL; >> + } >> +#endif > > So, I'm guessing you don't do this unconditionally because QEMU will > generate 64-bit code if compiled that way, regardless of the actual > target -- and you don't want stray garbage in the upper 32 bits being > written into IVPR. But why isn't this an issue with all the other SPRs? > Why don't we have a problem with junk being written into the upper half > of MAS3, for example (there's MAS3_RPN_MASK, but it's not used)? I was thinking of making it unconditional, but this way seemed cleaner to me, as it actually follows exactly what the spec says. Not sure what would happen if you have -1 in your 32-bit register value and you try to write that to IVPR otherwise. It'd probably break :). > Speaking of which, I don't see where you change MAS2_EPN_MASK to take > MSR_CM into account (or to accept 64-bit MAS2 at all). Ugh. Good question why this works at all. Do we by accident truncate everything to 32bit? Alex
On 06/20/2012 05:59 PM, Alexander Graf wrote: > > On 21.06.2012, at 00:26, Scott Wood wrote: > >> On 06/20/2012 03:11 PM, Alexander Graf wrote: >>> + /* XXX better abstract into Emb.xxx features */ >>> + if (version == fsl_e5500) { >>> + spr_register(env, SPR_BOOKE_EPCR, "EPCR", >>> + SPR_NOACCESS, SPR_NOACCESS, >>> + &spr_read_generic, &spr_write_generic, >>> + 0x00000000); >>> + spr_register(env, SPR_BOOKE_MAS7_MAS3, "MAS7_MAS3", >>> + SPR_NOACCESS, SPR_NOACCESS, >>> + &spr_read_mas73, &spr_write_mas73, >>> + 0x00000000); >>> + env->reset_msr = (1ULL < MSR_CM); >> >> That's a funny way of writing "env->reset_msr = 0". :-) >> >> Assuming you really meant "env->reset_msr = 1ULL << MSR_CM", why? We >> enter the kernel in 32-bit mode. It resets in 32-bit mode as well, if >> we ever implement that for e5500 QEMU. > > Hrm. At least my self-compiled kernel did issue an "ld" instruction before going into MSR_CM mode, hence I figured we need it. You don't need MSR_CM to run 64-bit instructions. It just affects masking in certain places. >>> + } >>> >>> #if !defined(CONFIG_USER_ONLY) >>> env->nb_tlb = 0; >>> @@ -4576,6 +4655,14 @@ static void init_proc_e500 (CPUPPCState *env, int version) >>> #endif >>> >>> init_excp_e200(env); >>> + >>> +#if !defined(CONFIG_USER_ONLY) >>> + /* We support 64bit wide IVPR on 64bit platforms */ >>> + if (version == fsl_e5500) { >>> + env->ivpr_mask = (target_ulong)~0xFFFFULL; >>> + } >>> +#endif >> >> So, I'm guessing you don't do this unconditionally because QEMU will >> generate 64-bit code if compiled that way, regardless of the actual >> target -- and you don't want stray garbage in the upper 32 bits being >> written into IVPR. But why isn't this an issue with all the other SPRs? >> Why don't we have a problem with junk being written into the upper half >> of MAS3, for example (there's MAS3_RPN_MASK, but it's not used)? > > I was thinking of making it unconditional, but this way seemed > cleaner to me, as it actually follows exactly what the spec says. Not > sure what would happen if you have -1 in your 32-bit register value > and you try to write that to IVPR otherwise. It'd probably break :). It would only break because there doesn't seem to be any generic way of treating 32-bit SPRs as 32-bit. We should probably have a separate spr_write_generic32(). For a register like IVPR we'd select 32 or full-size at init time, based on the type of CPU we're modelling. For something like MAS3 we'd always use the 32-bit version. -Scott
On 21.06.2012, at 01:07, Scott Wood wrote: > On 06/20/2012 05:59 PM, Alexander Graf wrote: >> >> On 21.06.2012, at 00:26, Scott Wood wrote: >> >>> On 06/20/2012 03:11 PM, Alexander Graf wrote: >>>> + /* XXX better abstract into Emb.xxx features */ >>>> + if (version == fsl_e5500) { >>>> + spr_register(env, SPR_BOOKE_EPCR, "EPCR", >>>> + SPR_NOACCESS, SPR_NOACCESS, >>>> + &spr_read_generic, &spr_write_generic, >>>> + 0x00000000); >>>> + spr_register(env, SPR_BOOKE_MAS7_MAS3, "MAS7_MAS3", >>>> + SPR_NOACCESS, SPR_NOACCESS, >>>> + &spr_read_mas73, &spr_write_mas73, >>>> + 0x00000000); >>>> + env->reset_msr = (1ULL < MSR_CM); >>> >>> That's a funny way of writing "env->reset_msr = 0". :-) >>> >>> Assuming you really meant "env->reset_msr = 1ULL << MSR_CM", why? We >>> enter the kernel in 32-bit mode. It resets in 32-bit mode as well, if >>> we ever implement that for e5500 QEMU. >> >> Hrm. At least my self-compiled kernel did issue an "ld" instruction before going into MSR_CM mode, hence I figured we need it. > > You don't need MSR_CM to run 64-bit instructions. It just affects > masking in certain places. Wait - you don't? Is there a comprehensive description on what MSR_CM really does and does not? > >>>> + } >>>> >>>> #if !defined(CONFIG_USER_ONLY) >>>> env->nb_tlb = 0; >>>> @@ -4576,6 +4655,14 @@ static void init_proc_e500 (CPUPPCState *env, int version) >>>> #endif >>>> >>>> init_excp_e200(env); >>>> + >>>> +#if !defined(CONFIG_USER_ONLY) >>>> + /* We support 64bit wide IVPR on 64bit platforms */ >>>> + if (version == fsl_e5500) { >>>> + env->ivpr_mask = (target_ulong)~0xFFFFULL; >>>> + } >>>> +#endif >>> >>> So, I'm guessing you don't do this unconditionally because QEMU will >>> generate 64-bit code if compiled that way, regardless of the actual >>> target -- and you don't want stray garbage in the upper 32 bits being >>> written into IVPR. But why isn't this an issue with all the other SPRs? >>> Why don't we have a problem with junk being written into the upper half >>> of MAS3, for example (there's MAS3_RPN_MASK, but it's not used)? >> >> I was thinking of making it unconditional, but this way seemed >> cleaner to me, as it actually follows exactly what the spec says. Not >> sure what would happen if you have -1 in your 32-bit register value >> and you try to write that to IVPR otherwise. It'd probably break :). > > It would only break because there doesn't seem to be any generic way of > treating 32-bit SPRs as 32-bit. We should probably have a separate > spr_write_generic32(). For a register like IVPR we'd select 32 or > full-size at init time, based on the type of CPU we're modelling. For > something like MAS3 we'd always use the 32-bit version. Yup, that should work :) Alex
On 06/20/2012 06:10 PM, Alexander Graf wrote: > > On 21.06.2012, at 01:07, Scott Wood wrote: > >> On 06/20/2012 05:59 PM, Alexander Graf wrote: >>> >>> On 21.06.2012, at 00:26, Scott Wood wrote: >>> >>>> On 06/20/2012 03:11 PM, Alexander Graf wrote: >>>>> + /* XXX better abstract into Emb.xxx features */ >>>>> + if (version == fsl_e5500) { >>>>> + spr_register(env, SPR_BOOKE_EPCR, "EPCR", >>>>> + SPR_NOACCESS, SPR_NOACCESS, >>>>> + &spr_read_generic, &spr_write_generic, >>>>> + 0x00000000); >>>>> + spr_register(env, SPR_BOOKE_MAS7_MAS3, "MAS7_MAS3", >>>>> + SPR_NOACCESS, SPR_NOACCESS, >>>>> + &spr_read_mas73, &spr_write_mas73, >>>>> + 0x00000000); >>>>> + env->reset_msr = (1ULL < MSR_CM); >>>> >>>> That's a funny way of writing "env->reset_msr = 0". :-) >>>> >>>> Assuming you really meant "env->reset_msr = 1ULL << MSR_CM", why? We >>>> enter the kernel in 32-bit mode. It resets in 32-bit mode as well, if >>>> we ever implement that for e5500 QEMU. >>> >>> Hrm. At least my self-compiled kernel did issue an "ld" instruction before going into MSR_CM mode, hence I figured we need it. >> >> You don't need MSR_CM to run 64-bit instructions. It just affects >> masking in certain places. > > Wait - you don't? Is there a comprehensive description on what MSR_CM really does and does not? Not that I know of -- you need to search the ISA for places that mention MSR[CM] or 64-bit mode. -Scott
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index efa05fc..63452cc 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -4424,16 +4424,69 @@ static void init_proc_e300 (CPUPPCState *env) #define check_pow_e500mc check_pow_none #define init_proc_e500mc init_proc_e500mc +/* e5500 core */ +#define POWERPC_INSNS_e5500 (PPC_INSNS_BASE | PPC_ISEL | \ + PPC_WRTEE | PPC_RFDI | PPC_RFMCI | \ + PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \ + PPC_CACHE_DCBZ | PPC_CACHE_DCBA | \ + PPC_FLOAT | PPC_FLOAT_FRES | \ + PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL | \ + PPC_FLOAT_STFIWX | PPC_WAIT | \ + PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC | \ + PPC_64B | PPC_POPCNTB | PPC_POPCNTWD) +#define POWERPC_INSNS2_e5500 (PPC2_BOOKE206 | PPC2_PRCNTL) +#define POWERPC_MSRM_e5500 (0x000000009402FB36ULL) +#define POWERPC_MMU_e5500 (POWERPC_MMU_BOOKE206) +#define POWERPC_EXCP_e5500 (POWERPC_EXCP_BOOKE) +#define POWERPC_INPUT_e5500 (PPC_FLAGS_INPUT_BookE) +/* Fixme: figure out the correct flag for e5500 */ +#define POWERPC_BFDM_e5500 (bfd_mach_ppc_e500) +#define POWERPC_FLAG_e5500 (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \ + POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK) +#define check_pow_e5500 check_pow_none +#define init_proc_e5500 init_proc_e5500 + +#if !defined(CONFIG_USER_ONLY) +static void spr_write_mas73(void *opaque, int sprn, int gprn) +{ + TCGv val = tcg_temp_new(); + tcg_gen_ext32u_tl(val, cpu_gpr[gprn]); + gen_store_spr(SPR_BOOKE_MAS3, val); + tcg_gen_shri_tl(val, gprn, 32); + gen_store_spr(SPR_BOOKE_MAS7, val); + tcg_temp_free(val); +} + +static void spr_read_mas73(void *opaque, int gprn, int sprn) +{ + TCGv mas7 = tcg_temp_new(); + TCGv mas3 = tcg_temp_new(); + gen_load_spr(mas7, SPR_BOOKE_MAS7); + tcg_gen_shli_tl(mas7, mas7, 32); + gen_load_spr(mas3, SPR_BOOKE_MAS3); + tcg_gen_or_tl(cpu_gpr[gprn], mas3, mas7); + tcg_temp_free(mas3); + tcg_temp_free(mas7); +} + +static void spr_load_epr(void *opaque, int gprn, int sprn) +{ + gen_helper_load_epr(cpu_gpr[gprn], cpu_env); +} + +#endif + enum fsl_e500_version { fsl_e500v1, fsl_e500v2, fsl_e500mc, + fsl_e5500, }; static void init_proc_e500 (CPUPPCState *env, int version) { uint32_t tlbncfg[2]; - uint64_t ivor_mask = 0x0000000F0000FFFFULL; + uint64_t ivor_mask; uint32_t l1cfg0 = 0x3800 /* 8 ways */ | 0x0020; /* 32 kb */ #if !defined(CONFIG_USER_ONLY) @@ -4447,8 +4500,16 @@ static void init_proc_e500 (CPUPPCState *env, int version) * complain when accessing them. * gen_spr_BookE(env, 0x0000000F0000FD7FULL); */ - if (version == fsl_e500mc) { - ivor_mask = 0x000003FE0000FFFFULL; + switch (version) { + case fsl_e500v1: + case fsl_e500v2: + default: + ivor_mask = 0x0000000F0000FFFFULL; + break; + case fsl_e500mc: + case fsl_e5500: + ivor_mask = 0x000003FE0000FFFFULL; + break; } gen_spr_BookE(env, ivor_mask); /* Processor identification */ @@ -4476,6 +4537,7 @@ static void init_proc_e500 (CPUPPCState *env, int version) tlbncfg[1] = gen_tlbncfg(16, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 16); break; case fsl_e500mc: + case fsl_e5500: tlbncfg[0] = gen_tlbncfg(4, 1, 1, 0, 512); tlbncfg[1] = gen_tlbncfg(64, 1, 12, TLBnCFG_AVAIL | TLBnCFG_IPROT, 64); break; @@ -4491,6 +4553,7 @@ static void init_proc_e500 (CPUPPCState *env, int version) env->icache_line_size = 32; break; case fsl_e500mc: + case fsl_e5500: env->dcache_line_size = 64; env->icache_line_size = 64; l1cfg0 |= 0x1000000; /* 64 byte cache block size */ @@ -4566,6 +4629,22 @@ static void init_proc_e500 (CPUPPCState *env, int version) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_booke206_mmucsr0, 0x00000000); + spr_register(env, SPR_BOOKE_EPR, "EPR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_load_epr, SPR_NOACCESS, + 0x00000000); + /* XXX better abstract into Emb.xxx features */ + if (version == fsl_e5500) { + spr_register(env, SPR_BOOKE_EPCR, "EPCR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register(env, SPR_BOOKE_MAS7_MAS3, "MAS7_MAS3", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_mas73, &spr_write_mas73, + 0x00000000); + env->reset_msr = (1ULL < MSR_CM); + } #if !defined(CONFIG_USER_ONLY) env->nb_tlb = 0; @@ -4576,6 +4655,14 @@ static void init_proc_e500 (CPUPPCState *env, int version) #endif init_excp_e200(env); + +#if !defined(CONFIG_USER_ONLY) + /* We support 64bit wide IVPR on 64bit platforms */ + if (version == fsl_e5500) { + env->ivpr_mask = (target_ulong)~0xFFFFULL; + } +#endif + /* Allocate hardware IRQ controller */ ppce500_irq_init(env); } @@ -4595,6 +4682,13 @@ static void init_proc_e500mc(CPUPPCState *env) init_proc_e500(env, fsl_e500mc); } +#ifdef TARGET_PPC64 +static void init_proc_e5500(CPUPPCState *env) +{ + init_proc_e500(env, fsl_e5500); +} +#endif + /* Non-embedded PowerPC */ /* POWER : same as 601, without mfmsr, mfsr */ @@ -7139,6 +7233,7 @@ enum { CPU_POWERPC_e500v2_v22 = 0x80210022, CPU_POWERPC_e500v2_v30 = 0x80210030, CPU_POWERPC_e500mc = 0x80230020, + CPU_POWERPC_e5500 = 0x80240020, /* MPC85xx microcontrollers */ #define CPU_POWERPC_MPC8533 CPU_POWERPC_MPC8533_v11 #define CPU_POWERPC_MPC8533_v10 CPU_POWERPC_e500v2_v21 @@ -8533,6 +8628,9 @@ static const ppc_def_t ppc_defs[] = { /* PowerPC e500v2 v3.0 core */ POWERPC_DEF("e500v2_v30", CPU_POWERPC_e500v2_v30, e500v2), POWERPC_DEF("e500mc", CPU_POWERPC_e500mc, e500mc), +#ifdef TARGET_PPC64 + POWERPC_DEF("e5500", CPU_POWERPC_e5500, e5500), +#endif /* PowerPC e500 microcontrollers */ /* MPC8533 */ POWERPC_DEF_SVR("MPC8533",
This patch adds e5500's CPU initialization to the TCG CPU initialization code. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate_init.c | 104 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 101 insertions(+), 3 deletions(-)