summaryrefslogtreecommitdiffstats
path: root/sys/i386/include/pmc_mdep.h
blob: 63d5f8bf0b67af8a482646d090050e0898c0447c (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*-
 * Copyright (c) 2003-2005,2008 Joseph Koshy
 * Copyright (c) 2007 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by A. Joseph Koshy under
 * sponsorship from the FreeBSD Foundation and Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#ifndef _MACHINE_PMC_MDEP_H
#define	_MACHINE_PMC_MDEP_H 1

#ifdef	_KERNEL
struct pmc_mdep;
#endif

/*
 * On the i386 platform we support the following PMCs.
 *
 * TSC		The timestamp counter
 * K7		AMD Athlon XP/MP and other 32 bit processors.
 * K8		AMD Athlon64 and Opteron PMCs in 32 bit mode.
 * PIV		Intel P4/HTT and P4/EMT64
 * PPRO		Intel Pentium Pro, Pentium-II, Pentium-III, Celeron and
 *		Pentium-M processors
 * PENTIUM	Intel Pentium MMX.
 * IAP		Intel Core/Core2/Atom programmable PMCs.
 * IAF		Intel fixed-function PMCs.
 */

#include <dev/hwpmc/hwpmc_amd.h> /* K7 and K8 */
#include <dev/hwpmc/hwpmc_core.h>
#include <dev/hwpmc/hwpmc_piv.h>
#include <dev/hwpmc/hwpmc_ppro.h>
#include <dev/hwpmc/hwpmc_pentium.h>
#include <dev/hwpmc/hwpmc_tsc.h>

/*
 * Intel processors implementing V2 and later of the Intel performance
 * measurement architecture have PMCs of the following classes: TSC,
 * IAF and IAP.
 */
#define	PMC_MDEP_CLASS_INDEX_TSC	0
#define	PMC_MDEP_CLASS_INDEX_K7		1
#define	PMC_MDEP_CLASS_INDEX_K8		1
#define	PMC_MDEP_CLASS_INDEX_P4		1
#define	PMC_MDEP_CLASS_INDEX_P5		1
#define	PMC_MDEP_CLASS_INDEX_P6		1
#define	PMC_MDEP_CLASS_INDEX_IAP	1
#define	PMC_MDEP_CLASS_INDEX_IAF	2

/*
 * Architecture specific extensions to <sys/pmc.h> structures.
 */

union pmc_md_op_pmcallocate  {
	struct pmc_md_amd_op_pmcallocate	pm_amd;
	struct pmc_md_iaf_op_pmcallocate	pm_iaf;
	struct pmc_md_iap_op_pmcallocate	pm_iap;
	struct pmc_md_p4_op_pmcallocate		pm_p4;
	struct pmc_md_pentium_op_pmcallocate	pm_pentium;
	struct pmc_md_ppro_op_pmcallocate	pm_ppro;
	uint64_t				__pad[4];
};

/* Logging */
#define	PMCLOG_READADDR		PMCLOG_READ32
#define	PMCLOG_EMITADDR		PMCLOG_EMIT32

#ifdef _KERNEL

/* MD extension for 'struct pmc' */
union pmc_md_pmc  {
	struct pmc_md_amd_pmc	pm_amd;
	struct pmc_md_iaf_pmc	pm_iaf;
	struct pmc_md_iap_pmc	pm_iap;
	struct pmc_md_p4_pmc	pm_p4;
	struct pmc_md_pentium_pmc pm_pentium;
	struct pmc_md_ppro_pmc	pm_ppro;
};

struct pmc;
struct pmc_mdep;

#define	PMC_TRAPFRAME_TO_PC(TF)	((TF)->tf_eip)
#define	PMC_TRAPFRAME_TO_FP(TF)	((TF)->tf_ebp)

/*
 * The layout of the stack frame on entry into the NMI handler depends on
 * whether a privilege level change (and consequent stack switch) was
 * required for entry.
 *
 * When processing an interrupt when in user mode, the processor switches
 * stacks, and saves the user mode stack pointer on the kernel stack.  The
 * user mode stack pointer is then available to the interrupt handler
 * at frame->tf_esp.
 *
 * When processing an interrupt while in kernel mode, the processor
 * continues to use the existing (kernel) stack.  Therefore we determine
 * the stack pointer for the interrupted kernel procedure by adding an
 * offset to the current frame pointer.
 */

#define	PMC_TRAPFRAME_TO_USER_SP(TF)	((TF)->tf_esp)
#define	PMC_TRAPFRAME_TO_KERNEL_SP(TF)	((uintptr_t) &((TF)->tf_esp))

#define	PMC_IN_KERNEL_STACK(S,START,END)		\
	((S) >= (START) && (S) < (END))
#define	PMC_IN_KERNEL(va) (((va) >= USRSTACK) &&	\
	((va) < VM_MAX_KERNEL_ADDRESS))

#define	PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)

#define	PMC_IN_TRAP_HANDLER(PC) 			\
	((PC) >= (uintptr_t) start_exceptions &&	\
	 (PC) < (uintptr_t) end_exceptions)

#define	PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(I)		\
	(((I) & 0x00ffffff) == 0xe58955) /* pushl %ebp; movl %esp,%ebp */
#define	PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(I)		\
	(((I) & 0x0000ffff) == 0xe589)	/* movl %esp,%ebp */
#define	PMC_AT_FUNCTION_EPILOGUE_RET(I)			\
	(((I) & 0xFF) == 0xC3)		   /* ret */

/*
 * Prototypes
 */

void	start_exceptions(void), end_exceptions(void);
void	pmc_x86_lapic_enable_pmc_interrupt(void);

struct pmc_mdep *pmc_amd_initialize(void);
void	pmc_amd_finalize(struct pmc_mdep *_md);
struct pmc_mdep *pmc_intel_initialize(void);
void	pmc_intel_finalize(struct pmc_mdep *_md);

#endif /* _KERNEL */
#endif /* _MACHINE_PMC_MDEP_H */
OpenPOWER on IntegriCloud