KVM: arm64: Add handling of AArch32 PCMEID{2,3} PMUv3 registers
authorMarc Zyngier <maz@kernel.org>
Thu, 31 Dec 2020 11:39:01 +0000 (11:39 +0000)
committerMarc Zyngier <maz@kernel.org>
Wed, 3 Feb 2021 10:59:26 +0000 (10:59 +0000)
Despite advertising support for AArch32 PMUv3p1, we fail to handle
the PMCEID{2,3} registers, which conveniently alias with the top
bits of PMCEID{0,1}_EL1.

Implement these registers with the usual AA32(HI/LO) aliasing
mechanism.

Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/sys_regs.c

index ce08d28..2bea049 100644 (file)
@@ -685,14 +685,18 @@ static bool access_pmselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 static bool access_pmceid(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
                          const struct sys_reg_desc *r)
 {
-       u64 pmceid;
+       u64 pmceid, mask, shift;
 
        BUG_ON(p->is_write);
 
        if (pmu_access_el0_disabled(vcpu))
                return false;
 
+       get_access_mask(r, &mask, &shift);
+
        pmceid = kvm_pmu_get_pmceid(vcpu, (p->Op2 & 1));
+       pmceid &= mask;
+       pmceid >>= shift;
 
        p->regval = pmceid;
 
@@ -1895,8 +1899,8 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn( 9), CRm(12), Op2( 3), access_pmovs },
        { Op1( 0), CRn( 9), CRm(12), Op2( 4), access_pmswinc },
        { Op1( 0), CRn( 9), CRm(12), Op2( 5), access_pmselr },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 6), access_pmceid },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 7), access_pmceid },
+       { AA32(LO), Op1( 0), CRn( 9), CRm(12), Op2( 6), access_pmceid },
+       { AA32(LO), Op1( 0), CRn( 9), CRm(12), Op2( 7), access_pmceid },
        { Op1( 0), CRn( 9), CRm(13), Op2( 0), access_pmu_evcntr },
        { Op1( 0), CRn( 9), CRm(13), Op2( 1), access_pmu_evtyper },
        { Op1( 0), CRn( 9), CRm(13), Op2( 2), access_pmu_evcntr },
@@ -1904,6 +1908,8 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn( 9), CRm(14), Op2( 1), access_pminten },
        { Op1( 0), CRn( 9), CRm(14), Op2( 2), access_pminten },
        { Op1( 0), CRn( 9), CRm(14), Op2( 3), access_pmovs },
+       { AA32(HI), Op1( 0), CRn( 9), CRm(14), Op2( 4), access_pmceid },
+       { AA32(HI), Op1( 0), CRn( 9), CRm(14), Op2( 5), access_pmceid },
 
        /* PRRR/MAIR0 */
        { AA32(LO), Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, MAIR_EL1 },