1/* 2 * PMU register read/write functions for TCG IBM POWER chips 3 * 4 * Copyright IBM Corp. 2021 5 * 6 * Authors: 7 * Daniel Henrique Barboza <danielhb413@gmail.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) 14 15/* 16 * Checks whether the Group A SPR (MMCR0, MMCR2, MMCRA, and the 17 * PMCs) has problem state read access. 18 * 19 * Read access is granted for all PMCC values but 0b01, where a 20 * Facility Unavailable Interrupt will occur. 21 */ 22static bool spr_groupA_read_allowed(DisasContext *ctx) 23{ 24 if (!ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) { 25 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_PMU); 26 return false; 27 } 28 29 return true; 30} 31 32/* 33 * Checks whether the Group A SPR (MMCR0, MMCR2, MMCRA, and the 34 * PMCs) has problem state write access. 35 * 36 * Write access is granted for PMCC values 0b10 and 0b11. Userspace 37 * writing with PMCC 0b00 will generate a Hypervisor Emulation 38 * Assistance Interrupt. Userspace writing with PMCC 0b01 will 39 * generate a Facility Unavailable Interrupt. 40 */ 41static bool spr_groupA_write_allowed(DisasContext *ctx) 42{ 43 if (ctx->mmcr0_pmcc0) { 44 return true; 45 } 46 47 if (ctx->mmcr0_pmcc1) { 48 /* PMCC = 0b01 */ 49 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_PMU); 50 } else { 51 /* PMCC = 0b00 */ 52 gen_hvpriv_exception(ctx, POWERPC_EXCP_PRIV_REG); 53 } 54 55 return false; 56} 57 58/* 59 * Helper function to avoid code repetition between MMCR0 and 60 * MMCR2 problem state write functions. 61 */ 62static TCGv masked_gprn_for_spr_write(int gprn, int sprn, 63 uint64_t spr_mask) 64{ 65 TCGv ret = tcg_temp_new(); 66 TCGv t0 = tcg_temp_new(); 67 68 /* 'ret' starts with all mask bits cleared */ 69 gen_load_spr(ret, sprn); 70 tcg_gen_andi_tl(ret, ret, ~(spr_mask)); 71 72 /* Apply the mask into 'gprn' in a temp var */ 73 tcg_gen_andi_tl(t0, cpu_gpr[gprn], spr_mask); 74 75 /* Add the masked gprn bits into 'ret' */ 76 tcg_gen_or_tl(ret, ret, t0); 77 78 return ret; 79} 80 81void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn) 82{ 83 TCGv t0; 84 85 if (!spr_groupA_read_allowed(ctx)) { 86 return; 87 } 88 89 t0 = tcg_temp_new(); 90 91 /* 92 * Filter out all bits but FC, PMAO, and PMAE, according 93 * to ISA v3.1, in 10.4.4 Monitor Mode Control Register 0, 94 * fourth paragraph. 95 */ 96 gen_load_spr(t0, SPR_POWER_MMCR0); 97 tcg_gen_andi_tl(t0, t0, MMCR0_UREG_MASK); 98 tcg_gen_mov_tl(cpu_gpr[gprn], t0); 99} 100 101static void write_MMCR0_common(DisasContext *ctx, TCGv val) 102{ 103 /* 104 * helper_store_mmcr0 will make clock based operations that 105 * will cause 'bad icount read' errors if we do not execute 106 * translator_io_start() beforehand. 107 */ 108 translator_io_start(&ctx->base); 109 gen_helper_store_mmcr0(tcg_env, val); 110 111 /* 112 * End the translation block because MMCR0 writes can change 113 * ctx->pmu_insn_cnt. 114 */ 115 ctx->base.is_jmp = DISAS_EXIT_UPDATE; 116} 117 118void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn) 119{ 120 TCGv masked_gprn; 121 122 if (!spr_groupA_write_allowed(ctx)) { 123 return; 124 } 125 126 /* 127 * Filter out all bits but FC, PMAO, and PMAE, according 128 * to ISA v3.1, in 10.4.4 Monitor Mode Control Register 0, 129 * fourth paragraph. 130 */ 131 masked_gprn = masked_gprn_for_spr_write(gprn, SPR_POWER_MMCR0, 132 MMCR0_UREG_MASK); 133 write_MMCR0_common(ctx, masked_gprn); 134} 135 136void spr_read_MMCR2_ureg(DisasContext *ctx, int gprn, int sprn) 137{ 138 TCGv t0; 139 140 if (!spr_groupA_read_allowed(ctx)) { 141 return; 142 } 143 144 t0 = tcg_temp_new(); 145 146 /* 147 * On read, filter out all bits that are not FCnP0 bits. 148 * When MMCR0[PMCC] is set to 0b10 or 0b11, providing 149 * problem state programs read/write access to MMCR2, 150 * only the FCnP0 bits can be accessed. All other bits are 151 * not changed when mtspr is executed in problem state, and 152 * all other bits return 0s when mfspr is executed in problem 153 * state, according to ISA v3.1, section 10.4.6 Monitor Mode 154 * Control Register 2, p. 1316, third paragraph. 155 */ 156 gen_load_spr(t0, SPR_POWER_MMCR2); 157 tcg_gen_andi_tl(t0, t0, MMCR2_UREG_MASK); 158 tcg_gen_mov_tl(cpu_gpr[gprn], t0); 159} 160 161void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn) 162{ 163 TCGv masked_gprn; 164 165 if (!spr_groupA_write_allowed(ctx)) { 166 return; 167 } 168 169 /* 170 * Filter the bits that can be written using MMCR2_UREG_MASK, 171 * similar to what is done in spr_write_MMCR0_ureg(). 172 */ 173 masked_gprn = masked_gprn_for_spr_write(gprn, SPR_POWER_MMCR2, 174 MMCR2_UREG_MASK); 175 gen_store_spr(SPR_POWER_MMCR2, masked_gprn); 176} 177 178void spr_write_MMCRA(DisasContext *ctx, int sprn, int gprn) 179{ 180 gen_helper_store_mmcrA(tcg_env, cpu_gpr[gprn]); 181} 182 183void spr_read_PMC(DisasContext *ctx, int gprn, int sprn) 184{ 185 TCGv_i32 t_sprn = tcg_constant_i32(sprn); 186 187 translator_io_start(&ctx->base); 188 gen_helper_read_pmc(cpu_gpr[gprn], tcg_env, t_sprn); 189} 190 191void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn) 192{ 193 if (!spr_groupA_read_allowed(ctx)) { 194 return; 195 } 196 197 spr_read_PMC(ctx, gprn, sprn + 0x10); 198} 199 200void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn) 201{ 202 /* 203 * If PMCC = 0b11, PMC5 and PMC6 aren't included in the Performance 204 * Monitor, and a read attempt results in a Facility Unavailable 205 * Interrupt. 206 */ 207 if (ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) { 208 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_PMU); 209 return; 210 } 211 212 /* The remaining steps are similar to PMCs 1-4 userspace read */ 213 spr_read_PMC14_ureg(ctx, gprn, sprn); 214} 215 216void spr_write_PMC(DisasContext *ctx, int sprn, int gprn) 217{ 218 TCGv_i32 t_sprn = tcg_constant_i32(sprn); 219 220 translator_io_start(&ctx->base); 221 gen_helper_store_pmc(tcg_env, t_sprn, cpu_gpr[gprn]); 222} 223 224void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn) 225{ 226 if (!spr_groupA_write_allowed(ctx)) { 227 return; 228 } 229 230 spr_write_PMC(ctx, sprn + 0x10, gprn); 231} 232 233void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn) 234{ 235 /* 236 * If PMCC = 0b11, PMC5 and PMC6 aren't included in the Performance 237 * Monitor, and a write attempt results in a Facility Unavailable 238 * Interrupt. 239 */ 240 if (ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) { 241 gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_PMU); 242 return; 243 } 244 245 /* The remaining steps are similar to PMCs 1-4 userspace write */ 246 spr_write_PMC14_ureg(ctx, sprn, gprn); 247} 248 249void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn) 250{ 251 write_MMCR0_common(ctx, cpu_gpr[gprn]); 252} 253 254void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn) 255{ 256 translator_io_start(&ctx->base); 257 gen_helper_store_mmcr1(tcg_env, cpu_gpr[gprn]); 258} 259#else 260void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn) 261{ 262 spr_read_ureg(ctx, gprn, sprn); 263} 264 265void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn) 266{ 267 spr_noaccess(ctx, gprn, sprn); 268} 269 270void spr_read_MMCR2_ureg(DisasContext *ctx, int gprn, int sprn) 271{ 272 spr_read_ureg(ctx, gprn, sprn); 273} 274 275void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn) 276{ 277 spr_noaccess(ctx, gprn, sprn); 278} 279 280void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn) 281{ 282 spr_read_ureg(ctx, gprn, sprn); 283} 284 285void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn) 286{ 287 spr_read_ureg(ctx, gprn, sprn); 288} 289 290void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn) 291{ 292 spr_noaccess(ctx, gprn, sprn); 293} 294 295void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn) 296{ 297 spr_noaccess(ctx, gprn, sprn); 298} 299 300void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn) 301{ 302 spr_write_generic(ctx, sprn, gprn); 303} 304 305void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn) 306{ 307 spr_write_generic(ctx, sprn, gprn); 308} 309 310void spr_write_PMC(DisasContext *ctx, int sprn, int gprn) 311{ 312 spr_write_generic(ctx, sprn, gprn); 313} 314#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */ 315