1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/types.h>
3*4882a593Smuzhiyun #include <linux/interrupt.h>
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <asm/xen/hypercall.h>
6*4882a593Smuzhiyun #include <xen/xen.h>
7*4882a593Smuzhiyun #include <xen/page.h>
8*4882a593Smuzhiyun #include <xen/interface/xen.h>
9*4882a593Smuzhiyun #include <xen/interface/vcpu.h>
10*4882a593Smuzhiyun #include <xen/interface/xenpmu.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "xen-ops.h"
13*4882a593Smuzhiyun #include "pmu.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /* x86_pmu.handle_irq definition */
16*4882a593Smuzhiyun #include "../events/perf_event.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #define XENPMU_IRQ_PROCESSING 1
19*4882a593Smuzhiyun struct xenpmu {
20*4882a593Smuzhiyun /* Shared page between hypervisor and domain */
21*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun uint8_t flags;
24*4882a593Smuzhiyun };
25*4882a593Smuzhiyun static DEFINE_PER_CPU(struct xenpmu, xenpmu_shared);
26*4882a593Smuzhiyun #define get_xenpmu_data() (this_cpu_ptr(&xenpmu_shared)->xenpmu_data)
27*4882a593Smuzhiyun #define get_xenpmu_flags() (this_cpu_ptr(&xenpmu_shared)->flags)
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /* Macro for computing address of a PMU MSR bank */
30*4882a593Smuzhiyun #define field_offset(ctxt, field) ((void *)((uintptr_t)ctxt + \
31*4882a593Smuzhiyun (uintptr_t)ctxt->field))
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* AMD PMU */
34*4882a593Smuzhiyun #define F15H_NUM_COUNTERS 6
35*4882a593Smuzhiyun #define F10H_NUM_COUNTERS 4
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static __read_mostly uint32_t amd_counters_base;
38*4882a593Smuzhiyun static __read_mostly uint32_t amd_ctrls_base;
39*4882a593Smuzhiyun static __read_mostly int amd_msr_step;
40*4882a593Smuzhiyun static __read_mostly int k7_counters_mirrored;
41*4882a593Smuzhiyun static __read_mostly int amd_num_counters;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Intel PMU */
44*4882a593Smuzhiyun #define MSR_TYPE_COUNTER 0
45*4882a593Smuzhiyun #define MSR_TYPE_CTRL 1
46*4882a593Smuzhiyun #define MSR_TYPE_GLOBAL 2
47*4882a593Smuzhiyun #define MSR_TYPE_ARCH_COUNTER 3
48*4882a593Smuzhiyun #define MSR_TYPE_ARCH_CTRL 4
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* Number of general pmu registers (CPUID.EAX[0xa].EAX[8..15]) */
51*4882a593Smuzhiyun #define PMU_GENERAL_NR_SHIFT 8
52*4882a593Smuzhiyun #define PMU_GENERAL_NR_BITS 8
53*4882a593Smuzhiyun #define PMU_GENERAL_NR_MASK (((1 << PMU_GENERAL_NR_BITS) - 1) \
54*4882a593Smuzhiyun << PMU_GENERAL_NR_SHIFT)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Number of fixed pmu registers (CPUID.EDX[0xa].EDX[0..4]) */
57*4882a593Smuzhiyun #define PMU_FIXED_NR_SHIFT 0
58*4882a593Smuzhiyun #define PMU_FIXED_NR_BITS 5
59*4882a593Smuzhiyun #define PMU_FIXED_NR_MASK (((1 << PMU_FIXED_NR_BITS) - 1) \
60*4882a593Smuzhiyun << PMU_FIXED_NR_SHIFT)
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* Alias registers (0x4c1) for full-width writes to PMCs */
63*4882a593Smuzhiyun #define MSR_PMC_ALIAS_MASK (~(MSR_IA32_PERFCTR0 ^ MSR_IA32_PMC0))
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define INTEL_PMC_TYPE_SHIFT 30
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun static __read_mostly int intel_num_arch_counters, intel_num_fixed_counters;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun
xen_pmu_arch_init(void)70*4882a593Smuzhiyun static void xen_pmu_arch_init(void)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun switch (boot_cpu_data.x86) {
75*4882a593Smuzhiyun case 0x15:
76*4882a593Smuzhiyun amd_num_counters = F15H_NUM_COUNTERS;
77*4882a593Smuzhiyun amd_counters_base = MSR_F15H_PERF_CTR;
78*4882a593Smuzhiyun amd_ctrls_base = MSR_F15H_PERF_CTL;
79*4882a593Smuzhiyun amd_msr_step = 2;
80*4882a593Smuzhiyun k7_counters_mirrored = 1;
81*4882a593Smuzhiyun break;
82*4882a593Smuzhiyun case 0x10:
83*4882a593Smuzhiyun case 0x12:
84*4882a593Smuzhiyun case 0x14:
85*4882a593Smuzhiyun case 0x16:
86*4882a593Smuzhiyun default:
87*4882a593Smuzhiyun amd_num_counters = F10H_NUM_COUNTERS;
88*4882a593Smuzhiyun amd_counters_base = MSR_K7_PERFCTR0;
89*4882a593Smuzhiyun amd_ctrls_base = MSR_K7_EVNTSEL0;
90*4882a593Smuzhiyun amd_msr_step = 1;
91*4882a593Smuzhiyun k7_counters_mirrored = 0;
92*4882a593Smuzhiyun break;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
95*4882a593Smuzhiyun amd_num_counters = F10H_NUM_COUNTERS;
96*4882a593Smuzhiyun amd_counters_base = MSR_K7_PERFCTR0;
97*4882a593Smuzhiyun amd_ctrls_base = MSR_K7_EVNTSEL0;
98*4882a593Smuzhiyun amd_msr_step = 1;
99*4882a593Smuzhiyun k7_counters_mirrored = 0;
100*4882a593Smuzhiyun } else {
101*4882a593Smuzhiyun uint32_t eax, ebx, ecx, edx;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun cpuid(0xa, &eax, &ebx, &ecx, &edx);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun intel_num_arch_counters = (eax & PMU_GENERAL_NR_MASK) >>
106*4882a593Smuzhiyun PMU_GENERAL_NR_SHIFT;
107*4882a593Smuzhiyun intel_num_fixed_counters = (edx & PMU_FIXED_NR_MASK) >>
108*4882a593Smuzhiyun PMU_FIXED_NR_SHIFT;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
get_fam15h_addr(u32 addr)112*4882a593Smuzhiyun static inline uint32_t get_fam15h_addr(u32 addr)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun switch (addr) {
115*4882a593Smuzhiyun case MSR_K7_PERFCTR0:
116*4882a593Smuzhiyun case MSR_K7_PERFCTR1:
117*4882a593Smuzhiyun case MSR_K7_PERFCTR2:
118*4882a593Smuzhiyun case MSR_K7_PERFCTR3:
119*4882a593Smuzhiyun return MSR_F15H_PERF_CTR + (addr - MSR_K7_PERFCTR0);
120*4882a593Smuzhiyun case MSR_K7_EVNTSEL0:
121*4882a593Smuzhiyun case MSR_K7_EVNTSEL1:
122*4882a593Smuzhiyun case MSR_K7_EVNTSEL2:
123*4882a593Smuzhiyun case MSR_K7_EVNTSEL3:
124*4882a593Smuzhiyun return MSR_F15H_PERF_CTL + (addr - MSR_K7_EVNTSEL0);
125*4882a593Smuzhiyun default:
126*4882a593Smuzhiyun break;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun return addr;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
is_amd_pmu_msr(unsigned int msr)132*4882a593Smuzhiyun static inline bool is_amd_pmu_msr(unsigned int msr)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun if ((msr >= MSR_F15H_PERF_CTL &&
135*4882a593Smuzhiyun msr < MSR_F15H_PERF_CTR + (amd_num_counters * 2)) ||
136*4882a593Smuzhiyun (msr >= MSR_K7_EVNTSEL0 &&
137*4882a593Smuzhiyun msr < MSR_K7_PERFCTR0 + amd_num_counters))
138*4882a593Smuzhiyun return true;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return false;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
is_intel_pmu_msr(u32 msr_index,int * type,int * index)143*4882a593Smuzhiyun static int is_intel_pmu_msr(u32 msr_index, int *type, int *index)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun u32 msr_index_pmc;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun switch (msr_index) {
148*4882a593Smuzhiyun case MSR_CORE_PERF_FIXED_CTR_CTRL:
149*4882a593Smuzhiyun case MSR_IA32_DS_AREA:
150*4882a593Smuzhiyun case MSR_IA32_PEBS_ENABLE:
151*4882a593Smuzhiyun *type = MSR_TYPE_CTRL;
152*4882a593Smuzhiyun return true;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun case MSR_CORE_PERF_GLOBAL_CTRL:
155*4882a593Smuzhiyun case MSR_CORE_PERF_GLOBAL_STATUS:
156*4882a593Smuzhiyun case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
157*4882a593Smuzhiyun *type = MSR_TYPE_GLOBAL;
158*4882a593Smuzhiyun return true;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun default:
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if ((msr_index >= MSR_CORE_PERF_FIXED_CTR0) &&
163*4882a593Smuzhiyun (msr_index < MSR_CORE_PERF_FIXED_CTR0 +
164*4882a593Smuzhiyun intel_num_fixed_counters)) {
165*4882a593Smuzhiyun *index = msr_index - MSR_CORE_PERF_FIXED_CTR0;
166*4882a593Smuzhiyun *type = MSR_TYPE_COUNTER;
167*4882a593Smuzhiyun return true;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun if ((msr_index >= MSR_P6_EVNTSEL0) &&
171*4882a593Smuzhiyun (msr_index < MSR_P6_EVNTSEL0 + intel_num_arch_counters)) {
172*4882a593Smuzhiyun *index = msr_index - MSR_P6_EVNTSEL0;
173*4882a593Smuzhiyun *type = MSR_TYPE_ARCH_CTRL;
174*4882a593Smuzhiyun return true;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun msr_index_pmc = msr_index & MSR_PMC_ALIAS_MASK;
178*4882a593Smuzhiyun if ((msr_index_pmc >= MSR_IA32_PERFCTR0) &&
179*4882a593Smuzhiyun (msr_index_pmc < MSR_IA32_PERFCTR0 +
180*4882a593Smuzhiyun intel_num_arch_counters)) {
181*4882a593Smuzhiyun *type = MSR_TYPE_ARCH_COUNTER;
182*4882a593Smuzhiyun *index = msr_index_pmc - MSR_IA32_PERFCTR0;
183*4882a593Smuzhiyun return true;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun return false;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
xen_intel_pmu_emulate(unsigned int msr,u64 * val,int type,int index,bool is_read)189*4882a593Smuzhiyun static bool xen_intel_pmu_emulate(unsigned int msr, u64 *val, int type,
190*4882a593Smuzhiyun int index, bool is_read)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun uint64_t *reg = NULL;
193*4882a593Smuzhiyun struct xen_pmu_intel_ctxt *ctxt;
194*4882a593Smuzhiyun uint64_t *fix_counters;
195*4882a593Smuzhiyun struct xen_pmu_cntr_pair *arch_cntr_pair;
196*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
197*4882a593Smuzhiyun uint8_t xenpmu_flags = get_xenpmu_flags();
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if (!xenpmu_data || !(xenpmu_flags & XENPMU_IRQ_PROCESSING))
201*4882a593Smuzhiyun return false;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun ctxt = &xenpmu_data->pmu.c.intel;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun switch (msr) {
206*4882a593Smuzhiyun case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
207*4882a593Smuzhiyun reg = &ctxt->global_ovf_ctrl;
208*4882a593Smuzhiyun break;
209*4882a593Smuzhiyun case MSR_CORE_PERF_GLOBAL_STATUS:
210*4882a593Smuzhiyun reg = &ctxt->global_status;
211*4882a593Smuzhiyun break;
212*4882a593Smuzhiyun case MSR_CORE_PERF_GLOBAL_CTRL:
213*4882a593Smuzhiyun reg = &ctxt->global_ctrl;
214*4882a593Smuzhiyun break;
215*4882a593Smuzhiyun case MSR_CORE_PERF_FIXED_CTR_CTRL:
216*4882a593Smuzhiyun reg = &ctxt->fixed_ctrl;
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun default:
219*4882a593Smuzhiyun switch (type) {
220*4882a593Smuzhiyun case MSR_TYPE_COUNTER:
221*4882a593Smuzhiyun fix_counters = field_offset(ctxt, fixed_counters);
222*4882a593Smuzhiyun reg = &fix_counters[index];
223*4882a593Smuzhiyun break;
224*4882a593Smuzhiyun case MSR_TYPE_ARCH_COUNTER:
225*4882a593Smuzhiyun arch_cntr_pair = field_offset(ctxt, arch_counters);
226*4882a593Smuzhiyun reg = &arch_cntr_pair[index].counter;
227*4882a593Smuzhiyun break;
228*4882a593Smuzhiyun case MSR_TYPE_ARCH_CTRL:
229*4882a593Smuzhiyun arch_cntr_pair = field_offset(ctxt, arch_counters);
230*4882a593Smuzhiyun reg = &arch_cntr_pair[index].control;
231*4882a593Smuzhiyun break;
232*4882a593Smuzhiyun default:
233*4882a593Smuzhiyun return false;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (reg) {
238*4882a593Smuzhiyun if (is_read)
239*4882a593Smuzhiyun *val = *reg;
240*4882a593Smuzhiyun else {
241*4882a593Smuzhiyun *reg = *val;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (msr == MSR_CORE_PERF_GLOBAL_OVF_CTRL)
244*4882a593Smuzhiyun ctxt->global_status &= (~(*val));
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun return true;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun return false;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
xen_amd_pmu_emulate(unsigned int msr,u64 * val,bool is_read)252*4882a593Smuzhiyun static bool xen_amd_pmu_emulate(unsigned int msr, u64 *val, bool is_read)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun uint64_t *reg = NULL;
255*4882a593Smuzhiyun int i, off = 0;
256*4882a593Smuzhiyun struct xen_pmu_amd_ctxt *ctxt;
257*4882a593Smuzhiyun uint64_t *counter_regs, *ctrl_regs;
258*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
259*4882a593Smuzhiyun uint8_t xenpmu_flags = get_xenpmu_flags();
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (!xenpmu_data || !(xenpmu_flags & XENPMU_IRQ_PROCESSING))
262*4882a593Smuzhiyun return false;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (k7_counters_mirrored &&
265*4882a593Smuzhiyun ((msr >= MSR_K7_EVNTSEL0) && (msr <= MSR_K7_PERFCTR3)))
266*4882a593Smuzhiyun msr = get_fam15h_addr(msr);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun ctxt = &xenpmu_data->pmu.c.amd;
269*4882a593Smuzhiyun for (i = 0; i < amd_num_counters; i++) {
270*4882a593Smuzhiyun if (msr == amd_ctrls_base + off) {
271*4882a593Smuzhiyun ctrl_regs = field_offset(ctxt, ctrls);
272*4882a593Smuzhiyun reg = &ctrl_regs[i];
273*4882a593Smuzhiyun break;
274*4882a593Smuzhiyun } else if (msr == amd_counters_base + off) {
275*4882a593Smuzhiyun counter_regs = field_offset(ctxt, counters);
276*4882a593Smuzhiyun reg = &counter_regs[i];
277*4882a593Smuzhiyun break;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun off += amd_msr_step;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if (reg) {
283*4882a593Smuzhiyun if (is_read)
284*4882a593Smuzhiyun *val = *reg;
285*4882a593Smuzhiyun else
286*4882a593Smuzhiyun *reg = *val;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun return true;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun return false;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
pmu_msr_read(unsigned int msr,uint64_t * val,int * err)293*4882a593Smuzhiyun bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
296*4882a593Smuzhiyun if (is_amd_pmu_msr(msr)) {
297*4882a593Smuzhiyun if (!xen_amd_pmu_emulate(msr, val, 1))
298*4882a593Smuzhiyun *val = native_read_msr_safe(msr, err);
299*4882a593Smuzhiyun return true;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun } else {
302*4882a593Smuzhiyun int type, index;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (is_intel_pmu_msr(msr, &type, &index)) {
305*4882a593Smuzhiyun if (!xen_intel_pmu_emulate(msr, val, type, index, 1))
306*4882a593Smuzhiyun *val = native_read_msr_safe(msr, err);
307*4882a593Smuzhiyun return true;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun return false;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
pmu_msr_write(unsigned int msr,uint32_t low,uint32_t high,int * err)314*4882a593Smuzhiyun bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun uint64_t val = ((uint64_t)high << 32) | low;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
319*4882a593Smuzhiyun if (is_amd_pmu_msr(msr)) {
320*4882a593Smuzhiyun if (!xen_amd_pmu_emulate(msr, &val, 0))
321*4882a593Smuzhiyun *err = native_write_msr_safe(msr, low, high);
322*4882a593Smuzhiyun return true;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun } else {
325*4882a593Smuzhiyun int type, index;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun if (is_intel_pmu_msr(msr, &type, &index)) {
328*4882a593Smuzhiyun if (!xen_intel_pmu_emulate(msr, &val, type, index, 0))
329*4882a593Smuzhiyun *err = native_write_msr_safe(msr, low, high);
330*4882a593Smuzhiyun return true;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun return false;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
xen_amd_read_pmc(int counter)337*4882a593Smuzhiyun static unsigned long long xen_amd_read_pmc(int counter)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun struct xen_pmu_amd_ctxt *ctxt;
340*4882a593Smuzhiyun uint64_t *counter_regs;
341*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
342*4882a593Smuzhiyun uint8_t xenpmu_flags = get_xenpmu_flags();
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun if (!xenpmu_data || !(xenpmu_flags & XENPMU_IRQ_PROCESSING)) {
345*4882a593Smuzhiyun uint32_t msr;
346*4882a593Smuzhiyun int err;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun msr = amd_counters_base + (counter * amd_msr_step);
349*4882a593Smuzhiyun return native_read_msr_safe(msr, &err);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun ctxt = &xenpmu_data->pmu.c.amd;
353*4882a593Smuzhiyun counter_regs = field_offset(ctxt, counters);
354*4882a593Smuzhiyun return counter_regs[counter];
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
xen_intel_read_pmc(int counter)357*4882a593Smuzhiyun static unsigned long long xen_intel_read_pmc(int counter)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun struct xen_pmu_intel_ctxt *ctxt;
360*4882a593Smuzhiyun uint64_t *fixed_counters;
361*4882a593Smuzhiyun struct xen_pmu_cntr_pair *arch_cntr_pair;
362*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
363*4882a593Smuzhiyun uint8_t xenpmu_flags = get_xenpmu_flags();
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun if (!xenpmu_data || !(xenpmu_flags & XENPMU_IRQ_PROCESSING)) {
366*4882a593Smuzhiyun uint32_t msr;
367*4882a593Smuzhiyun int err;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun if (counter & (1 << INTEL_PMC_TYPE_SHIFT))
370*4882a593Smuzhiyun msr = MSR_CORE_PERF_FIXED_CTR0 + (counter & 0xffff);
371*4882a593Smuzhiyun else
372*4882a593Smuzhiyun msr = MSR_IA32_PERFCTR0 + counter;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun return native_read_msr_safe(msr, &err);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun ctxt = &xenpmu_data->pmu.c.intel;
378*4882a593Smuzhiyun if (counter & (1 << INTEL_PMC_TYPE_SHIFT)) {
379*4882a593Smuzhiyun fixed_counters = field_offset(ctxt, fixed_counters);
380*4882a593Smuzhiyun return fixed_counters[counter & 0xffff];
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun arch_cntr_pair = field_offset(ctxt, arch_counters);
384*4882a593Smuzhiyun return arch_cntr_pair[counter].counter;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
xen_read_pmc(int counter)387*4882a593Smuzhiyun unsigned long long xen_read_pmc(int counter)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
390*4882a593Smuzhiyun return xen_amd_read_pmc(counter);
391*4882a593Smuzhiyun else
392*4882a593Smuzhiyun return xen_intel_read_pmc(counter);
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
pmu_apic_update(uint32_t val)395*4882a593Smuzhiyun int pmu_apic_update(uint32_t val)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun int ret;
398*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun if (!xenpmu_data) {
401*4882a593Smuzhiyun pr_warn_once("%s: pmudata not initialized\n", __func__);
402*4882a593Smuzhiyun return -EINVAL;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun xenpmu_data->pmu.l.lapic_lvtpc = val;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (get_xenpmu_flags() & XENPMU_IRQ_PROCESSING)
408*4882a593Smuzhiyun return 0;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun ret = HYPERVISOR_xenpmu_op(XENPMU_lvtpc_set, NULL);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun return ret;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun /* perf callbacks */
xen_is_in_guest(void)416*4882a593Smuzhiyun static int xen_is_in_guest(void)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun const struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun if (!xenpmu_data) {
421*4882a593Smuzhiyun pr_warn_once("%s: pmudata not initialized\n", __func__);
422*4882a593Smuzhiyun return 0;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun if (!xen_initial_domain() || (xenpmu_data->domain_id >= DOMID_SELF))
426*4882a593Smuzhiyun return 0;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun return 1;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
xen_is_user_mode(void)431*4882a593Smuzhiyun static int xen_is_user_mode(void)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun const struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (!xenpmu_data) {
436*4882a593Smuzhiyun pr_warn_once("%s: pmudata not initialized\n", __func__);
437*4882a593Smuzhiyun return 0;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun if (xenpmu_data->pmu.pmu_flags & PMU_SAMPLE_PV)
441*4882a593Smuzhiyun return (xenpmu_data->pmu.pmu_flags & PMU_SAMPLE_USER);
442*4882a593Smuzhiyun else
443*4882a593Smuzhiyun return !!(xenpmu_data->pmu.r.regs.cpl & 3);
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
xen_get_guest_ip(void)446*4882a593Smuzhiyun static unsigned long xen_get_guest_ip(void)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun const struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun if (!xenpmu_data) {
451*4882a593Smuzhiyun pr_warn_once("%s: pmudata not initialized\n", __func__);
452*4882a593Smuzhiyun return 0;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun return xenpmu_data->pmu.r.regs.ip;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun static struct perf_guest_info_callbacks xen_guest_cbs = {
459*4882a593Smuzhiyun .is_in_guest = xen_is_in_guest,
460*4882a593Smuzhiyun .is_user_mode = xen_is_user_mode,
461*4882a593Smuzhiyun .get_guest_ip = xen_get_guest_ip,
462*4882a593Smuzhiyun };
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun /* Convert registers from Xen's format to Linux' */
xen_convert_regs(const struct xen_pmu_regs * xen_regs,struct pt_regs * regs,uint64_t pmu_flags)465*4882a593Smuzhiyun static void xen_convert_regs(const struct xen_pmu_regs *xen_regs,
466*4882a593Smuzhiyun struct pt_regs *regs, uint64_t pmu_flags)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun regs->ip = xen_regs->ip;
469*4882a593Smuzhiyun regs->cs = xen_regs->cs;
470*4882a593Smuzhiyun regs->sp = xen_regs->sp;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun if (pmu_flags & PMU_SAMPLE_PV) {
473*4882a593Smuzhiyun if (pmu_flags & PMU_SAMPLE_USER)
474*4882a593Smuzhiyun regs->cs |= 3;
475*4882a593Smuzhiyun else
476*4882a593Smuzhiyun regs->cs &= ~3;
477*4882a593Smuzhiyun } else {
478*4882a593Smuzhiyun if (xen_regs->cpl)
479*4882a593Smuzhiyun regs->cs |= 3;
480*4882a593Smuzhiyun else
481*4882a593Smuzhiyun regs->cs &= ~3;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
xen_pmu_irq_handler(int irq,void * dev_id)485*4882a593Smuzhiyun irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun int err, ret = IRQ_NONE;
488*4882a593Smuzhiyun struct pt_regs regs = {0};
489*4882a593Smuzhiyun const struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
490*4882a593Smuzhiyun uint8_t xenpmu_flags = get_xenpmu_flags();
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun if (!xenpmu_data) {
493*4882a593Smuzhiyun pr_warn_once("%s: pmudata not initialized\n", __func__);
494*4882a593Smuzhiyun return ret;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun this_cpu_ptr(&xenpmu_shared)->flags =
498*4882a593Smuzhiyun xenpmu_flags | XENPMU_IRQ_PROCESSING;
499*4882a593Smuzhiyun xen_convert_regs(&xenpmu_data->pmu.r.regs, ®s,
500*4882a593Smuzhiyun xenpmu_data->pmu.pmu_flags);
501*4882a593Smuzhiyun if (x86_pmu.handle_irq(®s))
502*4882a593Smuzhiyun ret = IRQ_HANDLED;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /* Write out cached context to HW */
505*4882a593Smuzhiyun err = HYPERVISOR_xenpmu_op(XENPMU_flush, NULL);
506*4882a593Smuzhiyun this_cpu_ptr(&xenpmu_shared)->flags = xenpmu_flags;
507*4882a593Smuzhiyun if (err) {
508*4882a593Smuzhiyun pr_warn_once("%s: failed hypercall, err: %d\n", __func__, err);
509*4882a593Smuzhiyun return IRQ_NONE;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return ret;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun bool is_xen_pmu;
516*4882a593Smuzhiyun
xen_pmu_init(int cpu)517*4882a593Smuzhiyun void xen_pmu_init(int cpu)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun int err;
520*4882a593Smuzhiyun struct xen_pmu_params xp;
521*4882a593Smuzhiyun unsigned long pfn;
522*4882a593Smuzhiyun struct xen_pmu_data *xenpmu_data;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun BUILD_BUG_ON(sizeof(struct xen_pmu_data) > PAGE_SIZE);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (xen_hvm_domain() || (cpu != 0 && !is_xen_pmu))
527*4882a593Smuzhiyun return;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun xenpmu_data = (struct xen_pmu_data *)get_zeroed_page(GFP_KERNEL);
530*4882a593Smuzhiyun if (!xenpmu_data) {
531*4882a593Smuzhiyun pr_err("VPMU init: No memory\n");
532*4882a593Smuzhiyun return;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun pfn = virt_to_pfn(xenpmu_data);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun xp.val = pfn_to_mfn(pfn);
537*4882a593Smuzhiyun xp.vcpu = cpu;
538*4882a593Smuzhiyun xp.version.maj = XENPMU_VER_MAJ;
539*4882a593Smuzhiyun xp.version.min = XENPMU_VER_MIN;
540*4882a593Smuzhiyun err = HYPERVISOR_xenpmu_op(XENPMU_init, &xp);
541*4882a593Smuzhiyun if (err)
542*4882a593Smuzhiyun goto fail;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun per_cpu(xenpmu_shared, cpu).xenpmu_data = xenpmu_data;
545*4882a593Smuzhiyun per_cpu(xenpmu_shared, cpu).flags = 0;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (!is_xen_pmu) {
548*4882a593Smuzhiyun is_xen_pmu = true;
549*4882a593Smuzhiyun perf_register_guest_info_callbacks(&xen_guest_cbs);
550*4882a593Smuzhiyun xen_pmu_arch_init();
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun return;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun fail:
556*4882a593Smuzhiyun if (err == -EOPNOTSUPP || err == -ENOSYS)
557*4882a593Smuzhiyun pr_info_once("VPMU disabled by hypervisor.\n");
558*4882a593Smuzhiyun else
559*4882a593Smuzhiyun pr_info_once("Could not initialize VPMU for cpu %d, error %d\n",
560*4882a593Smuzhiyun cpu, err);
561*4882a593Smuzhiyun free_pages((unsigned long)xenpmu_data, 0);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
xen_pmu_finish(int cpu)564*4882a593Smuzhiyun void xen_pmu_finish(int cpu)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun struct xen_pmu_params xp;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun if (xen_hvm_domain())
569*4882a593Smuzhiyun return;
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun xp.vcpu = cpu;
572*4882a593Smuzhiyun xp.version.maj = XENPMU_VER_MAJ;
573*4882a593Smuzhiyun xp.version.min = XENPMU_VER_MIN;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun (void)HYPERVISOR_xenpmu_op(XENPMU_finish, &xp);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun free_pages((unsigned long)per_cpu(xenpmu_shared, cpu).xenpmu_data, 0);
578*4882a593Smuzhiyun per_cpu(xenpmu_shared, cpu).xenpmu_data = NULL;
579*4882a593Smuzhiyun }
580