qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

power8-pmu-regs.c.inc (8277B)


      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 acccess is granted for all PMCC values but 0b01, where a
     20  * Facility Unavailable Interrupt will occur.
     21  */
     22 static 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 acccess 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  */
     41 static 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  *
     62  * 'ret' must be tcg_temp_freed() by the caller.
     63  */
     64 static TCGv masked_gprn_for_spr_write(int gprn, int sprn,
     65                                       uint64_t spr_mask)
     66 {
     67     TCGv ret = tcg_temp_new();
     68     TCGv t0 = tcg_temp_new();
     69 
     70     /* 'ret' starts with all mask bits cleared */
     71     gen_load_spr(ret, sprn);
     72     tcg_gen_andi_tl(ret, ret, ~(spr_mask));
     73 
     74     /* Apply the mask into 'gprn' in a temp var */
     75     tcg_gen_andi_tl(t0, cpu_gpr[gprn], spr_mask);
     76 
     77     /* Add the masked gprn bits into 'ret' */
     78     tcg_gen_or_tl(ret, ret, t0);
     79 
     80     tcg_temp_free(t0);
     81 
     82     return ret;
     83 }
     84 
     85 void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn)
     86 {
     87     TCGv t0;
     88 
     89     if (!spr_groupA_read_allowed(ctx)) {
     90         return;
     91     }
     92 
     93     t0 = tcg_temp_new();
     94 
     95     /*
     96      * Filter out all bits but FC, PMAO, and PMAE, according
     97      * to ISA v3.1, in 10.4.4 Monitor Mode Control Register 0,
     98      * fourth paragraph.
     99      */
    100     gen_load_spr(t0, SPR_POWER_MMCR0);
    101     tcg_gen_andi_tl(t0, t0, MMCR0_UREG_MASK);
    102     tcg_gen_mov_tl(cpu_gpr[gprn], t0);
    103 
    104     tcg_temp_free(t0);
    105 }
    106 
    107 static void write_MMCR0_common(DisasContext *ctx, TCGv val)
    108 {
    109     /*
    110      * helper_store_mmcr0 will make clock based operations that
    111      * will cause 'bad icount read' errors if we do not execute
    112      * gen_icount_io_start() beforehand.
    113      */
    114     gen_icount_io_start(ctx);
    115     gen_helper_store_mmcr0(cpu_env, val);
    116 
    117     /*
    118      * End the translation block because MMCR0 writes can change
    119      * ctx->pmu_insn_cnt.
    120      */
    121     ctx->base.is_jmp = DISAS_EXIT_UPDATE;
    122 }
    123 
    124 void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn)
    125 {
    126     TCGv masked_gprn;
    127 
    128     if (!spr_groupA_write_allowed(ctx)) {
    129         return;
    130     }
    131 
    132     /*
    133      * Filter out all bits but FC, PMAO, and PMAE, according
    134      * to ISA v3.1, in 10.4.4 Monitor Mode Control Register 0,
    135      * fourth paragraph.
    136      */
    137     masked_gprn = masked_gprn_for_spr_write(gprn, SPR_POWER_MMCR0,
    138                                             MMCR0_UREG_MASK);
    139     write_MMCR0_common(ctx, masked_gprn);
    140 
    141     tcg_temp_free(masked_gprn);
    142 }
    143 
    144 void spr_read_MMCR2_ureg(DisasContext *ctx, int gprn, int sprn)
    145 {
    146     TCGv t0;
    147 
    148     if (!spr_groupA_read_allowed(ctx)) {
    149         return;
    150     }
    151 
    152     t0 = tcg_temp_new();
    153 
    154     /*
    155      * On read, filter out all bits that are not FCnP0 bits.
    156      * When MMCR0[PMCC] is set to 0b10 or 0b11, providing
    157      * problem state programs read/write access to MMCR2,
    158      * only the FCnP0 bits can be accessed. All other bits are
    159      * not changed when mtspr is executed in problem state, and
    160      * all other bits return 0s when mfspr is executed in problem
    161      * state, according to ISA v3.1, section 10.4.6 Monitor Mode
    162      * Control Register 2, p. 1316, third paragraph.
    163      */
    164     gen_load_spr(t0, SPR_POWER_MMCR2);
    165     tcg_gen_andi_tl(t0, t0, MMCR2_UREG_MASK);
    166     tcg_gen_mov_tl(cpu_gpr[gprn], t0);
    167 
    168     tcg_temp_free(t0);
    169 }
    170 
    171 void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn)
    172 {
    173     TCGv masked_gprn;
    174 
    175     if (!spr_groupA_write_allowed(ctx)) {
    176         return;
    177     }
    178 
    179     /*
    180      * Filter the bits that can be written using MMCR2_UREG_MASK,
    181      * similar to what is done in spr_write_MMCR0_ureg().
    182      */
    183     masked_gprn = masked_gprn_for_spr_write(gprn, SPR_POWER_MMCR2,
    184                                             MMCR2_UREG_MASK);
    185     gen_store_spr(SPR_POWER_MMCR2, masked_gprn);
    186 
    187     tcg_temp_free(masked_gprn);
    188 }
    189 
    190 void spr_read_PMC(DisasContext *ctx, int gprn, int sprn)
    191 {
    192     TCGv_i32 t_sprn = tcg_const_i32(sprn);
    193 
    194     gen_icount_io_start(ctx);
    195     gen_helper_read_pmc(cpu_gpr[gprn], cpu_env, t_sprn);
    196 
    197     tcg_temp_free_i32(t_sprn);
    198 }
    199 
    200 void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn)
    201 {
    202     if (!spr_groupA_read_allowed(ctx)) {
    203         return;
    204     }
    205 
    206     spr_read_PMC(ctx, gprn, sprn + 0x10);
    207 }
    208 
    209 void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn)
    210 {
    211     /*
    212      * If PMCC = 0b11, PMC5 and PMC6 aren't included in the Performance
    213      * Monitor, and a read attempt results in a Facility Unavailable
    214      * Interrupt.
    215      */
    216     if (ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) {
    217         gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_PMU);
    218         return;
    219     }
    220 
    221     /* The remaining steps are similar to PMCs 1-4 userspace read */
    222     spr_read_PMC14_ureg(ctx, gprn, sprn);
    223 }
    224 
    225 void spr_write_PMC(DisasContext *ctx, int sprn, int gprn)
    226 {
    227     TCGv_i32 t_sprn = tcg_const_i32(sprn);
    228 
    229     gen_icount_io_start(ctx);
    230     gen_helper_store_pmc(cpu_env, t_sprn, cpu_gpr[gprn]);
    231 
    232     tcg_temp_free_i32(t_sprn);
    233 }
    234 
    235 void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn)
    236 {
    237     if (!spr_groupA_write_allowed(ctx)) {
    238         return;
    239     }
    240 
    241     spr_write_PMC(ctx, sprn + 0x10, gprn);
    242 }
    243 
    244 void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn)
    245 {
    246     /*
    247      * If PMCC = 0b11, PMC5 and PMC6 aren't included in the Performance
    248      * Monitor, and a write attempt results in a Facility Unavailable
    249      * Interrupt.
    250      */
    251     if (ctx->mmcr0_pmcc0 && ctx->mmcr0_pmcc1) {
    252         gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_PMU);
    253         return;
    254     }
    255 
    256     /* The remaining steps are similar to PMCs 1-4 userspace write */
    257     spr_write_PMC14_ureg(ctx, sprn, gprn);
    258 }
    259 
    260 void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
    261 {
    262     write_MMCR0_common(ctx, cpu_gpr[gprn]);
    263 }
    264 
    265 void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn)
    266 {
    267     gen_icount_io_start(ctx);
    268     gen_helper_store_mmcr1(cpu_env, cpu_gpr[gprn]);
    269 }
    270 #else
    271 void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn)
    272 {
    273     spr_read_ureg(ctx, gprn, sprn);
    274 }
    275 
    276 void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int gprn)
    277 {
    278     spr_noaccess(ctx, gprn, sprn);
    279 }
    280 
    281 void spr_read_MMCR2_ureg(DisasContext *ctx, int gprn, int sprn)
    282 {
    283     spr_read_ureg(ctx, gprn, sprn);
    284 }
    285 
    286 void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn)
    287 {
    288     spr_noaccess(ctx, gprn, sprn);
    289 }
    290 
    291 void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn)
    292 {
    293     spr_read_ureg(ctx, gprn, sprn);
    294 }
    295 
    296 void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn)
    297 {
    298     spr_read_ureg(ctx, gprn, sprn);
    299 }
    300 
    301 void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn)
    302 {
    303     spr_noaccess(ctx, gprn, sprn);
    304 }
    305 
    306 void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn)
    307 {
    308     spr_noaccess(ctx, gprn, sprn);
    309 }
    310 
    311 void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
    312 {
    313     spr_write_generic(ctx, sprn, gprn);
    314 }
    315 
    316 void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn)
    317 {
    318     spr_write_generic(ctx, sprn, gprn);
    319 }
    320 
    321 void spr_write_PMC(DisasContext *ctx, int sprn, int gprn)
    322 {
    323     spr_write_generic(ctx, sprn, gprn);
    324 }
    325 #endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */