[PATCH v4 28/28] KVM: arm64: nv: Add support for HCRX_EL2

Jing Zhang jingzhangos at google.com
Tue Aug 15 17:18:45 PDT 2023


Hi Marc,

On Tue, Aug 15, 2023 at 11:47 AM Marc Zyngier <maz at kernel.org> wrote:
>
> HCRX_EL2 has an interesting effect on HFGITR_EL2, as it conditions
> the traps of TLBI*nXS.
>
> Expand the FGT support to add a new Fine Grained Filter that will
> get checked when the instruction gets trapped, allowing the shadow
> register to override the trap as needed.
>
> Reviewed-by: Eric Auger <eric.auger at redhat.com>
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>  arch/arm64/include/asm/kvm_arm.h        |  5 ++
>  arch/arm64/include/asm/kvm_host.h       |  1 +
>  arch/arm64/kvm/emulate-nested.c         | 94 ++++++++++++++++---------
>  arch/arm64/kvm/hyp/include/hyp/switch.h | 15 +++-
>  arch/arm64/kvm/nested.c                 |  3 +-
>  arch/arm64/kvm/sys_regs.c               |  2 +
>  6 files changed, 83 insertions(+), 37 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> index d229f238c3b6..137f732789c9 100644
> --- a/arch/arm64/include/asm/kvm_arm.h
> +++ b/arch/arm64/include/asm/kvm_arm.h
> @@ -369,6 +369,11 @@
>  #define __HDFGWTR_EL2_MASK     ~__HDFGWTR_EL2_nMASK
>  #define __HDFGWTR_EL2_nMASK    GENMASK(62, 60)
>
> +/* Similar definitions for HCRX_EL2 */
> +#define __HCRX_EL2_RES0                (GENMASK(63, 16) | GENMASK(13, 12))
> +#define __HCRX_EL2_MASK                (0)
> +#define __HCRX_EL2_nMASK       (GENMASK(15, 14) | GENMASK(4, 0))
> +
>  /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
>  #define HPFAR_MASK     (~UL(0xf))
>  /*
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index cb1c5c54cedd..93c541111dea 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -380,6 +380,7 @@ enum vcpu_sysreg {
>         CPTR_EL2,       /* Architectural Feature Trap Register (EL2) */
>         HSTR_EL2,       /* Hypervisor System Trap Register */
>         HACR_EL2,       /* Hypervisor Auxiliary Control Register */
> +       HCRX_EL2,       /* Extended Hypervisor Configuration Register */
>         TTBR0_EL2,      /* Translation Table Base Register 0 (EL2) */
>         TTBR1_EL2,      /* Translation Table Base Register 1 (EL2) */
>         TCR_EL2,        /* Translation Control Register (EL2) */
> diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-nested.c
> index c9662f9a345e..1cc606c16416 100644
> --- a/arch/arm64/kvm/emulate-nested.c
> +++ b/arch/arm64/kvm/emulate-nested.c
> @@ -426,11 +426,13 @@ static const complex_condition_check ccc[] = {
>   * [13:10]     enum fgt_group_id (4 bits)
>   * [19:14]     bit number in the FGT register (6 bits)
>   * [20]                trap polarity (1 bit)
> - * [62:21]     Unused (42 bits)
> + * [25:21]     FG filter (5 bits)
> + * [62:26]     Unused (37 bits)
>   * [63]                RES0 - Must be zero, as lost on insertion in the xarray
>   */
>  #define TC_CGT_BITS    10
>  #define TC_FGT_BITS    4
> +#define TC_FGF_BITS    5
>
>  union trap_config {
>         u64     val;
> @@ -439,7 +441,8 @@ union trap_config {
>                 unsigned long   fgt:TC_FGT_BITS; /* Fine Grained Trap id */
>                 unsigned long   bit:6;           /* Bit number */
>                 unsigned long   pol:1;           /* Polarity */
> -               unsigned long   unused:42;       /* Unused, should be zero */
> +               unsigned long   fgf:TC_FGF_BITS; /* Fine Grained Filter */
> +               unsigned long   unused:37;       /* Unused, should be zero */
>                 unsigned long   mbz:1;           /* Must Be Zero */
>         };
>  };
> @@ -947,7 +950,15 @@ enum fgt_group_id {
>         __NR_FGT_GROUP_IDS__
>  };
>
> -#define SR_FGT(sr, g, b, p)                                    \
> +enum fg_filter_id {
> +       __NO_FGF__,
> +       HCRX_FGTnXS,
> +
> +       /* Must be last */
> +       __NR_FG_FILTER_IDS__
> +};
> +
> +#define SR_FGF(sr, g, b, p, f)                                 \
>         {                                                       \
>                 .encoding       = sr,                           \
>                 .end            = sr,                           \
> @@ -955,10 +966,13 @@ enum fgt_group_id {
>                         .fgt = g ## _GROUP,                     \
>                         .bit = g ## _EL2_ ## b ## _SHIFT,       \
>                         .pol = p,                               \
> +                       .fgf = f,                               \
>                 },                                              \
>                 .line = __LINE__,                               \
>         }
>
> +#define SR_FGT(sr, g, b, p)    SR_FGF(sr, g, b, p, __NO_FGF__)
> +
>  static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
>         /* HFGRTR_EL2, HFGWTR_EL2 */
>         SR_FGT(SYS_TPIDR2_EL0,          HFGxTR, nTPIDR2_EL0, 0),
> @@ -1062,37 +1076,37 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
>         SR_FGT(OP_TLBI_ASIDE1OS,        HFGITR, TLBIASIDE1OS, 1),
>         SR_FGT(OP_TLBI_VAE1OS,          HFGITR, TLBIVAE1OS, 1),
>         SR_FGT(OP_TLBI_VMALLE1OS,       HFGITR, TLBIVMALLE1OS, 1),
> -       /* FIXME: nXS variants must be checked against HCRX_EL2.FGTnXS */
> -       SR_FGT(OP_TLBI_VAALE1NXS,       HFGITR, TLBIVAALE1, 1),
> -       SR_FGT(OP_TLBI_VALE1NXS,        HFGITR, TLBIVALE1, 1),
> -       SR_FGT(OP_TLBI_VAAE1NXS,        HFGITR, TLBIVAAE1, 1),
> -       SR_FGT(OP_TLBI_ASIDE1NXS,       HFGITR, TLBIASIDE1, 1),
> -       SR_FGT(OP_TLBI_VAE1NXS,         HFGITR, TLBIVAE1, 1),
> -       SR_FGT(OP_TLBI_VMALLE1NXS,      HFGITR, TLBIVMALLE1, 1),
> -       SR_FGT(OP_TLBI_RVAALE1NXS,      HFGITR, TLBIRVAALE1, 1),
> -       SR_FGT(OP_TLBI_RVALE1NXS,       HFGITR, TLBIRVALE1, 1),
> -       SR_FGT(OP_TLBI_RVAAE1NXS,       HFGITR, TLBIRVAAE1, 1),
> -       SR_FGT(OP_TLBI_RVAE1NXS,        HFGITR, TLBIRVAE1, 1),
> -       SR_FGT(OP_TLBI_RVAALE1ISNXS,    HFGITR, TLBIRVAALE1IS, 1),
> -       SR_FGT(OP_TLBI_RVALE1ISNXS,     HFGITR, TLBIRVALE1IS, 1),
> -       SR_FGT(OP_TLBI_RVAAE1ISNXS,     HFGITR, TLBIRVAAE1IS, 1),
> -       SR_FGT(OP_TLBI_RVAE1ISNXS,      HFGITR, TLBIRVAE1IS, 1),
> -       SR_FGT(OP_TLBI_VAALE1ISNXS,     HFGITR, TLBIVAALE1IS, 1),
> -       SR_FGT(OP_TLBI_VALE1ISNXS,      HFGITR, TLBIVALE1IS, 1),
> -       SR_FGT(OP_TLBI_VAAE1ISNXS,      HFGITR, TLBIVAAE1IS, 1),
> -       SR_FGT(OP_TLBI_ASIDE1ISNXS,     HFGITR, TLBIASIDE1IS, 1),
> -       SR_FGT(OP_TLBI_VAE1ISNXS,       HFGITR, TLBIVAE1IS, 1),
> -       SR_FGT(OP_TLBI_VMALLE1ISNXS,    HFGITR, TLBIVMALLE1IS, 1),
> -       SR_FGT(OP_TLBI_RVAALE1OSNXS,    HFGITR, TLBIRVAALE1OS, 1),
> -       SR_FGT(OP_TLBI_RVALE1OSNXS,     HFGITR, TLBIRVALE1OS, 1),
> -       SR_FGT(OP_TLBI_RVAAE1OSNXS,     HFGITR, TLBIRVAAE1OS, 1),
> -       SR_FGT(OP_TLBI_RVAE1OSNXS,      HFGITR, TLBIRVAE1OS, 1),
> -       SR_FGT(OP_TLBI_VAALE1OSNXS,     HFGITR, TLBIVAALE1OS, 1),
> -       SR_FGT(OP_TLBI_VALE1OSNXS,      HFGITR, TLBIVALE1OS, 1),
> -       SR_FGT(OP_TLBI_VAAE1OSNXS,      HFGITR, TLBIVAAE1OS, 1),
> -       SR_FGT(OP_TLBI_ASIDE1OSNXS,     HFGITR, TLBIASIDE1OS, 1),
> -       SR_FGT(OP_TLBI_VAE1OSNXS,       HFGITR, TLBIVAE1OS, 1),
> -       SR_FGT(OP_TLBI_VMALLE1OSNXS,    HFGITR, TLBIVMALLE1OS, 1),
> +       /* nXS variants must be checked against HCRX_EL2.FGTnXS */
> +       SR_FGF(OP_TLBI_VAALE1NXS,       HFGITR, TLBIVAALE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VALE1NXS,        HFGITR, TLBIVALE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAAE1NXS,        HFGITR, TLBIVAAE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_ASIDE1NXS,       HFGITR, TLBIASIDE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAE1NXS,         HFGITR, TLBIVAE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VMALLE1NXS,      HFGITR, TLBIVMALLE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAALE1NXS,      HFGITR, TLBIRVAALE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVALE1NXS,       HFGITR, TLBIRVALE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAAE1NXS,       HFGITR, TLBIRVAAE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAE1NXS,        HFGITR, TLBIRVAE1, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAALE1ISNXS,    HFGITR, TLBIRVAALE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVALE1ISNXS,     HFGITR, TLBIRVALE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAAE1ISNXS,     HFGITR, TLBIRVAAE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAE1ISNXS,      HFGITR, TLBIRVAE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAALE1ISNXS,     HFGITR, TLBIVAALE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VALE1ISNXS,      HFGITR, TLBIVALE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAAE1ISNXS,      HFGITR, TLBIVAAE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_ASIDE1ISNXS,     HFGITR, TLBIASIDE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAE1ISNXS,       HFGITR, TLBIVAE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VMALLE1ISNXS,    HFGITR, TLBIVMALLE1IS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAALE1OSNXS,    HFGITR, TLBIRVAALE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVALE1OSNXS,     HFGITR, TLBIRVALE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAAE1OSNXS,     HFGITR, TLBIRVAAE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_RVAE1OSNXS,      HFGITR, TLBIRVAE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAALE1OSNXS,     HFGITR, TLBIVAALE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VALE1OSNXS,      HFGITR, TLBIVALE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAAE1OSNXS,      HFGITR, TLBIVAAE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_ASIDE1OSNXS,     HFGITR, TLBIASIDE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VAE1OSNXS,       HFGITR, TLBIVAE1OS, 1, HCRX_FGTnXS),
> +       SR_FGF(OP_TLBI_VMALLE1OSNXS,    HFGITR, TLBIVMALLE1OS, 1, HCRX_FGTnXS),
>         SR_FGT(OP_AT_S1E1WP,            HFGITR, ATS1E1WP, 1),
>         SR_FGT(OP_AT_S1E1RP,            HFGITR, ATS1E1RP, 1),
>         SR_FGT(OP_AT_S1E0W,             HFGITR, ATS1E0W, 1),
> @@ -1622,6 +1636,7 @@ int __init populate_nv_trap_config(void)
>         BUILD_BUG_ON(sizeof(union trap_config) != sizeof(void *));
>         BUILD_BUG_ON(__NR_CGT_GROUP_IDS__ > BIT(TC_CGT_BITS));
>         BUILD_BUG_ON(__NR_FGT_GROUP_IDS__ > BIT(TC_FGT_BITS));
> +       BUILD_BUG_ON(__NR_FG_FILTER_IDS__ > BIT(TC_FGF_BITS));
>
>         for (int i = 0; i < ARRAY_SIZE(encoding_to_cgt); i++) {
>                 const struct encoding_to_trap_config *cgt = &encoding_to_cgt[i];
> @@ -1812,6 +1827,17 @@ bool __check_nv_sr_forward(struct kvm_vcpu *vcpu)
>
>         case HFGITR_GROUP:
>                 val = sanitised_sys_reg(vcpu, HFGITR_EL2);
> +               switch (tc.fgf) {
> +                       u64 tmp;
> +
> +               case __NO_FGF__:
> +                       break;
> +
> +               case HCRX_FGTnXS:
> +                       tmp = sanitised_sys_reg(vcpu, HCRX_EL2);
> +                       if (tmp & HCRX_EL2_FGTnXS)
> +                               tc.fgt = __NO_FGT_GROUP__;
> +               }
>                 break;
>
>         case __NR_FGT_GROUP_IDS__:
> diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
> index 060c5a0409e5..3acf6d77e324 100644
> --- a/arch/arm64/kvm/hyp/include/hyp/switch.h
> +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
> @@ -197,8 +197,19 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
>         vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2);
>         write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
>
> -       if (cpus_have_final_cap(ARM64_HAS_HCX))
> -               write_sysreg_s(HCRX_GUEST_FLAGS, SYS_HCRX_EL2);
> +       if (cpus_have_final_cap(ARM64_HAS_HCX)) {
> +               u64 hcrx = HCRX_GUEST_FLAGS;
> +               if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
> +                       u64 clr = 0, set = 0;
> +
> +                       compute_clr_set(vcpu, HCRX_EL2, clr, set);
> +
> +                       hcrx |= set;
> +                       hcrx &= ~clr;
> +               }
> +
> +               write_sysreg_s(hcrx, SYS_HCRX_EL2);
> +       }
>
>         __activate_traps_hfgxtr(vcpu);
>  }
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 3facd8918ae3..042695a210ce 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -117,7 +117,8 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
>                 break;
>
>         case SYS_ID_AA64MMFR1_EL1:
> -               val &= (NV_FTR(MMFR1, PAN)      |
> +               val &= (NV_FTR(MMFR1, HCX)      |
> +                       NV_FTR(MMFR1, PAN)      |
>                         NV_FTR(MMFR1, LO)       |
>                         NV_FTR(MMFR1, HPDS)     |
>                         NV_FTR(MMFR1, VH)       |
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 9556896311db..e92ec810d449 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -2372,6 +2372,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>         EL2_REG(HFGITR_EL2, access_rw, reset_val, 0),
>         EL2_REG(HACR_EL2, access_rw, reset_val, 0),
>
> +       EL2_REG(HCRX_EL2, access_rw, reset_val, 0),
> +
>         EL2_REG(TTBR0_EL2, access_rw, reset_val, 0),
>         EL2_REG(TTBR1_EL2, access_rw, reset_val, 0),
>         EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1),
> --
> 2.34.1
>

Reviewed-by: Jing Zhang <jingzhangos at google.com>

Jing



More information about the linux-arm-kernel mailing list