diff options
Diffstat (limited to 'target/ppc')
-rw-r--r-- | target/ppc/cpu-models.c | 6 | ||||
-rw-r--r-- | target/ppc/cpu-models.h | 1 | ||||
-rw-r--r-- | target/ppc/cpu-qom.h | 1 | ||||
-rw-r--r-- | target/ppc/cpu.h | 1 | ||||
-rw-r--r-- | target/ppc/int_helper.c | 16 | ||||
-rw-r--r-- | target/ppc/kvm.c | 22 | ||||
-rw-r--r-- | target/ppc/translate.c | 12 | ||||
-rw-r--r-- | target/ppc/translate_init.c | 286 |
8 files changed, 97 insertions, 248 deletions
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 9d45702843..6c9bfde2d2 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -756,8 +756,10 @@ POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970, "PowerPC 970 v2.2") - POWERPC_DEF("power9_v1.0", CPU_POWERPC_POWER9_BASE, POWER9, + POWERPC_DEF("power9_v1.0", CPU_POWERPC_POWER9_DD1, POWER9, "POWER9 v1.0") + POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9, + "POWER9 v2.0") POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970, "PowerPC 970FX v1.0 (G5)") @@ -945,7 +947,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "power8e", "power8e_v2.1" }, { "power8", "power8_v2.0" }, { "power8nvl", "power8nvl_v1.0" }, - { "power9", "power9_v1.0" }, + { "power9", "power9_v2.0" }, { "970", "970_v2.2" }, { "970fx", "970fx_v3.1" }, { "970mp", "970mp_v1.1" }, diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index 25ef372d4c..efdb2fa53c 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -372,6 +372,7 @@ enum { CPU_POWERPC_POWER8NVL_v10 = 0x004C0100, CPU_POWERPC_POWER9_BASE = 0x004E0000, CPU_POWERPC_POWER9_DD1 = 0x004E0100, + CPU_POWERPC_POWER9_DD20 = 0x004E1200, CPU_POWERPC_970_v22 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index d0cf6ca2a9..429b47f959 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -181,6 +181,7 @@ typedef struct PowerPCCPUClass { DeviceRealize parent_realize; DeviceUnrealize parent_unrealize; void (*parent_reset)(CPUState *cpu); + void (*parent_parse_features)(const char *type, char *str, Error **errp); uint32_t pvr; bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr); diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 64aef17f6f..989761b795 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1278,7 +1278,6 @@ extern const struct VMStateDescription vmstate_ppc_cpu; /*****************************************************************************/ void ppc_translate_init(void); -const char *ppc_cpu_lookup_alias(const char *alias); /* you can call this signal handler from your SIGBUS and SIGSEGV signal handlers to inform the virtual CPU of exceptions. non zero is returned if the signal was handled by the virtual CPU. */ diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index da4e1a62c9..1c013a0ee3 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -219,17 +219,17 @@ target_ulong helper_sraw(CPUPPCState *env, target_ulong value, shift &= 0x1f; ret = (int32_t)value >> shift; if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) { - env->ca = 0; + env->ca32 = env->ca = 0; } else { - env->ca = 1; + env->ca32 = env->ca = 1; } } else { ret = (int32_t)value; - env->ca = 0; + env->ca32 = env->ca = 0; } } else { ret = (int32_t)value >> 31; - env->ca = (ret != 0); + env->ca32 = env->ca = (ret != 0); } return (target_long)ret; } @@ -245,17 +245,17 @@ target_ulong helper_srad(CPUPPCState *env, target_ulong value, shift &= 0x3f; ret = (int64_t)value >> shift; if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) { - env->ca = 0; + env->ca32 = env->ca = 0; } else { - env->ca = 1; + env->ca32 = env->ca = 1; } } else { ret = (int64_t)value; - env->ca = 0; + env->ca32 = env->ca = 0; } } else { ret = (int64_t)value >> 63; - env->ca = (ret != 0); + env->ca32 = env->ca = (ret != 0); } return ret; } diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 171d3d8040..9d57debf0e 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -123,7 +123,7 @@ static bool kvmppc_is_pr(KVMState *ks) return kvm_vm_check_extension(ks, KVM_CAP_PPC_GET_PVINFO) != 0; } -static int kvm_ppc_register_host_cpu_type(void); +static int kvm_ppc_register_host_cpu_type(MachineState *ms); int kvm_arch_init(MachineState *ms, KVMState *s) { @@ -163,7 +163,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) "VM to stall at times!\n"); } - kvm_ppc_register_host_cpu_type(); + kvm_ppc_register_host_cpu_type(ms); return 0; } @@ -2487,12 +2487,13 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void) return pvr_pcc; } -static int kvm_ppc_register_host_cpu_type(void) +static int kvm_ppc_register_host_cpu_type(MachineState *ms) { TypeInfo type_info = { .name = TYPE_HOST_POWERPC_CPU, .class_init = kvmppc_host_cpu_class_init, }; + MachineClass *mc = MACHINE_GET_CLASS(ms); PowerPCCPUClass *pvr_pcc; ObjectClass *oc; DeviceClass *dc; @@ -2504,21 +2505,14 @@ static int kvm_ppc_register_host_cpu_type(void) } type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_register(&type_info); + if (object_dynamic_cast(OBJECT(ms), TYPE_SPAPR_MACHINE)) { + /* override TCG default cpu type with 'host' cpu model */ + mc->default_cpu_type = TYPE_HOST_POWERPC_CPU; + } oc = object_class_by_name(type_info.name); g_assert(oc); -#if defined(TARGET_PPC64) - type_info.name = g_strdup_printf("%s-"TYPE_SPAPR_CPU_CORE, "host"); - type_info.parent = TYPE_SPAPR_CPU_CORE, - type_info.instance_size = sizeof(sPAPRCPUCore); - type_info.instance_init = NULL; - type_info.class_init = spapr_cpu_core_class_init; - type_info.class_data = (void *) "host"; - type_register(&type_info); - g_free((void *)type_info.name); -#endif - /* * Update generic CPU family class alias (e.g. on a POWER8NVL host, * we want "POWER8" to be a "family" alias that points to the current diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 606b605ba0..a81ff69d75 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -2181,6 +2181,9 @@ static void gen_srawi(DisasContext *ctx) if (sh == 0) { tcg_gen_ext32s_tl(dst, src); tcg_gen_movi_tl(cpu_ca, 0); + if (is_isa300(ctx)) { + tcg_gen_movi_tl(cpu_ca32, 0); + } } else { TCGv t0; tcg_gen_ext32s_tl(dst, src); @@ -2190,6 +2193,9 @@ static void gen_srawi(DisasContext *ctx) tcg_gen_and_tl(cpu_ca, cpu_ca, t0); tcg_temp_free(t0); tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); + if (is_isa300(ctx)) { + tcg_gen_mov_tl(cpu_ca32, cpu_ca); + } tcg_gen_sari_tl(dst, dst, sh); } if (unlikely(Rc(ctx->opcode) != 0)) { @@ -2259,6 +2265,9 @@ static inline void gen_sradi(DisasContext *ctx, int n) if (sh == 0) { tcg_gen_mov_tl(dst, src); tcg_gen_movi_tl(cpu_ca, 0); + if (is_isa300(ctx)) { + tcg_gen_movi_tl(cpu_ca32, 0); + } } else { TCGv t0; tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1); @@ -2267,6 +2276,9 @@ static inline void gen_sradi(DisasContext *ctx, int n) tcg_gen_and_tl(cpu_ca, cpu_ca, t0); tcg_temp_free(t0); tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0); + if (is_isa300(ctx)) { + tcg_gen_mov_tl(cpu_ca32, cpu_ca); + } tcg_gen_sari_tl(dst, src, sh); } if (unlikely(Rc(ctx->opcode) != 0)) { diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index c6399a3a0d..7b9bf6a773 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -4176,223 +4176,6 @@ POWERPC_FAMILY(440x5wDFPU)(ObjectClass *oc, void *data) POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; } -static void init_proc_460 (CPUPPCState *env) -{ - /* Time base */ - gen_tbl(env); - gen_spr_BookE(env, 0x000000000000FFFFULL); - gen_spr_440(env); - gen_spr_usprgh(env); - /* Processor identification */ - spr_register(env, SPR_BOOKE_PIR, "PIR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_pir, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_IAC3, "IAC3", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_IAC4, "IAC4", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_DVC1, "DVC1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_DVC2, "DVC2", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_MCSR, "MCSR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_440_CCR1, "CCR1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_DCRIPR, "SPR_DCRIPR", - &spr_read_generic, &spr_write_generic, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* Memory management */ -#if !defined(CONFIG_USER_ONLY) - env->nb_tlb = 64; - env->nb_ways = 1; - env->id_tlbs = 0; - env->tlb_type = TLB_EMB; -#endif - init_excp_BookE(env); - env->dcache_line_size = 32; - env->icache_line_size = 32; - /* XXX: TODO: allocate internal IRQ controller */ - - SET_FIT_PERIOD(12, 16, 20, 24); - SET_WDT_PERIOD(20, 24, 28, 32); -} - -POWERPC_FAMILY(460)(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); - - dc->desc = "PowerPC 460 (guessed)"; - pcc->init_proc = init_proc_460; - pcc->check_pow = check_pow_nocheck; - pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | - PPC_DCR | PPC_DCRX | PPC_DCRUX | - PPC_WRTEE | PPC_MFAPIDI | PPC_MFTB | - PPC_CACHE | PPC_CACHE_ICBI | - PPC_CACHE_DCBZ | PPC_CACHE_DCBA | - PPC_MEM_TLBSYNC | PPC_TLBIVA | - PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | - PPC_440_SPEC; - pcc->msr_mask = (1ull << MSR_POW) | - (1ull << MSR_CE) | - (1ull << MSR_EE) | - (1ull << MSR_PR) | - (1ull << MSR_FP) | - (1ull << MSR_ME) | - (1ull << MSR_FE0) | - (1ull << MSR_DWE) | - (1ull << MSR_DE) | - (1ull << MSR_FE1) | - (1ull << MSR_IR) | - (1ull << MSR_DR); - pcc->mmu_model = POWERPC_MMU_BOOKE; - pcc->excp_model = POWERPC_EXCP_BOOKE; - pcc->bus_model = PPC_FLAGS_INPUT_BookE; - pcc->bfd_mach = bfd_mach_ppc_403; - pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE | - POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; -} - -static void init_proc_460F(CPUPPCState *env) -{ - /* Time base */ - gen_tbl(env); - gen_spr_BookE(env, 0x000000000000FFFFULL); - gen_spr_440(env); - gen_spr_usprgh(env); - /* Processor identification */ - spr_register(env, SPR_BOOKE_PIR, "PIR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_pir, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_IAC3, "IAC3", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_IAC4, "IAC4", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_DVC1, "DVC1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_DVC2, "DVC2", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_BOOKE_MCSR, "MCSR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_440_CCR1, "CCR1", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* XXX : not implemented */ - spr_register(env, SPR_DCRIPR, "SPR_DCRIPR", - &spr_read_generic, &spr_write_generic, - &spr_read_generic, &spr_write_generic, - 0x00000000); - /* Memory management */ -#if !defined(CONFIG_USER_ONLY) - env->nb_tlb = 64; - env->nb_ways = 1; - env->id_tlbs = 0; - env->tlb_type = TLB_EMB; -#endif - init_excp_BookE(env); - env->dcache_line_size = 32; - env->icache_line_size = 32; - /* XXX: TODO: allocate internal IRQ controller */ - - SET_FIT_PERIOD(12, 16, 20, 24); - SET_WDT_PERIOD(20, 24, 28, 32); -} - -POWERPC_FAMILY(460F)(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); - - dc->desc = "PowerPC 460F (guessed)"; - pcc->init_proc = init_proc_460F; - pcc->check_pow = check_pow_nocheck; - pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | - PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL | - PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | - PPC_FLOAT_STFIWX | PPC_MFTB | - PPC_DCR | PPC_DCRX | PPC_DCRUX | - PPC_WRTEE | PPC_MFAPIDI | - PPC_CACHE | PPC_CACHE_ICBI | - PPC_CACHE_DCBZ | PPC_CACHE_DCBA | - PPC_MEM_TLBSYNC | PPC_TLBIVA | - PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | - PPC_440_SPEC; - pcc->msr_mask = (1ull << MSR_POW) | - (1ull << MSR_CE) | - (1ull << MSR_EE) | - (1ull << MSR_PR) | - (1ull << MSR_FP) | - (1ull << MSR_ME) | - (1ull << MSR_FE0) | - (1ull << MSR_DWE) | - (1ull << MSR_DE) | - (1ull << MSR_FE1) | - (1ull << MSR_IR) | - (1ull << MSR_DR); - pcc->mmu_model = POWERPC_MMU_BOOKE; - pcc->excp_model = POWERPC_EXCP_BOOKE; - pcc->bus_model = PPC_FLAGS_INPUT_BookE; - pcc->bfd_mach = bfd_mach_ppc_403; - pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE | - POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; -} - static void init_proc_MPC5xx(CPUPPCState *env) { /* Time base */ @@ -10277,6 +10060,19 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr) return pcc; } +static const char *ppc_cpu_lookup_alias(const char *alias) +{ + int ai; + + for (ai = 0; ppc_cpu_aliases[ai].alias != NULL; ai++) { + if (strcmp(ppc_cpu_aliases[ai].alias, alias) == 0) { + return ppc_cpu_aliases[ai].model; + } + } + + return NULL; +} + static ObjectClass *ppc_cpu_class_by_name(const char *name) { char *cpu_model, *typename; @@ -10314,17 +10110,59 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name) return NULL; } -const char *ppc_cpu_lookup_alias(const char *alias) +static void ppc_cpu_parse_featurestr(const char *type, char *features, + Error **errp) { - int ai; + Object *machine = qdev_get_machine(); + const PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(object_class_by_name(type)); - for (ai = 0; ppc_cpu_aliases[ai].alias != NULL; ai++) { - if (strcmp(ppc_cpu_aliases[ai].alias, alias) == 0) { - return ppc_cpu_aliases[ai].model; + if (!features) { + return; + } + + if (object_property_find(machine, "max-cpu-compat", NULL)) { + int i; + char **inpieces; + char *s = features; + Error *local_err = NULL; + char *compat_str = NULL; + + /* + * Backwards compatibility hack: + * + * CPUs had a "compat=" property which didn't make sense for + * anything except pseries. It was replaced by "max-cpu-compat" + * machine option. This supports old command lines like + * -cpu POWER8,compat=power7 + * By stripping the compat option and applying it to the machine + * before passing it on to the cpu level parser. + */ + inpieces = g_strsplit(features, ",", 0); + *s = '\0'; + for (i = 0; inpieces[i]; i++) { + if (g_str_has_prefix(inpieces[i], "compat=")) { + compat_str = inpieces[i]; + continue; + } + if ((i != 0) && (s != features)) { + s = g_stpcpy(s, ","); + } + s = g_stpcpy(s, inpieces[i]); + } + + if (compat_str) { + char *v = compat_str + strlen("compat="); + object_property_set_str(machine, v, "max-cpu-compat", &local_err); + } + g_strfreev(inpieces); + if (local_err) { + error_propagate(errp, local_err); + return; } } - return NULL; + /* do property processing with generic handler */ + pcc->parent_parse_features(type, features, errp); } PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) @@ -10706,6 +10544,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) cc->reset = ppc_cpu_reset; cc->class_by_name = ppc_cpu_class_by_name; + pcc->parent_parse_features = cc->parse_features; + cc->parse_features = ppc_cpu_parse_featurestr; cc->has_work = ppc_cpu_has_work; cc->do_interrupt = ppc_cpu_do_interrupt; cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt; |