All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Daniel Henrique Barboza <danielhb413@gmail.com>
Cc: gustavo.romero@linaro.org, richard.henderson@linaro.org,
	qemu-devel@nongnu.org, groug@kaod.org, qemu-ppc@nongnu.org,
	clg@kaod.org
Subject: Re: [PATCH v2 01/16] target/ppc: add user write access control for PMU SPRs
Date: Wed, 25 Aug 2021 14:26:49 +1000	[thread overview]
Message-ID: <YSXGiZeWLI+L0/lr@yekko> (raw)
In-Reply-To: <20210824163032.394099-2-danielhb413@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9256 bytes --]

On Tue, Aug 24, 2021 at 01:30:17PM -0300, Daniel Henrique Barboza wrote:
> We're going to add PMU support for TCG PPC64 chips, based on IBM POWER8+
> emulation and following PowerISA v3.1.
> 
> PowerISA v3.1 defines two PMU registers groups, A and B:
> 
> - group A contains all performance monitor counters (PMCs), MMCR0, MMCR2
> and MMCRA;
> 
> - group B contains MMCR1, MMCR3, SIER, SIER2, SIER3, SIAR, SDAR.
> 
> Group A have read/write non-privileged access depending on MMCR0_PMCC
> bits. Group B is always userspace read only.
> 
> Userspace will require to write Group A registers, and at the same time
> some Linux PMU selftests deliberately test if we are allowing write
> access when we shouldn't. This patch address the access control of Group
> A PMU registers by doing the following:
> 
> - add a 'pmcc_clear' flag in DisasContext. This will map whether
> MMCR0_PMCC bits are cleared by checking HFLAGS_PMCCCLEAR;
> 
> - create a spr_write_PMU_groupA_ureg() that will be used to all
> userspace writes of PMU regs. The reg will apply the proper access
> control before forwarding execution to spr_write_ureg().
> 
> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Hoping to get a review from Richard as well before merging.

