diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/ppc/cpu.h | 19 | ||||
-rw-r--r-- | target/ppc/cpu_init.c | 25 | ||||
-rw-r--r-- | target/ppc/excp_helper.c | 58 | ||||
-rw-r--r-- | target/ppc/kvm_ppc.h | 3 | ||||
-rw-r--r-- | target/ppc/mmu_common.c | 5 | ||||
-rw-r--r-- | target/ppc/spr_common.h | 1 | ||||
-rw-r--r-- | target/ppc/translate.c | 19 |
7 files changed, 113 insertions, 17 deletions
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 81d4263..3923f17 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1069,6 +1069,21 @@ struct ppc_radix_page_info { }; /*****************************************************************************/ +/* Dynamic Execution Control Register */ + +#define DEXCR_ASPECT(name, num) \ +FIELD(DEXCR, PNH_##name, PPC_BIT_NR(num), 1) \ +FIELD(DEXCR, PRO_##name, PPC_BIT_NR(num + 32), 1) \ +FIELD(HDEXCR, HNU_##name, PPC_BIT_NR(num), 1) \ +FIELD(HDEXCR, ENF_##name, PPC_BIT_NR(num + 32), 1) \ + +DEXCR_ASPECT(SBHE, 0) +DEXCR_ASPECT(IBRTPD, 1) +DEXCR_ASPECT(SRAPD, 4) +DEXCR_ASPECT(NPHIE, 5) +DEXCR_ASPECT(PHIE, 6) + +/*****************************************************************************/ /* The whole PowerPC CPU context */ /* @@ -1674,9 +1689,11 @@ void ppc_compat_add_property(Object *obj, const char *name, #define SPR_BOOKE_GIVOR13 (0x1BC) #define SPR_BOOKE_GIVOR14 (0x1BD) #define SPR_TIR (0x1BE) +#define SPR_UHDEXCR (0x1C7) #define SPR_PTCR (0x1D0) #define SPR_HASHKEYR (0x1D4) #define SPR_HASHPKEYR (0x1D5) +#define SPR_HDEXCR (0x1D7) #define SPR_BOOKE_SPEFSCR (0x200) #define SPR_Exxx_BBEAR (0x201) #define SPR_Exxx_BBTAR (0x202) @@ -1865,8 +1882,10 @@ void ppc_compat_add_property(Object *obj, const char *name, #define SPR_RCPU_L2U_RA2 (0x32A) #define SPR_MPC_MD_DBRAM1 (0x32A) #define SPR_RCPU_L2U_RA3 (0x32B) +#define SPR_UDEXCR (0x32C) #define SPR_TAR (0x32F) #define SPR_ASDR (0x330) +#define SPR_DEXCR (0x33C) #define SPR_IC (0x350) #define SPR_VTB (0x351) #define SPR_MMCRC (0x353) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 95d2585..abee71d 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5727,6 +5727,30 @@ static void register_power10_hash_sprs(CPUPPCState *env) hashpkeyr_initial_value); } +static void register_power10_dexcr_sprs(CPUPPCState *env) +{ + spr_register(env, SPR_DEXCR, "DEXCR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0); + + spr_register(env, SPR_UDEXCR, "DEXCR", + &spr_read_dexcr_ureg, SPR_NOACCESS, + &spr_read_dexcr_ureg, SPR_NOACCESS, + 0); + + spr_register_hv(env, SPR_HDEXCR, "HDEXCR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0); + + spr_register(env, SPR_UHDEXCR, "HDEXCR", + &spr_read_dexcr_ureg, SPR_NOACCESS, + &spr_read_dexcr_ureg, SPR_NOACCESS, + 0); +} + /* * Initialize PMU counter overflow timers for Power8 and * newer Power chips when using TCG. @@ -6402,6 +6426,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); register_power10_hash_sprs(env); + register_power10_dexcr_sprs(env); /* FIXME: Filter fields properly based on privilege level */ spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 94adcb7..add4d54 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2902,29 +2902,57 @@ static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key) return stage1_h ^ stage1_l; } +static void do_hash(CPUPPCState *env, target_ulong ea, target_ulong ra, + target_ulong rb, uint64_t key, bool store) +{ + uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash; + + if (store) { + cpu_stq_data_ra(env, ea, calculated_hash, GETPC()); + } else { + loaded_hash = cpu_ldq_data_ra(env, ea, GETPC()); + if (loaded_hash != calculated_hash) { + raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_TRAP, GETPC()); + } + } +} + #include "qemu/guest-random.h" -#define HELPER_HASH(op, key, store) \ +#ifdef TARGET_PPC64 +#define HELPER_HASH(op, key, store, dexcr_aspect) \ void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \ target_ulong rb) \ { \ - uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash; \ - \ - if (store) { \ - cpu_stq_data_ra(env, ea, calculated_hash, GETPC()); \ - } else { \ - loaded_hash = cpu_ldq_data_ra(env, ea, GETPC()); \ - if (loaded_hash != calculated_hash) { \ - raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, \ - POWERPC_EXCP_TRAP, GETPC()); \ - } \ + if (env->msr & R_MSR_PR_MASK) { \ + if (!(env->spr[SPR_DEXCR] & R_DEXCR_PRO_##dexcr_aspect##_MASK || \ + env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \ + return; \ + } else if (!(env->msr & R_MSR_HV_MASK)) { \ + if (!(env->spr[SPR_DEXCR] & R_DEXCR_PNH_##dexcr_aspect##_MASK || \ + env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \ + return; \ + } else if (!(env->msr & R_MSR_S_MASK)) { \ + if (!(env->spr[SPR_HDEXCR] & R_HDEXCR_HNU_##dexcr_aspect##_MASK)) \ + return; \ } \ + \ + do_hash(env, ea, ra, rb, key, store); \ +} +#else +#define HELPER_HASH(op, key, store, dexcr_aspect) \ +void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \ + target_ulong rb) \ +{ \ + do_hash(env, ea, ra, rb, key, store); \ } +#endif /* TARGET_PPC64 */ -HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true) -HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false) -HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true) -HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false) +HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true, NPHIE) +HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false, NPHIE) +HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true, PHIE) +HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false, PHIE) #endif /* CONFIG_TCG */ #if !defined(CONFIG_USER_ONLY) diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index ee9325b..5fd9753 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -9,6 +9,9 @@ #ifndef KVM_PPC_H #define KVM_PPC_H +#include "exec/hwaddr.h" +#include "cpu.h" + #define TYPE_HOST_POWERPC_CPU POWERPC_CPU_TYPE_NAME("host") #ifdef CONFIG_KVM diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c index 89107a6..8901f4d 100644 --- a/target/ppc/mmu_common.c +++ b/target/ppc/mmu_common.c @@ -811,7 +811,8 @@ static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb, } } - qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: No TLB entry found for effective address " + "0x" TARGET_FMT_lx "\n", __func__, address); return -1; found_tlb: @@ -979,7 +980,7 @@ static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset, pa = entry->mas7_3 & ~(size - 1); qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c" - "U%c%c%c %c%c%c%c%c U%c%c%c%c\n", + " U%c%c%c %c%c%c%c%c U%c%c%c%c\n", (uint64_t)ea, (uint64_t)pa, book3e_tsize_to_str[tsize], (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT, diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h index b5a5bc6..8437eb0 100644 --- a/target/ppc/spr_common.h +++ b/target/ppc/spr_common.h @@ -195,6 +195,7 @@ void spr_read_ebb_upper32(DisasContext *ctx, int gprn, int sprn); void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn); void spr_write_hmer(DisasContext *ctx, int sprn, int gprn); void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn); +void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn); #endif void register_low_BATs(CPUPPCState *env); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 19c1d17..edb3daa 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -1249,6 +1249,25 @@ void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn) gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB); spr_write_prev_upper32(ctx, sprn, gprn); } + +void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn) +{ + TCGv t0 = tcg_temp_new(); + + /* + * Access to the (H)DEXCR in problem state is done using separated + * SPR indexes which are 16 below the SPR indexes which have full + * access to the (H)DEXCR in privileged state. Problem state can + * only read bits 32:63, bits 0:31 return 0. + * + * See section 9.3.1-9.3.2 of PowerISA v3.1B + */ + + gen_load_spr(t0, sprn + 16); + tcg_gen_ext32u_tl(cpu_gpr[gprn], t0); + + tcg_temp_free(t0); +} #endif #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ |