diff options
| -rw-r--r-- | arch/arm64/kvm/pmu.c | 84 |
1 files changed, 74 insertions, 10 deletions
diff --git a/arch/arm64/kvm/pmu.c b/arch/arm64/kvm/pmu.c index 3f99a095a1ff..cd49db845ef4 100644 --- a/arch/arm64/kvm/pmu.c +++ b/arch/arm64/kvm/pmu.c | |||
| @@ -91,6 +91,74 @@ void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt) | |||
| 91 | write_sysreg(pmu->events_host, pmcntenset_el0); | 91 | write_sysreg(pmu->events_host, pmcntenset_el0); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | #define PMEVTYPER_READ_CASE(idx) \ | ||
| 95 | case idx: \ | ||
| 96 | return read_sysreg(pmevtyper##idx##_el0) | ||
| 97 | |||
| 98 | #define PMEVTYPER_WRITE_CASE(idx) \ | ||
| 99 | case idx: \ | ||
| 100 | write_sysreg(val, pmevtyper##idx##_el0); \ | ||
| 101 | break | ||
| 102 | |||
| 103 | #define PMEVTYPER_CASES(readwrite) \ | ||
| 104 | PMEVTYPER_##readwrite##_CASE(0); \ | ||
| 105 | PMEVTYPER_##readwrite##_CASE(1); \ | ||
| 106 | PMEVTYPER_##readwrite##_CASE(2); \ | ||
| 107 | PMEVTYPER_##readwrite##_CASE(3); \ | ||
| 108 | PMEVTYPER_##readwrite##_CASE(4); \ | ||
| 109 | PMEVTYPER_##readwrite##_CASE(5); \ | ||
| 110 | PMEVTYPER_##readwrite##_CASE(6); \ | ||
| 111 | PMEVTYPER_##readwrite##_CASE(7); \ | ||
| 112 | PMEVTYPER_##readwrite##_CASE(8); \ | ||
| 113 | PMEVTYPER_##readwrite##_CASE(9); \ | ||
| 114 | PMEVTYPER_##readwrite##_CASE(10); \ | ||
| 115 | PMEVTYPER_##readwrite##_CASE(11); \ | ||
| 116 | PMEVTYPER_##readwrite##_CASE(12); \ | ||
| 117 | PMEVTYPER_##readwrite##_CASE(13); \ | ||
| 118 | PMEVTYPER_##readwrite##_CASE(14); \ | ||
| 119 | PMEVTYPER_##readwrite##_CASE(15); \ | ||
| 120 | PMEVTYPER_##readwrite##_CASE(16); \ | ||
| 121 | PMEVTYPER_##readwrite##_CASE(17); \ | ||
| 122 | PMEVTYPER_##readwrite##_CASE(18); \ | ||
| 123 | PMEVTYPER_##readwrite##_CASE(19); \ | ||
| 124 | PMEVTYPER_##readwrite##_CASE(20); \ | ||
| 125 | PMEVTYPER_##readwrite##_CASE(21); \ | ||
| 126 | PMEVTYPER_##readwrite##_CASE(22); \ | ||
| 127 | PMEVTYPER_##readwrite##_CASE(23); \ | ||
| 128 | PMEVTYPER_##readwrite##_CASE(24); \ | ||
| 129 | PMEVTYPER_##readwrite##_CASE(25); \ | ||
| 130 | PMEVTYPER_##readwrite##_CASE(26); \ | ||
| 131 | PMEVTYPER_##readwrite##_CASE(27); \ | ||
| 132 | PMEVTYPER_##readwrite##_CASE(28); \ | ||
| 133 | PMEVTYPER_##readwrite##_CASE(29); \ | ||
| 134 | PMEVTYPER_##readwrite##_CASE(30) | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Read a value direct from PMEVTYPER<idx> | ||
| 138 | */ | ||
| 139 | static u64 kvm_vcpu_pmu_read_evtype_direct(int idx) | ||
| 140 | { | ||
| 141 | switch (idx) { | ||
| 142 | PMEVTYPER_CASES(READ); | ||
| 143 | default: | ||
| 144 | WARN_ON(1); | ||
| 145 | } | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | /* | ||
| 151 | * Write a value direct to PMEVTYPER<idx> | ||
| 152 | */ | ||
| 153 | static void kvm_vcpu_pmu_write_evtype_direct(int idx, u32 val) | ||
| 154 | { | ||
| 155 | switch (idx) { | ||
| 156 | PMEVTYPER_CASES(WRITE); | ||
| 157 | default: | ||
| 158 | WARN_ON(1); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 94 | /* | 162 | /* |
| 95 | * Modify ARMv8 PMU events to include EL0 counting | 163 | * Modify ARMv8 PMU events to include EL0 counting |
| 96 | */ | 164 | */ |
| @@ -100,11 +168,9 @@ static void kvm_vcpu_pmu_enable_el0(unsigned long events) | |||
| 100 | u32 counter; | 168 | u32 counter; |
| 101 | 169 | ||
| 102 | for_each_set_bit(counter, &events, 32) { | 170 | for_each_set_bit(counter, &events, 32) { |
| 103 | write_sysreg(counter, pmselr_el0); | 171 | typer = kvm_vcpu_pmu_read_evtype_direct(counter); |
| 104 | isb(); | 172 | typer &= ~ARMV8_PMU_EXCLUDE_EL0; |
| 105 | typer = read_sysreg(pmxevtyper_el0) & ~ARMV8_PMU_EXCLUDE_EL0; | 173 | kvm_vcpu_pmu_write_evtype_direct(counter, typer); |
| 106 | write_sysreg(typer, pmxevtyper_el0); | ||
| 107 | isb(); | ||
| 108 | } | 174 | } |
| 109 | } | 175 | } |
| 110 | 176 | ||
| @@ -117,11 +183,9 @@ static void kvm_vcpu_pmu_disable_el0(unsigned long events) | |||
| 117 | u32 counter; | 183 | u32 counter; |
| 118 | 184 | ||
| 119 | for_each_set_bit(counter, &events, 32) { | 185 | for_each_set_bit(counter, &events, 32) { |
| 120 | write_sysreg(counter, pmselr_el0); | 186 | typer = kvm_vcpu_pmu_read_evtype_direct(counter); |
| 121 | isb(); | 187 | typer |= ARMV8_PMU_EXCLUDE_EL0; |
| 122 | typer = read_sysreg(pmxevtyper_el0) | ARMV8_PMU_EXCLUDE_EL0; | 188 | kvm_vcpu_pmu_write_evtype_direct(counter, typer); |
| 123 | write_sysreg(typer, pmxevtyper_el0); | ||
| 124 | isb(); | ||
| 125 | } | 189 | } |
| 126 | } | 190 | } |
| 127 | 191 | ||
