op_hw_specific.h revision 5bbbe460405564a1aed8a67a13c43e9356ffc656
1/*
2 * @file architecture specific interfaces
3 * @remark Copyright 2008 Intel Corporation
4 * @remark Read the file COPYING
5 * @author Andi Kleen
6 */
7
8#if defined(__i386__) || defined(__x86_64__)
9
10/* Assume we run on the same host as the profilee */
11
12#define num_to_mask(x) ((1U << (x)) - 1)
13
14static inline int cpuid_vendor(char *vnd)
15{
16	union {
17		struct {
18			unsigned b,d,c;
19		};
20		char v[12];
21	} v;
22	unsigned eax;
23	asm("cpuid" : "=a" (eax), "=b" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0));
24	return !strncmp(v.v, vnd, 12);
25}
26
27/* Work around Nehalem spec update AAJ79: CPUID incorrectly indicates
28   unhalted reference cycle architectural event is supported. We assume
29   steppings after C0 report correct data in CPUID. */
30static inline void workaround_nehalem_aaj79(unsigned *ebx)
31{
32	union {
33		unsigned eax;
34		struct {
35			unsigned stepping : 4;
36			unsigned model : 4;
37			unsigned family : 4;
38			unsigned type : 2;
39			unsigned res : 2;
40			unsigned ext_model : 4;
41			unsigned ext_family : 8;
42			unsigned res2 : 4;
43		};
44	} v;
45	unsigned model;
46
47	if (!cpuid_vendor("GenuineIntel"))
48		return;
49	asm("cpuid" : "=a" (v.eax) : "0" (1) : "ecx","ebx","edx");
50	model = (v.ext_model << 4) + v.model;
51	if (v.family != 6 || model != 26 || v.stepping > 4)
52		return;
53	*ebx |= (1 << 2);	/* disable unsupported event */
54}
55
56static inline unsigned arch_get_filter(op_cpu cpu_type)
57{
58	if (cpu_type == CPU_ARCH_PERFMON) {
59		unsigned ebx, eax;
60		asm("cpuid" : "=a" (eax), "=b" (ebx) : "0" (0xa) : "ecx","edx");
61		workaround_nehalem_aaj79(&ebx);
62		return ebx & num_to_mask(eax >> 24);
63	}
64	return -1U;
65}
66
67static inline int arch_num_counters(op_cpu cpu_type)
68{
69	if (cpu_type == CPU_ARCH_PERFMON) {
70		unsigned v;
71		asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx");
72		return (v >> 8) & 0xff;
73	}
74	return -1;
75}
76
77static inline unsigned arch_get_counter_mask(void)
78{
79	unsigned v;
80	asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx");
81	return num_to_mask((v >> 8) & 0xff);
82}
83
84#else
85
86static inline unsigned arch_get_filter(op_cpu cpu_type)
87{
88	/* Do something with passed arg to shut up the compiler warning */
89	if (cpu_type != CPU_NO_GOOD)
90		return 0;
91	return 0;
92}
93
94static inline int arch_num_counters(op_cpu cpu_type)
95{
96	/* Do something with passed arg to shut up the compiler warning */
97	if (cpu_type != CPU_NO_GOOD)
98		return -1;
99	return -1;
100}
101
102static inline unsigned arch_get_counter_mask(void)
103{
104	return 0;
105}
106
107#endif
108