KVM: arm64: Handle HAFGRTR_EL2 trapping in nested virt
authorFuad Tabba <tabba@google.com>
Thu, 14 Dec 2023 10:01:49 +0000 (10:01 +0000)
committerMarc Zyngier <maz@kernel.org>
Mon, 18 Dec 2023 11:25:50 +0000 (11:25 +0000)
Add the encodings to fine grain trapping fields for HAFGRTR_EL2
and add the associated handling code in nested virt. Based on
DDI0601 2023-09. Add the missing field definitions as well,
both to generate the correct RES0 mask and to be able to toggle
their FGT bits.

Also add the code for handling FGT trapping, reading of the
register, to nested virt.

Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20231214100158.2305400-10-tabba@google.com
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/emulate-nested.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/sys_regs.c

index 824f29f04916af028783d8914fdc311c41597c10..ba14648e2de25945806bded615d6c1e61d7b015e 100644 (file)
@@ -443,6 +443,7 @@ enum vcpu_sysreg {
        HFGITR_EL2,
        HDFGRTR_EL2,
        HDFGWTR_EL2,
+       HAFGRTR_EL2,
        CNTHP_CTL_EL2,
        CNTHP_CVAL_EL2,
        CNTHV_CTL_EL2,
index 89901550db342f320d2fb9514ecbe890d1da745b..431fd429932dfaa557ac0977fbbc3baa58eef99d 100644 (file)
@@ -1012,6 +1012,7 @@ enum fgt_group_id {
        HDFGRTR_GROUP,
        HDFGWTR_GROUP,
        HFGITR_GROUP,
+       HAFGRTR_GROUP,
 
        /* Must be last */
        __NR_FGT_GROUP_IDS__
@@ -1689,6 +1690,49 @@ static const struct encoding_to_trap_config encoding_to_fgt[] __initconst = {
        SR_FGT(SYS_PMCR_EL0,            HDFGWTR, PMCR_EL0, 1),
        SR_FGT(SYS_PMSWINC_EL0,         HDFGWTR, PMSWINC_EL0, 1),
        SR_FGT(SYS_OSLAR_EL1,           HDFGWTR, OSLAR_EL1, 1),
+       /*
+        * HAFGRTR_EL2
+        */
+       SR_FGT(SYS_AMEVTYPER1_EL0(15),  HAFGRTR, AMEVTYPER115_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(14),  HAFGRTR, AMEVTYPER114_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(13),  HAFGRTR, AMEVTYPER113_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(12),  HAFGRTR, AMEVTYPER112_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(11),  HAFGRTR, AMEVTYPER111_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(10),  HAFGRTR, AMEVTYPER110_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(9),   HAFGRTR, AMEVTYPER19_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(8),   HAFGRTR, AMEVTYPER18_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(7),   HAFGRTR, AMEVTYPER17_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(6),   HAFGRTR, AMEVTYPER16_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(5),   HAFGRTR, AMEVTYPER15_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(4),   HAFGRTR, AMEVTYPER14_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(3),   HAFGRTR, AMEVTYPER13_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(2),   HAFGRTR, AMEVTYPER12_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(1),   HAFGRTR, AMEVTYPER11_EL0, 1),
+       SR_FGT(SYS_AMEVTYPER1_EL0(0),   HAFGRTR, AMEVTYPER10_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(15),   HAFGRTR, AMEVCNTR115_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(14),   HAFGRTR, AMEVCNTR114_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(13),   HAFGRTR, AMEVCNTR113_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(12),   HAFGRTR, AMEVCNTR112_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(11),   HAFGRTR, AMEVCNTR111_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(10),   HAFGRTR, AMEVCNTR110_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(9),    HAFGRTR, AMEVCNTR19_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(8),    HAFGRTR, AMEVCNTR18_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(7),    HAFGRTR, AMEVCNTR17_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(6),    HAFGRTR, AMEVCNTR16_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(5),    HAFGRTR, AMEVCNTR15_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(4),    HAFGRTR, AMEVCNTR14_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(3),    HAFGRTR, AMEVCNTR13_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(2),    HAFGRTR, AMEVCNTR12_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(1),    HAFGRTR, AMEVCNTR11_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR1_EL0(0),    HAFGRTR, AMEVCNTR10_EL0, 1),
+       SR_FGT(SYS_AMCNTENCLR1_EL0,     HAFGRTR, AMCNTEN1, 1),
+       SR_FGT(SYS_AMCNTENSET1_EL0,     HAFGRTR, AMCNTEN1, 1),
+       SR_FGT(SYS_AMCNTENCLR0_EL0,     HAFGRTR, AMCNTEN0, 1),
+       SR_FGT(SYS_AMCNTENSET0_EL0,     HAFGRTR, AMCNTEN0, 1),
+       SR_FGT(SYS_AMEVCNTR0_EL0(3),    HAFGRTR, AMEVCNTR03_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR0_EL0(2),    HAFGRTR, AMEVCNTR02_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR0_EL0(1),    HAFGRTR, AMEVCNTR01_EL0, 1),
+       SR_FGT(SYS_AMEVCNTR0_EL0(0),    HAFGRTR, AMEVCNTR00_EL0, 1),
 };
 
 static union trap_config get_trap_config(u32 sysreg)
@@ -1909,6 +1953,10 @@ bool __check_nv_sr_forward(struct kvm_vcpu *vcpu)
                        val = sanitised_sys_reg(vcpu, HDFGWTR_EL2);
                break;
 
+       case HAFGRTR_GROUP:
+               val = sanitised_sys_reg(vcpu, HAFGRTR_EL2);
+               break;
+
        case HFGITR_GROUP:
                val = sanitised_sys_reg(vcpu, HFGITR_EL2);
                switch (tc.fgf) {
index 7b4909dfd1f5675fb5eb85187206f95675cfba26..0436f0da98a42e37da8362c442a6dc3836cd7c0a 100644 (file)
@@ -80,6 +80,14 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
        } while(0)
 
 
+static inline bool cpu_has_amu(void)
+{
+       u64 pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1);
+
+       return cpuid_feature_extract_unsigned_field(pfr0,
+               ID_AA64PFR0_EL1_AMU_SHIFT);
+}
+
 static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpu_context *hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
@@ -156,6 +164,20 @@ static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
 
        write_sysreg_s(r_val, SYS_HDFGRTR_EL2);
        write_sysreg_s(w_val, SYS_HDFGWTR_EL2);
+
+       if (!cpu_has_amu())
+               return;
+
+       ctxt_sys_reg(hctxt, HAFGRTR_EL2) = read_sysreg_s(SYS_HAFGRTR_EL2);
+
+       r_clr = r_set = 0;
+       compute_clr_set(vcpu, HAFGRTR_EL2, r_clr, r_set);
+
+       r_val = __HAFGRTR_EL2_nMASK;
+       r_val |= r_set;
+       r_val &= ~r_clr;
+
+       write_sysreg_s(r_val, SYS_HAFGRTR_EL2);
 }
 
 static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
