@@ -533,6 +533,8 @@ FIELD(MSR, LE, MSR_LE, 1)
#define MMCR0_FC56 PPC_BIT(59) /* PMC Freeze Counters 5-6 bit */
#define MMCR0_PMC1CE PPC_BIT(48) /* MMCR0 PMC1 Condition Enabled */
#define MMCR0_PMCjCE PPC_BIT(49) /* MMCR0 PMCj Condition Enabled */
+#define MMCR0_FCP PPC_BIT(34) /* Freeze Counters/BHRB if PR=1 */
+#define MMCR0_FCPC PPC_BIT(51) /* Condition for FCP bit */
/* MMCR0 userspace r/w mask */
#define MMCR0_UREG_MASK (MMCR0_FC | MMCR0_PMAO | MMCR0_PMAE)
/* MMCR2 userspace r/w mask */
@@ -545,6 +547,8 @@ FIELD(MSR, LE, MSR_LE, 1)
#define MMCR2_UREG_MASK (MMCR2_FC1P0 | MMCR2_FC2P0 | MMCR2_FC3P0 | \
MMCR2_FC4P0 | MMCR2_FC5P0 | MMCR2_FC6P0)
+#define MMCRA_BHRBRD PPC_BIT(26) /* BHRB Recording Disable */
+
#define MMCR1_EVT_SIZE 8
/* extract64() does a right shift before extracting */
#define MMCR1_PMC1SEL_START 32
@@ -797,6 +801,7 @@ enum {
HFLAGS_PMCJCE = 17, /* MMCR0 PMCjCE bit */
HFLAGS_PMC_OTHER = 18, /* PMC other than PMC5-6 is enabled */
HFLAGS_INSN_CNT = 19, /* PMU instruction count enabled */
+ HFLAGS_BHRB_ENABLE = 20, /* Summary flag for enabling BHRB */
HFLAGS_VSX = 23, /* MSR_VSX if cpu has VSX */
HFLAGS_VR = 25, /* MSR_VR if cpu has VRE */
@@ -5152,7 +5152,7 @@ static void register_book3s_pmu_sup_sprs(CPUPPCState *env)
KVM_REG_PPC_MMCR1, 0x00000000);
spr_register_kvm(env, SPR_POWER_MMCRA, "MMCRA",
SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_MMCRA,
KVM_REG_PPC_MMCRA, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC1, "PMC1",
SPR_NOACCESS, SPR_NOACCESS,
@@ -7196,7 +7196,7 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
if (env->mmu_model != POWERPC_MMU_REAL) {
ppc_tlb_invalidate_all(env);
}
- pmu_mmcr01_updated(env);
+ pmu_mmcr01a_updated(env);
}
/* clean any pending stop state */
@@ -30,6 +30,7 @@ DEF_HELPER_2(store_dawr0, void, env, tl)
DEF_HELPER_2(store_dawrx0, void, env, tl)
DEF_HELPER_2(store_mmcr0, void, env, tl)
DEF_HELPER_2(store_mmcr1, void, env, tl)
+DEF_HELPER_2(store_mmcrA, void, env, tl)
DEF_HELPER_3(store_pmc, void, env, i32, i64)
DEF_HELPER_2(read_pmc, tl, env, i32)
DEF_HELPER_2(insns_inc, void, env, i32)
@@ -47,6 +47,39 @@ void hreg_swap_gpr_tgpr(CPUPPCState *env)
env->tgpr[3] = tmp;
}
+#if defined(TARGET_PPC64)
+static bool hreg_check_bhrb_enable(CPUPPCState *env)
+{
+ bool pr = !!(env->msr & (1 << MSR_PR));
+ target_long mmcr0;
+ bool fcp;
+ bool hv;
+
+ /* ISA 3.1 adds the PMCRA[BRHBRD] and problem state checks */
+ if ((env->insns_flags2 & PPC2_ISA310) &&
+ ((env->spr[SPR_POWER_MMCRA] & MMCRA_BHRBRD) || !pr)) {
+ return false;
+ }
+
+ /* Check for BHRB "frozen" conditions */
+ mmcr0 = env->spr[SPR_POWER_MMCR0];
+ fcp = !!(mmcr0 & MMCR0_FCP);
+ if (mmcr0 & MMCR0_FCPC) {
+ hv = !!(env->msr & (1ull << MSR_HV));
+ if (fcp) {
+ if (hv && pr) {
+ return false;
+ }
+ } else if (!hv && pr) {
+ return false;
+ }
+ } else if (fcp && pr) {
+ return false;
+ }
+ return true;
+}
+#endif
+
static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env)
{
uint32_t hflags = 0;
@@ -61,6 +94,9 @@ static uint32_t hreg_compute_pmu_hflags_value(CPUPPCState *env)
if (env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE) {
hflags |= 1 << HFLAGS_PMCJCE;
}
+ if (hreg_check_bhrb_enable(env)) {
+ hflags |= 1 << HFLAGS_BHRB_ENABLE;
+ }
#ifndef CONFIG_USER_ONLY
if (env->pmc_ins_cnt) {
@@ -85,6 +121,7 @@ static uint32_t hreg_compute_pmu_hflags_mask(CPUPPCState *env)
hflags_mask |= 1 << HFLAGS_PMCJCE;
hflags_mask |= 1 << HFLAGS_INSN_CNT;
hflags_mask |= 1 << HFLAGS_PMC_OTHER;
+ hflags_mask |= 1 << HFLAGS_BHRB_ENABLE;
#endif
return hflags_mask;
}
@@ -333,7 +333,7 @@ static int cpu_post_load(void *opaque, int version_id)
* triggered types (including HDEC) would need to carry more state.
*/
cpu_ppc_store_decr(env, env->spr[SPR_DECR]);
- pmu_mmcr01_updated(env);
+ pmu_mmcr01a_updated(env);
}
return 0;
@@ -175,6 +175,11 @@ void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn)
gen_store_spr(SPR_POWER_MMCR2, masked_gprn);
}
+void spr_write_MMCRA(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_mmcrA(tcg_env, cpu_gpr[gprn]);
+}
+
void spr_read_PMC(DisasContext *ctx, int gprn, int sprn)
{
TCGv_i32 t_sprn = tcg_constant_i32(sprn);
@@ -82,7 +82,7 @@ static void pmu_update_summaries(CPUPPCState *env)
env->pmc_cyc_cnt = cyc_cnt;
}
-void pmu_mmcr01_updated(CPUPPCState *env)
+void pmu_mmcr01a_updated(CPUPPCState *env)
{
PowerPCCPU *cpu = env_archcpu(env);
@@ -260,7 +260,7 @@ void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
env->spr[SPR_POWER_MMCR0] = value;
- pmu_mmcr01_updated(env);
+ pmu_mmcr01a_updated(env);
/* Update cycle overflow timers with the current MMCR0 state */
pmu_update_overflow_timers(env);
@@ -272,7 +272,14 @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value)
env->spr[SPR_POWER_MMCR1] = value;
- pmu_mmcr01_updated(env);
+ pmu_mmcr01a_updated(env);
+}
+
+void helper_store_mmcrA(CPUPPCState *env, uint64_t value)
+{
+ env->spr[SPR_POWER_MMCRA] = value;
+
+ pmu_mmcr01a_updated(env);
}
target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn)
@@ -301,7 +308,7 @@ static void perfm_alert(PowerPCCPU *cpu)
env->spr[SPR_POWER_MMCR0] |= MMCR0_FC;
/* Changing MMCR0_FC requires summaries and hflags update */
- pmu_mmcr01_updated(env);
+ pmu_mmcr01a_updated(env);
/*
* Delete all pending timers if we need to freeze
@@ -18,10 +18,10 @@
#define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL
void cpu_ppc_pmu_init(CPUPPCState *env);
-void pmu_mmcr01_updated(CPUPPCState *env);
+void pmu_mmcr01a_updated(CPUPPCState *env);
#else
static inline void cpu_ppc_pmu_init(CPUPPCState *env) { }
-static inline void pmu_mmcr01_updated(CPUPPCState *env) { }
+static inline void pmu_mmcr01a_updated(CPUPPCState *env) { }
#endif
#endif
@@ -85,6 +85,7 @@ void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn);
+void spr_write_MMCRA(DisasContext *ctx, int sprn, int gprn);
void spr_write_PMC(DisasContext *ctx, int sprn, int gprn);
void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn);
void spr_read_xer(DisasContext *ctx, int gprn, int sprn);
@@ -193,6 +193,7 @@ struct DisasContext {
bool mmcr0_pmcjce;
bool pmc_other;
bool pmu_insn_cnt;
+ bool bhrb_enable;
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
int singlestep_enabled;
uint32_t flags;
@@ -6345,6 +6346,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->mmcr0_pmcjce = (hflags >> HFLAGS_PMCJCE) & 1;
ctx->pmc_other = (hflags >> HFLAGS_PMC_OTHER) & 1;
ctx->pmu_insn_cnt = (hflags >> HFLAGS_INSN_CNT) & 1;
+ ctx->bhrb_enable = (hflags >> HFLAGS_BHRB_ENABLE) & 1;
ctx->singlestep_enabled = 0;
if ((hflags >> HFLAGS_SE) & 1) {