OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [x86/] [oprofile/] [op_model_ppro.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/**
2
 * @file op_model_ppro.h
3
 * pentium pro / P6 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
#include <asm/apic.h>
17
#include <asm/nmi.h>
18
 
19
#include "op_x86_model.h"
20
#include "op_counter.h"
21
 
22
#define NUM_COUNTERS 2
23
#define NUM_CONTROLS 2
24
 
25
#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
26
#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
27
#define CTR_32BIT_WRITE(l,msrs,c)       \
28
        do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0);} while (0)
29
#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
30
 
31
#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
32
#define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
33
#define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
34
#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
35
#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
36
#define CTRL_CLEAR(x) (x &= (1<<21))
37
#define CTRL_SET_ENABLE(val) (val |= 1<<20)
38
#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
39
#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
40
#define CTRL_SET_UM(val, m) (val |= (m << 8))
41
#define CTRL_SET_EVENT(val, e) (val |= e)
42
 
43
static unsigned long reset_value[NUM_COUNTERS];
44
 
45
static void ppro_fill_in_addresses(struct op_msrs * const msrs)
46
{
47
        int i;
48
 
49
        for (i=0; i < NUM_COUNTERS; i++) {
50
                if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
51
                        msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
52
                else
53
                        msrs->counters[i].addr = 0;
54
        }
55
 
56
        for (i=0; i < NUM_CONTROLS; i++) {
57
                if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
58
                        msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
59
                else
60
                        msrs->controls[i].addr = 0;
61
        }
62
}
63
 
64
 
65
static void ppro_setup_ctrs(struct op_msrs const * const msrs)
66
{
67
        unsigned int low, high;
68
        int i;
69
 
70
        /* clear all counters */
71
        for (i = 0 ; i < NUM_CONTROLS; ++i) {
72
                if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
73
                        continue;
74
                CTRL_READ(low, high, msrs, i);
75
                CTRL_CLEAR(low);
76
                CTRL_WRITE(low, high, msrs, i);
77
        }
78
 
79
        /* avoid a false detection of ctr overflows in NMI handler */
80
        for (i = 0; i < NUM_COUNTERS; ++i) {
81
                if (unlikely(!CTR_IS_RESERVED(msrs,i)))
82
                        continue;
83
                CTR_32BIT_WRITE(1, msrs, i);
84
        }
85
 
86
        /* enable active counters */
87
        for (i = 0; i < NUM_COUNTERS; ++i) {
88
                if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
89
                        reset_value[i] = counter_config[i].count;
90
 
91
                        CTR_32BIT_WRITE(counter_config[i].count, msrs, i);
92
 
93
                        CTRL_READ(low, high, msrs, i);
94
                        CTRL_CLEAR(low);
95
                        CTRL_SET_ENABLE(low);
96
                        CTRL_SET_USR(low, counter_config[i].user);
97
                        CTRL_SET_KERN(low, counter_config[i].kernel);
98
                        CTRL_SET_UM(low, counter_config[i].unit_mask);
99
                        CTRL_SET_EVENT(low, counter_config[i].event);
100
                        CTRL_WRITE(low, high, msrs, i);
101
                } else {
102
                        reset_value[i] = 0;
103
                }
104
        }
105
}
106
 
107
 
108
static int ppro_check_ctrs(struct pt_regs * const regs,
109
                           struct op_msrs const * const msrs)
110
{
111
        unsigned int low, high;
112
        int i;
113
 
114
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
115
                if (!reset_value[i])
116
                        continue;
117
                CTR_READ(low, high, msrs, i);
118
                if (CTR_OVERFLOWED(low)) {
119
                        oprofile_add_sample(regs, i);
120
                        CTR_32BIT_WRITE(reset_value[i], msrs, i);
121
                }
122
        }
123
 
124
        /* Only P6 based Pentium M need to re-unmask the apic vector but it
125
         * doesn't hurt other P6 variant */
126
        apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
127
 
128
        /* We can't work out if we really handled an interrupt. We
129
         * might have caught a *second* counter just after overflowing
130
         * the interrupt for this counter then arrives
131
         * and we don't find a counter that's overflowed, so we
132
         * would return 0 and get dazed + confused. Instead we always
133
         * assume we found an overflow. This sucks.
134
         */
135
        return 1;
136
}
137
 
138
 
139
static void ppro_start(struct op_msrs const * const msrs)
140
{
141
        unsigned int low,high;
142
        int i;
143
 
144
        for (i = 0; i < NUM_COUNTERS; ++i) {
145
                if (reset_value[i]) {
146
                        CTRL_READ(low, high, msrs, i);
147
                        CTRL_SET_ACTIVE(low);
148
                        CTRL_WRITE(low, high, msrs, i);
149
                }
150
        }
151
}
152
 
153
 
154
static void ppro_stop(struct op_msrs const * const msrs)
155
{
156
        unsigned int low,high;
157
        int i;
158
 
159
        for (i = 0; i < NUM_COUNTERS; ++i) {
160
                if (!reset_value[i])
161
                        continue;
162
                CTRL_READ(low, high, msrs, i);
163
                CTRL_SET_INACTIVE(low);
164
                CTRL_WRITE(low, high, msrs, i);
165
        }
166
}
167
 
168
static void ppro_shutdown(struct op_msrs const * const msrs)
169
{
170
        int i;
171
 
172
        for (i = 0 ; i < NUM_COUNTERS ; ++i) {
173
                if (CTR_IS_RESERVED(msrs,i))
174
                        release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
175
        }
176
        for (i = 0 ; i < NUM_CONTROLS ; ++i) {
177
                if (CTRL_IS_RESERVED(msrs,i))
178
                        release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
179
        }
180
}
181
 
182
 
183
struct op_x86_model_spec const op_ppro_spec = {
184
        .num_counters = NUM_COUNTERS,
185
        .num_controls = NUM_CONTROLS,
186
        .fill_in_addresses = &ppro_fill_in_addresses,
187
        .setup_ctrs = &ppro_setup_ctrs,
188
        .check_ctrs = &ppro_check_ctrs,
189
        .start = &ppro_start,
190
        .stop = &ppro_stop,
191
        .shutdown = &ppro_shutdown
192
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.