summaryrefslogtreecommitdiff
path: root/sys/arch/i386/include/pctr.h
blob: 06458b6007ab0b558ff6451e21acf22e0dc8d074 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*	$OpenBSD: pctr.h,v 1.7 1997/09/08 21:21:42 dm Exp $	*/

/*
 * Pentium performance counter driver for OpenBSD.
 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
 *
 * Modification and redistribution in source and binary forms is
 * permitted provided that due credit is given to the author and the
 * OpenBSD project (for instance by leaving this copyright notice
 * intact).
 */

#ifndef _I386_PCTR_H_
#define _I386_PCTR_H_

typedef u_quad_t pctrval;

#define PCTR_NUM 2

struct pctrst {
  u_int pctr_fn[PCTR_NUM];    /* Current settings of hardware counters */
  pctrval pctr_tsc;           /* Free-running 64-bit cycle counter */
  pctrval pctr_hwc[PCTR_NUM]; /* Values of the hardware counters */
  pctrval pctr_idl;           /* Iterations of the idle loop */
};

/* Bit values in fn fields and PIOCS ioctl's */
#define P5CTR_K 0x40          /* Monitor kernel-level events */
#define P5CTR_U 0x80          /* Monitor user-level events */
#define P5CTR_C 0x100         /* count cycles rather than events */

#define P6CTR_U  0x010000     /* Monitor user-level events */
#define P6CTR_K  0x020000     /* Monitor kernel-level events */
#define P6CTR_E  0x040000     /* Edge detect */
#define P6CTR_EN 0x400000     /* Enable counters (counter 0 only) */
#define P6CTR_I  0x800000     /* Invert counter mask */

/* Unit Mask bits */
#define P6CTR_UM_M 0x0800     /* Modified cache lines */
#define P6CTR_UM_E 0x0400     /* Exclusive cache lines */
#define P6CTR_UM_S 0x0200     /* Shared cache lines */
#define P6CTR_UM_I 0x0100     /* Invalid cache lines */
#define P6CTR_UM_MESI (P6CTR_UM_M|P6CTR_UM_E|P6CTR_UM_S|P6CTR_UM_I)
#define P6CTR_UM_A 0x2000     /* Any initiator (as opposed to self) */

#define P6CTR_CM_SHIFT 24     /* Left shift for counter mask */

/* ioctl to set which counter a device tracks. */
#define PCIOCRD _IOR('c', 1, struct pctrst)   /* Read counter value */
#define PCIOCS0 _IOW('c', 8, unsigned int)    /* Set counter 0 function */
#define PCIOCS1 _IOW('c', 9, unsigned int)    /* Set counter 1 function */

#define _PATH_PCTR "/dev/pctr"


#define __cpuid()				\
({						\
  pctrval id;					\
  __asm __volatile ("pushfl\n"			\
		    "\tpopl %%eax\n"		\
		    "\tmovl %%eax,%%ecx\n"	\
		    "\txorl %1,%%eax\n"		\
		    "\tpushl %%eax\n"		\
		    "\tpopfl\n"			\
		    "\tpushfl\n"		\
		    "\tpopl %%eax\n"		\
		    "\tpushl %%ecx\n"		\
		    "\tpopfl\n"			\
		    "\tcmpl %%eax,%%ecx\n"	\
		    "\tmovl $0,%%eax\n"		\
		    "\tje 1f\n"			\
		    "\tcpuid\n"			\
		    "\ttestl %%eax,%%eax\n"	\
		    "\tje 1f\n"			\
		    "\tmovl $1,%%eax\n"		\
		    "\tcpuid\n"			\
		    "\tjmp 2f\n"		\
		    "1:\t"			\
		    "\txorl %%eax,%%eax\n"	\
		    "\txorl %%edx,%%edx\n"	\
		    "2:\t"			\
		    : "=A" (id) : "i" (PSL_ID)	\
		    : "edx", "ecx", "ebx");	\
  id;						\
})

#define __hastsc(id) (((id) & 0x1000000000ULL) != 0ULL)
#define __hasp5ctr(id) (((id) & 0xf00) == 0x500		\
			&& (((id) & 0xf0) == 0x10	\
			    || ((id) & 0xf0) == 0x20))
#define __hasp6ctr(id) (((id) & 0xf00) == 0x600)		

#define __cpufamily() ((__cpuid() >> 8) & 0xf)

#define rdtsc()						\
({							\
  pctrval v;						\
  __asm __volatile (".byte 0xf, 0x31" : "=A" (v));	\
  v;							\
})

/* Read the performance counters (Pentium Pro only) */
#define rdpmc(ctr)				\
({						\
  pctrval v;					\
  __asm __volatile (".byte 0xf, 0x33\n"		\
		    "\tandl $0xff, %%edx"	\
		    : "=A" (v) : "c" (ctr));	\
  v;						\
})

#ifdef _KERNEL

#define CR4_TSD 0x004         /* Time stamp disable */
#define CR4_PCE 0x100         /* Performance counter enable */

#define MSR_TSC 0x10          /* MSR for TSC */
#define P5MSR_CTRSEL 0x11     /* MSR for selecting both counters on P5 */
#define P5MSR_CTR0 0x12       /* Value of Ctr0 on P5 */
#define P5MSR_CTR1 0x13       /* Value of Ctr1 on P5 */
#define P6MSR_CTRSEL0 0x186   /* MSR for programming CTR0 on P6 */
#define P6MSR_CTRSEL1 0x187   /* MSR for programming CTR0 on P6 */
#define P6MSR_CTR0 0xc1       /* Ctr0 on P6 */
#define P6MSR_CTR1 0xc2       /* Ctr1 on P6 */

#define rdmsr(msr)						\
({								\
  pctrval v;							\
  __asm __volatile (".byte 0xf, 0x32" : "=A" (v) : "c" (msr));	\
  v;								\
})

#define wrmsr(msr, v) \
     __asm __volatile (".byte 0xf, 0x30" :: "A" ((u_quad_t) (v)), "c" (msr));

#endif /* _KERNEL */
#endif /* ! _I386_PCTR_H_ */