> ---
>  target/ppc/cpu.h         |  4 ++++
>  target/ppc/cpu_init.c    | 18 +++++++++---------
>  target/ppc/helper_regs.c |  3 +++
>  target/ppc/spr_tcg.h     |  1 +
>  target/ppc/translate.c   | 37 +++++++++++++++++++++++++++++++++++++
>  5 files changed, 54 insertions(+), 9 deletions(-)
> 
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 500205229c..627fc8d732 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -342,6 +342,9 @@ typedef struct ppc_v3_pate_t {
>  #define MSR_RI   1  /* Recoverable interrupt                        1        */
>  #define MSR_LE   0  /* Little-endian mode                           1 hflags */
>  
> +/* PMU bits */
> +#define MMCR0_PMCC  PPC_BITMASK(44, 45) /* PMC Control */
> +
>  /* LPCR bits */
>  #define LPCR_VPM0         PPC_BIT(0)
>  #define LPCR_VPM1         PPC_BIT(1)
> @@ -606,6 +609,7 @@ enum {
>      HFLAGS_SE = 10,  /* MSR_SE -- from elsewhere on embedded ppc */
>      HFLAGS_FP = 13,  /* MSR_FP */
>      HFLAGS_PR = 14,  /* MSR_PR */
> +    HFLAGS_PMCCCLEAR = 15, /* PMU MMCR0 PMCC equal to 0b00 */
>      HFLAGS_VSX = 23, /* MSR_VSX if cpu has VSX */
>      HFLAGS_VR = 25,  /* MSR_VR if cpu has VRE */
>  
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 66deb18a6b..c72c7fabea 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -6868,7 +6868,7 @@ static void register_book3s_pmu_sup_sprs(CPUPPCState *env)
>  static void register_book3s_pmu_user_sprs(CPUPPCState *env)
>  {
>      spr_register(env, SPR_POWER_UMMCR0, "UMMCR0",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UMMCR1, "UMMCR1",
> @@ -6876,31 +6876,31 @@ static void register_book3s_pmu_user_sprs(CPUPPCState *env)
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UMMCRA, "UMMCRA",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UPMC1, "UPMC1",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UPMC2, "UPMC2",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UPMC3, "UPMC3",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UPMC4, "UPMC4",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UPMC5, "UPMC5",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_UPMC6, "UPMC6",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_USIAR, "USIAR",
> @@ -6976,7 +6976,7 @@ static void register_power8_pmu_sup_sprs(CPUPPCState *env)
>  static void register_power8_pmu_user_sprs(CPUPPCState *env)
>  {
>      spr_register(env, SPR_POWER_UMMCR2, "UMMCR2",
> -                 &spr_read_ureg, SPR_NOACCESS,
> +                 &spr_read_ureg, &spr_write_PMU_groupA_ureg,
>                   &spr_read_ureg, &spr_write_ureg,
>                   0x00000000);
>      spr_register(env, SPR_POWER_USIER, "USIER",
> diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
> index 405450d863..4c1d9575ac 100644
> --- a/target/ppc/helper_regs.c
> +++ b/target/ppc/helper_regs.c
> @@ -106,6 +106,9 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env)
>      if (env->spr[SPR_LPCR] & LPCR_GTSE) {
>          hflags |= 1 << HFLAGS_GTSE;
>      }
> +    if (((env->spr[SPR_POWER_MMCR0] & MMCR0_PMCC) >> 18) == 0) {
> +        hflags |= 1 << HFLAGS_PMCCCLEAR;
> +    }
>  
>  #ifndef CONFIG_USER_ONLY
>      if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
> diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h
> index 0be5f347d5..027ec4c3f7 100644
> --- a/target/ppc/spr_tcg.h
> +++ b/target/ppc/spr_tcg.h
> @@ -40,6 +40,7 @@ void spr_read_601_rtcl(DisasContext *ctx, int gprn, int sprn);
>  void spr_read_601_rtcu(DisasContext *ctx, int gprn, int sprn);
>  void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn);
>  void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_PMU_groupA_ureg(DisasContext *ctx, int sprn, int gprn);
>  
>  #ifndef CONFIG_USER_ONLY
>  void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 171b216e17..3a1eafbba8 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -175,6 +175,7 @@ struct DisasContext {
>      bool spe_enabled;
>      bool tm_enabled;
>      bool gtse;
> +    bool pmcc_clear;
>      ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
>      int singlestep_enabled;
>      uint32_t flags;
> @@ -526,6 +527,41 @@ void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
>  }
>  #endif
>  
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> +/*
> + * User write function for PMU group A regs. PowerISA v3.1
> + * defines Group A sprs as:
> + *
> + * "The non-privileged read/write Performance Monitor registers
> + * (i.e., the PMCs, MMCR0, MMCR2, and MMCRA at SPR numbers
> + * 771-776, 779, 769, and 770, respectively)"
> + *
> + * These SPRs have a common user write access control via
> + * MMCR0 bits 44 and 45 (PMCC).
> + */
> +void spr_write_PMU_groupA_ureg(DisasContext *ctx, int sprn, int gprn)
> +{
> +    /*
> +     * For group A PMU sprs, if PMCC = 0b00, PowerISA v3.1
> +     * dictates that:
> +     *
> +     * "If an attempt is made to write to an SPR in group A in
> +     * problem state, a Hypervisor Emulation Assistance
> +     * interrupt will occur."
> +     */
> +    if (ctx->pmcc_clear) {
> +        gen_hvpriv_exception(ctx, POWERPC_EXCP_INVAL_SPR);
> +        return;
> +    }
> +    spr_write_ureg(ctx, sprn, gprn);
> +}
> +#else
> +void spr_write_PMU_groupA_ureg(DisasContext *ctx, int sprn, int gprn)
> +{
> +    spr_noaccess(ctx, gprn, sprn);
> +}
> +#endif
> +
>  /* SPR common to all non-embedded PowerPC */
>  /* DECR */
>  #if !defined(CONFIG_USER_ONLY)
> @@ -8539,6 +8575,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>      ctx->vsx_enabled = (hflags >> HFLAGS_VSX) & 1;
>      ctx->tm_enabled = (hflags >> HFLAGS_TM) & 1;
>      ctx->gtse = (hflags >> HFLAGS_GTSE) & 1;
> +    ctx->pmcc_clear = (hflags >> HFLAGS_PMCCCLEAR) & 1;
>  
>      ctx->singlestep_enabled = 0;
>      if ((hflags >> HFLAGS_SE) & 1) {

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2021-08-25  4:54 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-24 16:30 [PATCH v2 00/16] PMU-EBB support for PPC64 TCG Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 01/16] target/ppc: add user write access control for PMU SPRs Daniel Henrique Barboza
2021-08-25  4:26   ` David Gibson [this message]
2021-08-24 16:30 ` [PATCH v2 02/16] target/ppc: add user read functions for MMCR0 and MMCR2 Daniel Henrique Barboza
2021-08-25  4:30   ` David Gibson
2021-08-25 12:25     ` Paul A. Clarke
2021-08-25 13:35       ` David Gibson
2021-08-24 16:30 ` [PATCH v2 03/16] target/ppc: add exclusive user write function for MMCR0 Daniel Henrique Barboza
2021-08-25  4:37   ` David Gibson
2021-08-25 14:01     ` Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 04/16] target/ppc: PMU basic cycle count for pseries TCG Daniel Henrique Barboza
2021-08-25  5:19   ` David Gibson
2021-08-25 14:05     ` Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 05/16] target/ppc/power8_pmu.c: enable PMC1-PMC4 events Daniel Henrique Barboza
2021-08-25  5:23   ` David Gibson
2021-08-24 16:30 ` [PATCH v2 06/16] target/ppc: PMU: add instruction counting Daniel Henrique Barboza
2021-08-25  5:31   ` David Gibson
2021-08-25 14:10     ` Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 07/16] target/ppc/power8_pmu.c: add PM_RUN_INST_CMPL (0xFA) event Daniel Henrique Barboza
2021-08-25  5:32   ` David Gibson
2021-08-24 16:30 ` [PATCH v2 08/16] target/ppc/power8_pmu.c: add PMC14/PMC56 counter freeze bits Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 09/16] PPC64/TCG: Implement 'rfebb' instruction Daniel Henrique Barboza
2021-08-30 12:12   ` Matheus K. Ferst
2021-08-30 18:41     ` Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 10/16] target/ppc: PMU Event-Based exception support Daniel Henrique Barboza
2021-08-25  5:37   ` David Gibson
2021-08-30 19:09     ` Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 11/16] target/ppc/excp_helper.c: EBB handling adjustments Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 12/16] target/ppc/power8_pmu.c: enable PMC1 counter negative overflow Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 13/16] target/ppc/power8_pmu.c: cycles overflow with all PMCs Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 14/16] target/ppc: PMU: insns counter negative overflow support Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 15/16] target/ppc/translate: PMU: handle setting of PMCs while running Daniel Henrique Barboza
2021-08-24 16:30 ` [PATCH v2 16/16] target/ppc/power8_pmu.c: handle overflow bits when PMU is running Daniel Henrique Barboza

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YSXGiZeWLI+L0/lr@yekko \
    --to=david@gibson.dropbear.id.au \
    --cc=clg@kaod.org \
    --cc=danielhb413@gmail.com \
    --cc=groug@kaod.org \
    --cc=gustavo.romero@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.