Loading target/ppc/translate_init.inc.c +148 −95 Original line number Diff line number Diff line Loading @@ -41,12 +41,13 @@ #include "fpu/softfloat.h" #include "qapi/qapi-commands-target.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR //#define PPC_DUMP_SPR_ACCESSES /* #define PPC_DUMP_CPU */ /* #define PPC_DEBUG_SPR */ /* #define PPC_DUMP_SPR_ACCESSES */ /* #define USE_APPLE_GDB */ /* Generic callbacks: /* * Generic callbacks: * do nothing but store/retrieve spr value */ static void spr_load_dump_spr(int sprn) Loading Loading @@ -230,13 +231,13 @@ static void spr_read_tbu(DisasContext *ctx, int gprn, int sprn) } } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_read_atbl(DisasContext *ctx, int gprn, int sprn) { gen_helper_load_atbl(cpu_gpr[gprn], cpu_env); } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_read_atbu(DisasContext *ctx, int gprn, int sprn) { gen_helper_load_atbu(cpu_gpr[gprn], cpu_env); Loading Loading @@ -267,20 +268,20 @@ static void spr_write_tbu(DisasContext *ctx, int sprn, int gprn) } } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_write_atbl(DisasContext *ctx, int sprn, int gprn) { gen_helper_store_atbl(cpu_env, cpu_gpr[gprn]); } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_write_atbu(DisasContext *ctx, int sprn, int gprn) { gen_helper_store_atbu(cpu_env, cpu_gpr[gprn]); } #if defined(TARGET_PPC64) __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_read_purr(DisasContext *ctx, int gprn, int sprn) { gen_helper_load_purr(cpu_gpr[gprn], cpu_env); Loading Loading @@ -319,12 +320,16 @@ static void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn) /* IBAT0L...IBAT7L */ static void spr_read_ibat(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); } static void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4])); } static void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -359,12 +364,16 @@ static void spr_write_ibatl_h(DisasContext *ctx, int sprn, int gprn) /* DBAT0L...DBAT7L */ static void spr_read_dbat(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2])); } static void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4])); } static void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -473,7 +482,9 @@ static void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn) #if !defined(CONFIG_USER_ONLY) static void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); } static void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -532,7 +543,8 @@ static void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn) #if !defined(CONFIG_USER_ONLY) static void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1])); } static void spr_write_403_pbr(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -661,14 +673,20 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val) static inline void _spr_register(CPUPPCState *env, int num, const char *name, void (*uea_read)(DisasContext *ctx, int gprn, int sprn), void (*uea_write)(DisasContext *ctx, int sprn, int gprn), void (*uea_read)(DisasContext *ctx, int gprn, int sprn), void (*uea_write)(DisasContext *ctx, int sprn, int gprn), #if !defined(CONFIG_USER_ONLY) void (*oea_read)(DisasContext *ctx, int gprn, int sprn), void (*oea_write)(DisasContext *ctx, int sprn, int gprn), void (*hea_read)(DisasContext *opaque, int gprn, int sprn), void (*hea_write)(DisasContext *opaque, int sprn, int gprn), void (*oea_read)(DisasContext *ctx, int gprn, int sprn), void (*oea_write)(DisasContext *ctx, int sprn, int gprn), void (*hea_read)(DisasContext *opaque, int gprn, int sprn), void (*hea_write)(DisasContext *opaque, int sprn, int gprn), #endif #if defined(CONFIG_KVM) uint64_t one_reg_id, Loading Loading @@ -774,8 +792,10 @@ static void gen_spr_sdr1(CPUPPCState *env) { #ifndef CONFIG_USER_ONLY if (env->has_hv_mode) { /* SDR1 is a hypervisor resource on CPUs which have a * hypervisor mode */ /* * SDR1 is a hypervisor resource on CPUs which have a * hypervisor mode */ spr_register_hv(env, SPR_SDR1, "SDR1", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, Loading Loading @@ -1123,7 +1143,8 @@ static void spr_write_amr(DisasContext *ctx, int sprn, int gprn) TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); /* Note, the HV=1 PR=0 case is handled earlier by simply using /* * Note, the HV=1 PR=0 case is handled earlier by simply using * spr_write_generic for HV mode in the SPR table */ Loading Loading @@ -1157,7 +1178,8 @@ static void spr_write_uamor(DisasContext *ctx, int sprn, int gprn) TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); /* Note, the HV=1 case is handled earlier by simply using /* * Note, the HV=1 case is handled earlier by simply using * spr_write_generic for HV mode in the SPR table */ Loading Loading @@ -1187,7 +1209,8 @@ static void spr_write_iamr(DisasContext *ctx, int sprn, int gprn) TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); /* Note, the HV=1 case is handled earlier by simply using /* * Note, the HV=1 case is handled earlier by simply using * spr_write_generic for HV mode in the SPR table */ Loading Loading @@ -1215,10 +1238,13 @@ static void spr_write_iamr(DisasContext *ctx, int sprn, int gprn) static void gen_spr_amr(CPUPPCState *env) { #ifndef CONFIG_USER_ONLY /* Virtual Page Class Key protection */ /* The AMR is accessible either via SPR 13 or SPR 29. 13 is /* * Virtual Page Class Key protection * * The AMR is accessible either via SPR 13 or SPR 29. 13 is * userspace accessible, 29 is privileged. So we only need to set * the kvm ONE_REG id on one of them, we use 29 */ * the kvm ONE_REG id on one of them, we use 29 */ spr_register(env, SPR_UAMR, "UAMR", &spr_read_generic, &spr_write_amr, &spr_read_generic, &spr_write_amr, Loading Loading @@ -1902,7 +1928,8 @@ static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask, /* TLB assist registers */ /* XXX : not implemented */ for (i = 0; i < 8; i++) { void (*uea_write)(DisasContext *ctx, int sprn, int gprn) = &spr_write_generic32; void (*uea_write)(DisasContext *ctx, int sprn, int gprn) = &spr_write_generic32; if (i == 2 && (mas_mask & (1 << i)) && (env->insns_flags & PPC_64B)) { uea_write = &spr_write_generic; } Loading Loading @@ -2798,7 +2825,6 @@ static void gen_spr_8xx(CPUPPCState *env) 0x00000000); } // XXX: TODO /* * AMR => SPR 29 (Power 2.04) * CTRL => SPR 136 (Power 2.04) Loading Loading @@ -3344,16 +3370,18 @@ static int check_pow_nocheck(CPUPPCState *env) static int check_pow_hid0(CPUPPCState *env) { if (env->spr[SPR_HID0] & 0x00E00000) if (env->spr[SPR_HID0] & 0x00E00000) { return 1; } return 0; } static int check_pow_hid0_74xx(CPUPPCState *env) { if (env->spr[SPR_HID0] & 0x00600000) if (env->spr[SPR_HID0] & 0x00600000) { return 1; } return 0; } Loading Loading @@ -4602,7 +4630,8 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data) dc->desc = "e200 core"; pcc->init_proc = init_proc_e200; pcc->check_pow = check_pow_hid0; /* XXX: unimplemented instructions: /* * XXX: unimplemented instructions: * dcblc * dcbtlst * dcbtstls Loading Loading @@ -4848,7 +4877,8 @@ static void init_proc_e500(CPUPPCState *env, int version) tlbncfg[1] = 0x40028040; break; default: cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); } #endif /* Cache sizes */ Loading @@ -4872,7 +4902,8 @@ static void init_proc_e500(CPUPPCState *env, int version) l1cfg1 |= 0x0B83820; break; default: cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); } gen_spr_BookE206(env, 0x000000DF, tlbncfg, mmucfg); /* XXX : not implemented */ Loading Loading @@ -5252,7 +5283,8 @@ static void init_proc_601(CPUPPCState *env) 0x00000000); /* Memory management */ init_excp_601(env); /* XXX: beware that dcache line size is 64 /* * XXX: beware that dcache line size is 64 * but dcbz uses 32 bytes "sectors" * XXX: this breaks clcs instruction ! */ Loading Loading @@ -5789,7 +5821,8 @@ static void init_proc_750(CPUPPCState *env) 0x00000000); /* Memory management */ gen_low_BATs(env); /* XXX: high BATs are also present but are known to be bugged on /* * XXX: high BATs are also present but are known to be bugged on * die version 1.x */ init_excp_7x0(env); Loading Loading @@ -5971,7 +6004,8 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data) dc->desc = "PowerPC 750 CL"; pcc->init_proc = init_proc_750cl; pcc->check_pow = check_pow_hid0; /* XXX: not implemented: /* * XXX: not implemented: * cache lock instructions: * dcbz_l * floating point paired instructions Loading Loading @@ -7569,8 +7603,10 @@ static void gen_spr_book3s_altivec(CPUPPCState *env) &spr_read_generic, &spr_write_generic, KVM_REG_PPC_VRSAVE, 0x00000000); /* Can't find information on what this should be on reset. This * value is the one used by 74xx processors. */ /* * Can't find information on what this should be on reset. This * value is the one used by 74xx processors. */ vscr_init(env, 0x00010000); } Loading Loading @@ -8975,8 +9011,9 @@ static void init_ppc_proc(PowerPCCPU *cpu) env->irq_inputs = NULL; /* Set all exception vectors to an invalid address */ for (i = 0; i < POWERPC_EXCP_NB; i++) for (i = 0; i < POWERPC_EXCP_NB; i++) { env->excp_vectors[i] = (target_ulong)(-1ULL); } env->ivor_mask = 0x00000000; env->ivpr_mask = 0x00000000; /* Default MMU definitions */ Loading Loading @@ -9108,8 +9145,9 @@ static void init_ppc_proc(PowerPCCPU *cpu) #if !defined(CONFIG_USER_ONLY) if (env->nb_tlb != 0) { int nb_tlb = env->nb_tlb; if (env->id_tlbs != 0) if (env->id_tlbs != 0) { nb_tlb *= 2; } switch (env->tlb_type) { case TLB_6XX: env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb); Loading Loading @@ -9201,9 +9239,10 @@ static void fill_new_table(opc_handler_t **table, int len) { int i; for (i = 0; i < len; i++) for (i = 0; i < len; i++) { table[i] = &invalid_handler; } } static int create_new_table(opc_handler_t **table, unsigned char idx) { Loading @@ -9219,8 +9258,9 @@ static int create_new_table(opc_handler_t **table, unsigned char idx) static int insert_in_table(opc_handler_t **table, unsigned char idx, opc_handler_t *handler) { if (table[idx] != &invalid_handler) if (table[idx] != &invalid_handler) { return -1; } table[idx] = handler; return 0; Loading Loading @@ -9341,18 +9381,21 @@ static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn) } } else { if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2, insn->opc3, &insn->handler) < 0) insn->opc3, &insn->handler) < 0) { return -1; } } } else { if (register_ind_insn(ppc_opcodes, insn->opc1, insn->opc2, &insn->handler) < 0) insn->opc2, &insn->handler) < 0) { return -1; } } } else { if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) { return -1; } } return 0; } Loading @@ -9363,8 +9406,9 @@ static int test_opcode_table(opc_handler_t **table, int len) for (i = 0, count = 0; i < len; i++) { /* Consistency fixup */ if (table[i] == NULL) if (table[i] == NULL) { table[i] = &invalid_handler; } if (table[i] != &invalid_handler) { if (is_indirect_opcode(table[i])) { tmp = test_opcode_table(ind_table(table[i]), Loading @@ -9386,9 +9430,10 @@ static int test_opcode_table(opc_handler_t **table, int len) static void fix_opcode_tables(opc_handler_t **ppc_opcodes) { if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) { printf("*** WARNING: no opcode defined !\n"); } } /*****************************************************************************/ static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp) Loading Loading @@ -9726,14 +9771,15 @@ static int ppc_fixup_cpu(PowerPCCPU *cpu) { CPUPPCState *env = &cpu->env; /* TCG doesn't (yet) emulate some groups of instructions that * are implemented on some otherwise supported CPUs (e.g. VSX * and decimal floating point instructions on POWER7). We * remove unsupported instruction groups from the cpu state's * instruction masks and hope the guest can cope. For at * least the pseries machine, the unavailability of these * instructions can be advertised to the guest via the device * tree. */ /* * TCG doesn't (yet) emulate some groups of instructions that are * implemented on some otherwise supported CPUs (e.g. VSX and * decimal floating point instructions on POWER7). We remove * unsupported instruction groups from the cpu state's instruction * masks and hope the guest can cope. For at least the pseries * machine, the unavailability of these instructions can be * advertised to the guest via the device tree. */ if ((env->insns_flags & ~PPC_TCG_INSNS) || (env->insns_flags2 & ~PPC_TCG_INSNS2)) { warn_report("Disabling some instructions which are not " Loading Loading @@ -9928,31 +9974,37 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp) " Bus model : %s\n", excp_model, bus_model); printf(" MSR features :\n"); if (env->flags & POWERPC_FLAG_SPE) if (env->flags & POWERPC_FLAG_SPE) { printf(" signal processing engine enable" "\n"); else if (env->flags & POWERPC_FLAG_VRE) } else if (env->flags & POWERPC_FLAG_VRE) { printf(" vector processor enable\n"); if (env->flags & POWERPC_FLAG_TGPR) } if (env->flags & POWERPC_FLAG_TGPR) { printf(" temporary GPRs\n"); else if (env->flags & POWERPC_FLAG_CE) } else if (env->flags & POWERPC_FLAG_CE) { printf(" critical input enable\n"); if (env->flags & POWERPC_FLAG_SE) } if (env->flags & POWERPC_FLAG_SE) { printf(" single-step trace mode\n"); else if (env->flags & POWERPC_FLAG_DWE) } else if (env->flags & POWERPC_FLAG_DWE) { printf(" debug wait enable\n"); else if (env->flags & POWERPC_FLAG_UBLE) } else if (env->flags & POWERPC_FLAG_UBLE) { printf(" user BTB lock enable\n"); if (env->flags & POWERPC_FLAG_BE) } if (env->flags & POWERPC_FLAG_BE) { printf(" branch-step trace mode\n"); else if (env->flags & POWERPC_FLAG_DE) } else if (env->flags & POWERPC_FLAG_DE) { printf(" debug interrupt enable\n"); if (env->flags & POWERPC_FLAG_PX) } if (env->flags & POWERPC_FLAG_PX) { printf(" inclusive protection\n"); else if (env->flags & POWERPC_FLAG_PMM) } else if (env->flags & POWERPC_FLAG_PMM) { printf(" performance monitor mark\n"); if (env->flags == POWERPC_FLAG_NONE) } if (env->flags == POWERPC_FLAG_NONE) { printf(" none\n"); } printf(" Time-base/decrementer clock source: %s\n", env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus clock"); dump_ppc_insns(env); Loading Loading @@ -10094,8 +10146,9 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name) const char *p; unsigned long pvr; /* Lookup by PVR if cpu_model is valid 8 digit hex number * (excl: 0x prefix if present) /* * Lookup by PVR if cpu_model is valid 8 digit hex number (excl: * 0x prefix if present) */ if (!qemu_strtoul(name, &p, 16, &pvr)) { int len = p - name; Loading Loading @@ -10439,14 +10492,14 @@ static void ppc_cpu_instance_init(Object *obj) env->bfd_mach = pcc->bfd_mach; env->check_pow = pcc->check_pow; /* Mark HV mode as supported if the CPU has an MSR_HV bit * in the msr_mask. The mask can later be cleared by PAPR * mode but the hv mode support will remain, thus enforcing * that we cannot use priv. instructions in guest in PAPR * mode. For 970 we currently simply don't set HV in msr_mask * thus simulating an "Apple mode" 970. If we ever want to * support 970 HV mode, we'll have to add a processor attribute * of some sort. /* * Mark HV mode as supported if the CPU has an MSR_HV bit in the * msr_mask. The mask can later be cleared by PAPR mode but the hv * mode support will remain, thus enforcing that we cannot use * priv. instructions in guest in PAPR mode. For 970 we currently * simply don't set HV in msr_mask thus simulating an "Apple mode" * 970. If we ever want to support 970 HV mode, we'll have to add * a processor attribute of some sort. */ #if !defined(CONFIG_USER_ONLY) env->has_hv_mode = !!(env->msr_mask & MSR_HVB); Loading Loading
target/ppc/translate_init.inc.c +148 −95 Original line number Diff line number Diff line Loading @@ -41,12 +41,13 @@ #include "fpu/softfloat.h" #include "qapi/qapi-commands-target.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR //#define PPC_DUMP_SPR_ACCESSES /* #define PPC_DUMP_CPU */ /* #define PPC_DEBUG_SPR */ /* #define PPC_DUMP_SPR_ACCESSES */ /* #define USE_APPLE_GDB */ /* Generic callbacks: /* * Generic callbacks: * do nothing but store/retrieve spr value */ static void spr_load_dump_spr(int sprn) Loading Loading @@ -230,13 +231,13 @@ static void spr_read_tbu(DisasContext *ctx, int gprn, int sprn) } } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_read_atbl(DisasContext *ctx, int gprn, int sprn) { gen_helper_load_atbl(cpu_gpr[gprn], cpu_env); } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_read_atbu(DisasContext *ctx, int gprn, int sprn) { gen_helper_load_atbu(cpu_gpr[gprn], cpu_env); Loading Loading @@ -267,20 +268,20 @@ static void spr_write_tbu(DisasContext *ctx, int sprn, int gprn) } } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_write_atbl(DisasContext *ctx, int sprn, int gprn) { gen_helper_store_atbl(cpu_env, cpu_gpr[gprn]); } __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_write_atbu(DisasContext *ctx, int sprn, int gprn) { gen_helper_store_atbu(cpu_env, cpu_gpr[gprn]); } #if defined(TARGET_PPC64) __attribute__ (( unused )) ATTRIBUTE_UNUSED static void spr_read_purr(DisasContext *ctx, int gprn, int sprn) { gen_helper_load_purr(cpu_gpr[gprn], cpu_env); Loading Loading @@ -319,12 +320,16 @@ static void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn) /* IBAT0L...IBAT7L */ static void spr_read_ibat(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); } static void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4])); } static void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -359,12 +364,16 @@ static void spr_write_ibatl_h(DisasContext *ctx, int sprn, int gprn) /* DBAT0L...DBAT7L */ static void spr_read_dbat(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2])); } static void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4])); } static void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -473,7 +482,9 @@ static void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn) #if !defined(CONFIG_USER_ONLY) static void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2])); } static void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -532,7 +543,8 @@ static void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn) #if !defined(CONFIG_USER_ONLY) static void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn) { tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1])); tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1])); } static void spr_write_403_pbr(DisasContext *ctx, int sprn, int gprn) Loading Loading @@ -661,14 +673,20 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val) static inline void _spr_register(CPUPPCState *env, int num, const char *name, void (*uea_read)(DisasContext *ctx, int gprn, int sprn), void (*uea_write)(DisasContext *ctx, int sprn, int gprn), void (*uea_read)(DisasContext *ctx, int gprn, int sprn), void (*uea_write)(DisasContext *ctx, int sprn, int gprn), #if !defined(CONFIG_USER_ONLY) void (*oea_read)(DisasContext *ctx, int gprn, int sprn), void (*oea_write)(DisasContext *ctx, int sprn, int gprn), void (*hea_read)(DisasContext *opaque, int gprn, int sprn), void (*hea_write)(DisasContext *opaque, int sprn, int gprn), void (*oea_read)(DisasContext *ctx, int gprn, int sprn), void (*oea_write)(DisasContext *ctx, int sprn, int gprn), void (*hea_read)(DisasContext *opaque, int gprn, int sprn), void (*hea_write)(DisasContext *opaque, int sprn, int gprn), #endif #if defined(CONFIG_KVM) uint64_t one_reg_id, Loading Loading @@ -774,8 +792,10 @@ static void gen_spr_sdr1(CPUPPCState *env) { #ifndef CONFIG_USER_ONLY if (env->has_hv_mode) { /* SDR1 is a hypervisor resource on CPUs which have a * hypervisor mode */ /* * SDR1 is a hypervisor resource on CPUs which have a * hypervisor mode */ spr_register_hv(env, SPR_SDR1, "SDR1", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, Loading Loading @@ -1123,7 +1143,8 @@ static void spr_write_amr(DisasContext *ctx, int sprn, int gprn) TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); /* Note, the HV=1 PR=0 case is handled earlier by simply using /* * Note, the HV=1 PR=0 case is handled earlier by simply using * spr_write_generic for HV mode in the SPR table */ Loading Loading @@ -1157,7 +1178,8 @@ static void spr_write_uamor(DisasContext *ctx, int sprn, int gprn) TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); /* Note, the HV=1 case is handled earlier by simply using /* * Note, the HV=1 case is handled earlier by simply using * spr_write_generic for HV mode in the SPR table */ Loading Loading @@ -1187,7 +1209,8 @@ static void spr_write_iamr(DisasContext *ctx, int sprn, int gprn) TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); /* Note, the HV=1 case is handled earlier by simply using /* * Note, the HV=1 case is handled earlier by simply using * spr_write_generic for HV mode in the SPR table */ Loading Loading @@ -1215,10 +1238,13 @@ static void spr_write_iamr(DisasContext *ctx, int sprn, int gprn) static void gen_spr_amr(CPUPPCState *env) { #ifndef CONFIG_USER_ONLY /* Virtual Page Class Key protection */ /* The AMR is accessible either via SPR 13 or SPR 29. 13 is /* * Virtual Page Class Key protection * * The AMR is accessible either via SPR 13 or SPR 29. 13 is * userspace accessible, 29 is privileged. So we only need to set * the kvm ONE_REG id on one of them, we use 29 */ * the kvm ONE_REG id on one of them, we use 29 */ spr_register(env, SPR_UAMR, "UAMR", &spr_read_generic, &spr_write_amr, &spr_read_generic, &spr_write_amr, Loading Loading @@ -1902,7 +1928,8 @@ static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask, /* TLB assist registers */ /* XXX : not implemented */ for (i = 0; i < 8; i++) { void (*uea_write)(DisasContext *ctx, int sprn, int gprn) = &spr_write_generic32; void (*uea_write)(DisasContext *ctx, int sprn, int gprn) = &spr_write_generic32; if (i == 2 && (mas_mask & (1 << i)) && (env->insns_flags & PPC_64B)) { uea_write = &spr_write_generic; } Loading Loading @@ -2798,7 +2825,6 @@ static void gen_spr_8xx(CPUPPCState *env) 0x00000000); } // XXX: TODO /* * AMR => SPR 29 (Power 2.04) * CTRL => SPR 136 (Power 2.04) Loading Loading @@ -3344,16 +3370,18 @@ static int check_pow_nocheck(CPUPPCState *env) static int check_pow_hid0(CPUPPCState *env) { if (env->spr[SPR_HID0] & 0x00E00000) if (env->spr[SPR_HID0] & 0x00E00000) { return 1; } return 0; } static int check_pow_hid0_74xx(CPUPPCState *env) { if (env->spr[SPR_HID0] & 0x00600000) if (env->spr[SPR_HID0] & 0x00600000) { return 1; } return 0; } Loading Loading @@ -4602,7 +4630,8 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data) dc->desc = "e200 core"; pcc->init_proc = init_proc_e200; pcc->check_pow = check_pow_hid0; /* XXX: unimplemented instructions: /* * XXX: unimplemented instructions: * dcblc * dcbtlst * dcbtstls Loading Loading @@ -4848,7 +4877,8 @@ static void init_proc_e500(CPUPPCState *env, int version) tlbncfg[1] = 0x40028040; break; default: cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); } #endif /* Cache sizes */ Loading @@ -4872,7 +4902,8 @@ static void init_proc_e500(CPUPPCState *env, int version) l1cfg1 |= 0x0B83820; break; default: cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); } gen_spr_BookE206(env, 0x000000DF, tlbncfg, mmucfg); /* XXX : not implemented */ Loading Loading @@ -5252,7 +5283,8 @@ static void init_proc_601(CPUPPCState *env) 0x00000000); /* Memory management */ init_excp_601(env); /* XXX: beware that dcache line size is 64 /* * XXX: beware that dcache line size is 64 * but dcbz uses 32 bytes "sectors" * XXX: this breaks clcs instruction ! */ Loading Loading @@ -5789,7 +5821,8 @@ static void init_proc_750(CPUPPCState *env) 0x00000000); /* Memory management */ gen_low_BATs(env); /* XXX: high BATs are also present but are known to be bugged on /* * XXX: high BATs are also present but are known to be bugged on * die version 1.x */ init_excp_7x0(env); Loading Loading @@ -5971,7 +6004,8 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data) dc->desc = "PowerPC 750 CL"; pcc->init_proc = init_proc_750cl; pcc->check_pow = check_pow_hid0; /* XXX: not implemented: /* * XXX: not implemented: * cache lock instructions: * dcbz_l * floating point paired instructions Loading Loading @@ -7569,8 +7603,10 @@ static void gen_spr_book3s_altivec(CPUPPCState *env) &spr_read_generic, &spr_write_generic, KVM_REG_PPC_VRSAVE, 0x00000000); /* Can't find information on what this should be on reset. This * value is the one used by 74xx processors. */ /* * Can't find information on what this should be on reset. This * value is the one used by 74xx processors. */ vscr_init(env, 0x00010000); } Loading Loading @@ -8975,8 +9011,9 @@ static void init_ppc_proc(PowerPCCPU *cpu) env->irq_inputs = NULL; /* Set all exception vectors to an invalid address */ for (i = 0; i < POWERPC_EXCP_NB; i++) for (i = 0; i < POWERPC_EXCP_NB; i++) { env->excp_vectors[i] = (target_ulong)(-1ULL); } env->ivor_mask = 0x00000000; env->ivpr_mask = 0x00000000; /* Default MMU definitions */ Loading Loading @@ -9108,8 +9145,9 @@ static void init_ppc_proc(PowerPCCPU *cpu) #if !defined(CONFIG_USER_ONLY) if (env->nb_tlb != 0) { int nb_tlb = env->nb_tlb; if (env->id_tlbs != 0) if (env->id_tlbs != 0) { nb_tlb *= 2; } switch (env->tlb_type) { case TLB_6XX: env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb); Loading Loading @@ -9201,9 +9239,10 @@ static void fill_new_table(opc_handler_t **table, int len) { int i; for (i = 0; i < len; i++) for (i = 0; i < len; i++) { table[i] = &invalid_handler; } } static int create_new_table(opc_handler_t **table, unsigned char idx) { Loading @@ -9219,8 +9258,9 @@ static int create_new_table(opc_handler_t **table, unsigned char idx) static int insert_in_table(opc_handler_t **table, unsigned char idx, opc_handler_t *handler) { if (table[idx] != &invalid_handler) if (table[idx] != &invalid_handler) { return -1; } table[idx] = handler; return 0; Loading Loading @@ -9341,18 +9381,21 @@ static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn) } } else { if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2, insn->opc3, &insn->handler) < 0) insn->opc3, &insn->handler) < 0) { return -1; } } } else { if (register_ind_insn(ppc_opcodes, insn->opc1, insn->opc2, &insn->handler) < 0) insn->opc2, &insn->handler) < 0) { return -1; } } } else { if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) { return -1; } } return 0; } Loading @@ -9363,8 +9406,9 @@ static int test_opcode_table(opc_handler_t **table, int len) for (i = 0, count = 0; i < len; i++) { /* Consistency fixup */ if (table[i] == NULL) if (table[i] == NULL) { table[i] = &invalid_handler; } if (table[i] != &invalid_handler) { if (is_indirect_opcode(table[i])) { tmp = test_opcode_table(ind_table(table[i]), Loading @@ -9386,9 +9430,10 @@ static int test_opcode_table(opc_handler_t **table, int len) static void fix_opcode_tables(opc_handler_t **ppc_opcodes) { if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) { printf("*** WARNING: no opcode defined !\n"); } } /*****************************************************************************/ static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp) Loading Loading @@ -9726,14 +9771,15 @@ static int ppc_fixup_cpu(PowerPCCPU *cpu) { CPUPPCState *env = &cpu->env; /* TCG doesn't (yet) emulate some groups of instructions that * are implemented on some otherwise supported CPUs (e.g. VSX * and decimal floating point instructions on POWER7). We * remove unsupported instruction groups from the cpu state's * instruction masks and hope the guest can cope. For at * least the pseries machine, the unavailability of these * instructions can be advertised to the guest via the device * tree. */ /* * TCG doesn't (yet) emulate some groups of instructions that are * implemented on some otherwise supported CPUs (e.g. VSX and * decimal floating point instructions on POWER7). We remove * unsupported instruction groups from the cpu state's instruction * masks and hope the guest can cope. For at least the pseries * machine, the unavailability of these instructions can be * advertised to the guest via the device tree. */ if ((env->insns_flags & ~PPC_TCG_INSNS) || (env->insns_flags2 & ~PPC_TCG_INSNS2)) { warn_report("Disabling some instructions which are not " Loading Loading @@ -9928,31 +9974,37 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp) " Bus model : %s\n", excp_model, bus_model); printf(" MSR features :\n"); if (env->flags & POWERPC_FLAG_SPE) if (env->flags & POWERPC_FLAG_SPE) { printf(" signal processing engine enable" "\n"); else if (env->flags & POWERPC_FLAG_VRE) } else if (env->flags & POWERPC_FLAG_VRE) { printf(" vector processor enable\n"); if (env->flags & POWERPC_FLAG_TGPR) } if (env->flags & POWERPC_FLAG_TGPR) { printf(" temporary GPRs\n"); else if (env->flags & POWERPC_FLAG_CE) } else if (env->flags & POWERPC_FLAG_CE) { printf(" critical input enable\n"); if (env->flags & POWERPC_FLAG_SE) } if (env->flags & POWERPC_FLAG_SE) { printf(" single-step trace mode\n"); else if (env->flags & POWERPC_FLAG_DWE) } else if (env->flags & POWERPC_FLAG_DWE) { printf(" debug wait enable\n"); else if (env->flags & POWERPC_FLAG_UBLE) } else if (env->flags & POWERPC_FLAG_UBLE) { printf(" user BTB lock enable\n"); if (env->flags & POWERPC_FLAG_BE) } if (env->flags & POWERPC_FLAG_BE) { printf(" branch-step trace mode\n"); else if (env->flags & POWERPC_FLAG_DE) } else if (env->flags & POWERPC_FLAG_DE) { printf(" debug interrupt enable\n"); if (env->flags & POWERPC_FLAG_PX) } if (env->flags & POWERPC_FLAG_PX) { printf(" inclusive protection\n"); else if (env->flags & POWERPC_FLAG_PMM) } else if (env->flags & POWERPC_FLAG_PMM) { printf(" performance monitor mark\n"); if (env->flags == POWERPC_FLAG_NONE) } if (env->flags == POWERPC_FLAG_NONE) { printf(" none\n"); } printf(" Time-base/decrementer clock source: %s\n", env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus clock"); dump_ppc_insns(env); Loading Loading @@ -10094,8 +10146,9 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name) const char *p; unsigned long pvr; /* Lookup by PVR if cpu_model is valid 8 digit hex number * (excl: 0x prefix if present) /* * Lookup by PVR if cpu_model is valid 8 digit hex number (excl: * 0x prefix if present) */ if (!qemu_strtoul(name, &p, 16, &pvr)) { int len = p - name; Loading Loading @@ -10439,14 +10492,14 @@ static void ppc_cpu_instance_init(Object *obj) env->bfd_mach = pcc->bfd_mach; env->check_pow = pcc->check_pow; /* Mark HV mode as supported if the CPU has an MSR_HV bit * in the msr_mask. The mask can later be cleared by PAPR * mode but the hv mode support will remain, thus enforcing * that we cannot use priv. instructions in guest in PAPR * mode. For 970 we currently simply don't set HV in msr_mask * thus simulating an "Apple mode" 970. If we ever want to * support 970 HV mode, we'll have to add a processor attribute * of some sort. /* * Mark HV mode as supported if the CPU has an MSR_HV bit in the * msr_mask. The mask can later be cleared by PAPR mode but the hv * mode support will remain, thus enforcing that we cannot use * priv. instructions in guest in PAPR mode. For 970 we currently * simply don't set HV in msr_mask thus simulating an "Apple mode" * 970. If we ever want to support 970 HV mode, we'll have to add * a processor attribute of some sort. */ #if !defined(CONFIG_USER_ONLY) env->has_hv_mode = !!(env->msr_mask & MSR_HVB); Loading