write_sysreg(pmu->events_host, pmcntenset_el0);
 }
 
+#define PMEVTYPER_READ_CASE(idx)                               \
+       case idx:                                               \
+               return read_sysreg(pmevtyper##idx##_el0)
+
+#define PMEVTYPER_WRITE_CASE(idx)                              \
+       case idx:                                               \
+               write_sysreg(val, pmevtyper##idx##_el0);        \
+               break
+
+#define PMEVTYPER_CASES(readwrite)                             \
+       PMEVTYPER_##readwrite##_CASE(0);                        \
+       PMEVTYPER_##readwrite##_CASE(1);                        \
+       PMEVTYPER_##readwrite##_CASE(2);                        \
+       PMEVTYPER_##readwrite##_CASE(3);                        \
+       PMEVTYPER_##readwrite##_CASE(4);                        \
+       PMEVTYPER_##readwrite##_CASE(5);                        \
+       PMEVTYPER_##readwrite##_CASE(6);                        \
+       PMEVTYPER_##readwrite##_CASE(7);                        \
+       PMEVTYPER_##readwrite##_CASE(8);                        \
+       PMEVTYPER_##readwrite##_CASE(9);                        \
+       PMEVTYPER_##readwrite##_CASE(10);                       \
+       PMEVTYPER_##readwrite##_CASE(11);                       \
+       PMEVTYPER_##readwrite##_CASE(12);                       \
+       PMEVTYPER_##readwrite##_CASE(13);                       \
+       PMEVTYPER_##readwrite##_CASE(14);                       \
+       PMEVTYPER_##readwrite##_CASE(15);                       \
+       PMEVTYPER_##readwrite##_CASE(16);                       \
+       PMEVTYPER_##readwrite##_CASE(17);                       \
+       PMEVTYPER_##readwrite##_CASE(18);                       \
+       PMEVTYPER_##readwrite##_CASE(19);                       \
+       PMEVTYPER_##readwrite##_CASE(20);                       \
+       PMEVTYPER_##readwrite##_CASE(21);                       \
+       PMEVTYPER_##readwrite##_CASE(22);                       \
+       PMEVTYPER_##readwrite##_CASE(23);                       \
+       PMEVTYPER_##readwrite##_CASE(24);                       \
+       PMEVTYPER_##readwrite##_CASE(25);                       \
+       PMEVTYPER_##readwrite##_CASE(26);                       \
+       PMEVTYPER_##readwrite##_CASE(27);                       \
+       PMEVTYPER_##readwrite##_CASE(28);                       \
+       PMEVTYPER_##readwrite##_CASE(29);                       \
+       PMEVTYPER_##readwrite##_CASE(30)
+
+/*
+ * Read a value direct from PMEVTYPER<idx>
+ */
+static u64 kvm_vcpu_pmu_read_evtype_direct(int idx)
+{
+       switch (idx) {
+       PMEVTYPER_CASES(READ);
+       default:
+               WARN_ON(1);
+       }
+
+       return 0;
+}
+
+/*
+ * Write a value direct to PMEVTYPER<idx>
+ */
+static void kvm_vcpu_pmu_write_evtype_direct(int idx, u32 val)
+{
+       switch (idx) {
+       PMEVTYPER_CASES(WRITE);
+       default:
+               WARN_ON(1);
+       }
+}
+
 /*
  * Modify ARMv8 PMU events to include EL0 counting
  */
        u32 counter;
 
        for_each_set_bit(counter, &events, 32) {
-               write_sysreg(counter, pmselr_el0);
-               isb();
-               typer = read_sysreg(pmxevtyper_el0) & ~ARMV8_PMU_EXCLUDE_EL0;
-               write_sysreg(typer, pmxevtyper_el0);
-               isb();
+               typer = kvm_vcpu_pmu_read_evtype_direct(counter);
+               typer &= ~ARMV8_PMU_EXCLUDE_EL0;
+               kvm_vcpu_pmu_write_evtype_direct(counter, typer);
        }
 }
 
        u32 counter;
 
        for_each_set_bit(counter, &events, 32) {
-               write_sysreg(counter, pmselr_el0);
-               isb();
-               typer = read_sysreg(pmxevtyper_el0) | ARMV8_PMU_EXCLUDE_EL0;
-               write_sysreg(typer, pmxevtyper_el0);
-               isb();
+               typer = kvm_vcpu_pmu_read_evtype_direct(counter);
+               typer |= ARMV8_PMU_EXCLUDE_EL0;
+               kvm_vcpu_pmu_write_evtype_direct(counter, typer);
        }
 }