PageRenderTime 22ms CodeModel.GetById 13ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/i386/oprofile/op_model_athlon.c

https://bitbucket.org/evzijst/gittest
C | 149 lines | 106 code | 26 blank | 17 comment | 14 complexity | 82154ef78f68e382e9acc72982b78138 MD5 | raw file
  1/**
  2 * @file op_model_athlon.h
  3 * athlon / K7 model-specific MSR operations
  4 *
  5 * @remark Copyright 2002 OProfile authors
  6 * @remark Read the file COPYING
  7 *
  8 * @author John Levon
  9 * @author Philippe Elie
 10 * @author Graydon Hoare
 11 */
 12
 13#include <linux/oprofile.h>
 14#include <asm/ptrace.h>
 15#include <asm/msr.h>
 16 
 17#include "op_x86_model.h"
 18#include "op_counter.h"
 19
 20#define NUM_COUNTERS 4
 21#define NUM_CONTROLS 4
 22
 23#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
 24#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1);} while (0)
 25#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
 26
 27#define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
 28#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
 29#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
 30#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
 31#define CTRL_CLEAR(x) (x &= (1<<21))
 32#define CTRL_SET_ENABLE(val) (val |= 1<<20)
 33#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
 34#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
 35#define CTRL_SET_UM(val, m) (val |= (m << 8))
 36#define CTRL_SET_EVENT(val, e) (val |= e)
 37
 38static unsigned long reset_value[NUM_COUNTERS];
 39 
 40static void athlon_fill_in_addresses(struct op_msrs * const msrs)
 41{
 42	msrs->counters[0].addr = MSR_K7_PERFCTR0;
 43	msrs->counters[1].addr = MSR_K7_PERFCTR1;
 44	msrs->counters[2].addr = MSR_K7_PERFCTR2;
 45	msrs->counters[3].addr = MSR_K7_PERFCTR3;
 46
 47	msrs->controls[0].addr = MSR_K7_EVNTSEL0;
 48	msrs->controls[1].addr = MSR_K7_EVNTSEL1;
 49	msrs->controls[2].addr = MSR_K7_EVNTSEL2;
 50	msrs->controls[3].addr = MSR_K7_EVNTSEL3;
 51}
 52
 53 
 54static void athlon_setup_ctrs(struct op_msrs const * const msrs)
 55{
 56	unsigned int low, high;
 57	int i;
 58 
 59	/* clear all counters */
 60	for (i = 0 ; i < NUM_CONTROLS; ++i) {
 61		CTRL_READ(low, high, msrs, i);
 62		CTRL_CLEAR(low);
 63		CTRL_WRITE(low, high, msrs, i);
 64	}
 65	
 66	/* avoid a false detection of ctr overflows in NMI handler */
 67	for (i = 0; i < NUM_COUNTERS; ++i) {
 68		CTR_WRITE(1, msrs, i);
 69	}
 70
 71	/* enable active counters */
 72	for (i = 0; i < NUM_COUNTERS; ++i) {
 73		if (counter_config[i].enabled) {
 74			reset_value[i] = counter_config[i].count;
 75
 76			CTR_WRITE(counter_config[i].count, msrs, i);
 77
 78			CTRL_READ(low, high, msrs, i);
 79			CTRL_CLEAR(low);
 80			CTRL_SET_ENABLE(low);
 81			CTRL_SET_USR(low, counter_config[i].user);
 82			CTRL_SET_KERN(low, counter_config[i].kernel);
 83			CTRL_SET_UM(low, counter_config[i].unit_mask);
 84			CTRL_SET_EVENT(low, counter_config[i].event);
 85			CTRL_WRITE(low, high, msrs, i);
 86		} else {
 87			reset_value[i] = 0;
 88		}
 89	}
 90}
 91
 92 
 93static int athlon_check_ctrs(struct pt_regs * const regs,
 94			     struct op_msrs const * const msrs)
 95{
 96	unsigned int low, high;
 97	int i;
 98
 99	for (i = 0 ; i < NUM_COUNTERS; ++i) {
100		CTR_READ(low, high, msrs, i);
101		if (CTR_OVERFLOWED(low)) {
102			oprofile_add_sample(regs, i);
103			CTR_WRITE(reset_value[i], msrs, i);
104		}
105	}
106
107	/* See op_model_ppro.c */
108	return 1;
109}
110
111 
112static void athlon_start(struct op_msrs const * const msrs)
113{
114	unsigned int low, high;
115	int i;
116	for (i = 0 ; i < NUM_COUNTERS ; ++i) {
117		if (reset_value[i]) {
118			CTRL_READ(low, high, msrs, i);
119			CTRL_SET_ACTIVE(low);
120			CTRL_WRITE(low, high, msrs, i);
121		}
122	}
123}
124
125
126static void athlon_stop(struct op_msrs const * const msrs)
127{
128	unsigned int low,high;
129	int i;
130
131	/* Subtle: stop on all counters to avoid race with
132	 * setting our pm callback */
133	for (i = 0 ; i < NUM_COUNTERS ; ++i) {
134		CTRL_READ(low, high, msrs, i);
135		CTRL_SET_INACTIVE(low);
136		CTRL_WRITE(low, high, msrs, i);
137	}
138}
139
140
141struct op_x86_model_spec const op_athlon_spec = {
142	.num_counters = NUM_COUNTERS,
143	.num_controls = NUM_CONTROLS,
144	.fill_in_addresses = &athlon_fill_in_addresses,
145	.setup_ctrs = &athlon_setup_ctrs,
146	.check_ctrs = &athlon_check_ctrs,
147	.start = &athlon_start,
148	.stop = &athlon_stop
149};