@@ -174,6 +196,9 @@ static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
        write_sysreg_s(ctxt_sys_reg(hctxt, HFGITR_EL2), SYS_HFGITR_EL2);
        write_sysreg_s(ctxt_sys_reg(hctxt, HDFGRTR_EL2), SYS_HDFGRTR_EL2);
        write_sysreg_s(ctxt_sys_reg(hctxt, HDFGWTR_EL2), SYS_HDFGWTR_EL2);
+
+       if (vcpu_has_amu())
+               write_sysreg_s(ctxt_sys_reg(hctxt, HAFGRTR_EL2), SYS_HAFGRTR_EL2);
 }
 
 static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
index 4735e1b37fb3e08afd9825ae4e9ebad953605937..8bb297a2df3882db4e8623b9dbd8e707637f28c9 100644 (file)
@@ -2532,6 +2532,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_DACR32_EL2), trap_undef, reset_unknown, DACR32_EL2 },
        EL2_REG(HDFGRTR_EL2, access_rw, reset_val, 0),
        EL2_REG(HDFGWTR_EL2, access_rw, reset_val, 0),
+       EL2_REG(HAFGRTR_EL2, access_rw, reset_val, 0),
        EL2_REG(SPSR_EL2, access_rw, reset_val, 0),
        EL2_REG(ELR_EL2, access_rw, reset_val, 0),
        { SYS_DESC(SYS_SP_EL1), access_sp_el1},