val = read_sysreg(cpacr_el1);
        val |= CPACR_EL1_TTA;
        val &= ~CPACR_EL1_ZEN;
+
+       /*
+        * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to
+        * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2,
+        * except for some missing controls, such as TAM.
+        * In this case, CPTR_EL2.TAM has the same position with or without
+        * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM
+        * shift value for trapping the AMU accesses.
+        */
+
+       val |= CPTR_EL2_TAM;
+
        if (update_fp_enabled(vcpu)) {
                if (vcpu_has_sve(vcpu))
                        val |= CPACR_EL1_ZEN;
        __activate_traps_common(vcpu);
 
        val = CPTR_EL2_DEFAULT;
-       val |= CPTR_EL2_TTA | CPTR_EL2_TZ;
+       val |= CPTR_EL2_TTA | CPTR_EL2_TZ | CPTR_EL2_TAM;
        if (!update_fp_enabled(vcpu)) {
                val |= CPTR_EL2_TFP;
                __activate_traps_fpsimd32(vcpu);
 
        { SYS_DESC(SYS_PMEVTYPERn_EL0(n)),                                      \
          access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
 
+static bool access_amu(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                            const struct sys_reg_desc *r)
+{
+       kvm_inject_undefined(vcpu);
+
+       return false;
+}
+
+/* Macro to expand the AMU counter and type registers*/
+#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), access_amu }
+#define AMU_AMEVTYPE0_EL0(n) { SYS_DESC(SYS_AMEVTYPE0_EL0(n)), access_amu }
+#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), access_amu }
+#define AMU_AMEVTYPE1_EL0(n) { SYS_DESC(SYS_AMEVTYPE1_EL0(n)), access_amu }
+
 static bool trap_ptrauth(struct kvm_vcpu *vcpu,
                         struct sys_reg_params *p,
                         const struct sys_reg_desc *rd)
                         (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
        u64 val = raz ? 0 : read_sanitised_ftr_reg(id);
 
-       if (id == SYS_ID_AA64PFR0_EL1 && !vcpu_has_sve(vcpu)) {
-               val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
+       if (id == SYS_ID_AA64PFR0_EL1) {
+               if (!vcpu_has_sve(vcpu))
+                       val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
+               val &= ~(0xfUL << ID_AA64PFR0_AMU_SHIFT);
        } else if (id == SYS_ID_AA64ISAR1_EL1 && !vcpu_has_ptrauth(vcpu)) {
                val &= ~((0xfUL << ID_AA64ISAR1_APA_SHIFT) |
                         (0xfUL << ID_AA64ISAR1_API_SHIFT) |
        { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
        { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
 
+       { SYS_DESC(SYS_AMCR_EL0), access_amu },
+       { SYS_DESC(SYS_AMCFGR_EL0), access_amu },
+       { SYS_DESC(SYS_AMCGCR_EL0), access_amu },
+       { SYS_DESC(SYS_AMUSERENR_EL0), access_amu },
+       { SYS_DESC(SYS_AMCNTENCLR0_EL0), access_amu },
+       { SYS_DESC(SYS_AMCNTENSET0_EL0), access_amu },
+       { SYS_DESC(SYS_AMCNTENCLR1_EL0), access_amu },
+       { SYS_DESC(SYS_AMCNTENSET1_EL0), access_amu },
+       AMU_AMEVCNTR0_EL0(0),
+       AMU_AMEVCNTR0_EL0(1),
+       AMU_AMEVCNTR0_EL0(2),
+       AMU_AMEVCNTR0_EL0(3),
+       AMU_AMEVCNTR0_EL0(4),
+       AMU_AMEVCNTR0_EL0(5),
+       AMU_AMEVCNTR0_EL0(6),
+       AMU_AMEVCNTR0_EL0(7),
+       AMU_AMEVCNTR0_EL0(8),
+       AMU_AMEVCNTR0_EL0(9),
+       AMU_AMEVCNTR0_EL0(10),
+       AMU_AMEVCNTR0_EL0(11),
+       AMU_AMEVCNTR0_EL0(12),
+       AMU_AMEVCNTR0_EL0(13),
+       AMU_AMEVCNTR0_EL0(14),
+       AMU_AMEVCNTR0_EL0(15),
+       AMU_AMEVTYPE0_EL0(0),
+       AMU_AMEVTYPE0_EL0(1),
+       AMU_AMEVTYPE0_EL0(2),
+       AMU_AMEVTYPE0_EL0(3),
+       AMU_AMEVTYPE0_EL0(4),
+       AMU_AMEVTYPE0_EL0(5),
+       AMU_AMEVTYPE0_EL0(6),
+       AMU_AMEVTYPE0_EL0(7),
+       AMU_AMEVTYPE0_EL0(8),
+       AMU_AMEVTYPE0_EL0(9),
+       AMU_AMEVTYPE0_EL0(10),
+       AMU_AMEVTYPE0_EL0(11),
+       AMU_AMEVTYPE0_EL0(12),
+       AMU_AMEVTYPE0_EL0(13),
+       AMU_AMEVTYPE0_EL0(14),
+       AMU_AMEVTYPE0_EL0(15),
+       AMU_AMEVCNTR1_EL0(0),
+       AMU_AMEVCNTR1_EL0(1),
+       AMU_AMEVCNTR1_EL0(2),
+       AMU_AMEVCNTR1_EL0(3),
+       AMU_AMEVCNTR1_EL0(4),
+       AMU_AMEVCNTR1_EL0(5),
+       AMU_AMEVCNTR1_EL0(6),
+       AMU_AMEVCNTR1_EL0(7),
+       AMU_AMEVCNTR1_EL0(8),
+       AMU_AMEVCNTR1_EL0(9),
+       AMU_AMEVCNTR1_EL0(10),
+       AMU_AMEVCNTR1_EL0(11),
+       AMU_AMEVCNTR1_EL0(12),
+       AMU_AMEVCNTR1_EL0(13),
+       AMU_AMEVCNTR1_EL0(14),
+       AMU_AMEVCNTR1_EL0(15),
+       AMU_AMEVTYPE1_EL0(0),
+       AMU_AMEVTYPE1_EL0(1),
+       AMU_AMEVTYPE1_EL0(2),
+       AMU_AMEVTYPE1_EL0(3),
+       AMU_AMEVTYPE1_EL0(4),
+       AMU_AMEVTYPE1_EL0(5),
+       AMU_AMEVTYPE1_EL0(6),
+       AMU_AMEVTYPE1_EL0(7),
+       AMU_AMEVTYPE1_EL0(8),
+       AMU_AMEVTYPE1_EL0(9),
+       AMU_AMEVTYPE1_EL0(10),
+       AMU_AMEVTYPE1_EL0(11),
+       AMU_AMEVTYPE1_EL0(12),
+       AMU_AMEVTYPE1_EL0(13),
+       AMU_AMEVTYPE1_EL0(14),
+       AMU_AMEVTYPE1_EL0(15),
+
        { SYS_DESC(SYS_CNTP_TVAL_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTP_CTL_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTP_CVAL_EL0), access_arch_timer },