xref: /OK3568_Linux_fs/kernel/arch/x86/xen/pmu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &regs,
500*4882a593Smuzhiyun 			 xenpmu_data->pmu.pmu_flags);
501*4882a593Smuzhiyun 	if (x86_pmu.handle_irq(&regs))
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