@@ -6879,27 +6879,27 @@ static void register_book3s_pmu_user_sprs(CPUPPCState *env)
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_UPMC1, "UPMC1",
- &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_PMC14_ureg, &spr_write_PMC14_ureg,
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_UPMC2, "UPMC2",
- &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_PMC14_ureg, &spr_write_PMC14_ureg,
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_UPMC3, "UPMC3",
- &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_PMC14_ureg, &spr_write_PMC14_ureg,
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_UPMC4, "UPMC4",
- &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_PMC14_ureg, &spr_write_PMC14_ureg,
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_UPMC5, "UPMC5",
- &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_PMC56_ureg, &spr_write_PMC56_ureg,
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_UPMC6, "UPMC6",
- &spr_read_ureg, SPR_NOACCESS,
+ &spr_read_PMC56_ureg, &spr_write_PMC56_ureg,
&spr_read_ureg, &spr_write_ureg,
0x00000000);
spr_register(env, SPR_POWER_USIAR, "USIAR",
@@ -169,6 +169,56 @@ void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn)
tcg_temp_free(masked_gprn);
}
+
+void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn)
+{
+ if (!spr_groupA_read_allowed(ctx)) {
+ return;
+ }
+
+ spr_read_ureg(ctx, gprn, sprn);
+}
+
+void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn)
+{
+ /*
+ * If PMCC = 0b11, PMC5 and PMC6 aren't included in the Performance
+ * Monitor, and a read attempt results in a Facility Unavailable
+ * Interrupt.
+ */
+ if (ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) {
+ gen_hvpriv_exception(ctx, POWERPC_EXCP_FU);
+ return;
+ }
+
+ /* The remaining steps are similar to PMCs 1-4 userspace read */
+ spr_read_PMC14_ureg(ctx, gprn, sprn);
+}
+
+void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn)
+{
+ if (!spr_groupA_write_allowed(ctx)) {
+ return;
+ }
+
+ spr_write_ureg(ctx, sprn, gprn);
+}
+
+void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn)
+{
+ /*
+ * If PMCC = 0b11, PMC5 and PMC6 aren't included in the Performance
+ * Monitor, and a write attempt results in a Facility Unavailable
+ * Interrupt.
+ */
+ if (ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) {
+ gen_hvpriv_exception(ctx, POWERPC_EXCP_FU);
+ return;
+ }
+
+ /* The remaining steps are similar to PMCs 1-4 userspace write */
+ spr_write_PMC14_ureg(ctx, sprn, gprn);
+}
#else
void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn)
{
@@ -189,4 +239,24 @@ void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn)
{
spr_noaccess(ctx, gprn, sprn);
}
+
+void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn)
+{
+ spr_read_ureg(ctx, gprn, sprn);
+}
+
+void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn)
+{
+ spr_read_ureg(ctx, gprn, sprn);
+}
+
+void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn)
+{
+ spr_noaccess(ctx, gprn, sprn);
+}
+
+void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn)
+{
+ spr_noaccess(ctx, gprn, sprn);
+}
#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
@@ -34,6 +34,8 @@ void spr_write_ctr(DisasContext *ctx, int sprn, int gprn);
void spr_read_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_MMCR2_ureg(DisasContext *ctx, int gprn, int sprn);
+void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn);
+void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_tbl(DisasContext *ctx, int gprn, int sprn);
void spr_read_tbu(DisasContext *ctx, int gprn, int sprn);
void spr_read_atbl(DisasContext *ctx, int gprn, int sprn);
@@ -44,6 +46,8 @@ void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn);
void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn);
+void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn);
+void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn);
#ifndef CONFIG_USER_ONLY
void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);