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/] [alpha/] [oprofile/] [op_model_ev5.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/**
2
 * @file arch/alpha/oprofile/op_model_ev5.c
3
 *
4
 * @remark Copyright 2002 OProfile authors
5
 * @remark Read the file COPYING
6
 *
7
 * @author Richard Henderson <rth@twiddle.net>
8
 */
9
 
10
#include <linux/oprofile.h>
11
#include <linux/init.h>
12
#include <linux/smp.h>
13
#include <asm/ptrace.h>
14
#include <asm/system.h>
15
 
16
#include "op_impl.h"
17
 
18
 
19
/* Compute all of the registers in preparation for enabling profiling.
20
 
21
   The 21164 (EV5) and 21164PC (PCA65) vary in the bit placement and
22
   meaning of the "CBOX" events.  Given that we don't care about meaning
23
   at this point, arrange for the difference in bit placement to be
24
   handled by common code.  */
25
 
26
static void
27
common_reg_setup(struct op_register_config *reg,
28
                 struct op_counter_config *ctr,
29
                 struct op_system_config *sys,
30
                 int cbox1_ofs, int cbox2_ofs)
31
{
32
        int i, ctl, reset, need_reset;
33
 
34
        /* Select desired events.  The event numbers are selected such
35
           that they map directly into the event selection fields:
36
 
37
                PCSEL0: 0, 1
38
                PCSEL1: 24-39
39
                 CBOX1: 40-47
40
                PCSEL2: 48-63
41
                 CBOX2: 64-71
42
 
43
           There are two special cases, in that CYCLES can be measured
44
           on PCSEL[02], and SCACHE_WRITE can be measured on CBOX[12].
45
           These event numbers are canonicalizes to their first appearance.  */
46
 
47
        ctl = 0;
48
        for (i = 0; i < 3; ++i) {
49
                unsigned long event = ctr[i].event;
50
                if (!ctr[i].enabled)
51
                        continue;
52
 
53
                /* Remap the duplicate events, as described above.  */
54
                if (i == 2) {
55
                        if (event == 0)
56
                                event = 12+48;
57
                        else if (event == 2+41)
58
                                event = 4+65;
59
                }
60
 
61
                /* Convert the event numbers onto mux_select bit mask.  */
62
                if (event < 2)
63
                        ctl |= event << 31;
64
                else if (event < 24)
65
                        /* error */;
66
                else if (event < 40)
67
                        ctl |= (event - 24) << 4;
68
                else if (event < 48)
69
                        ctl |= (event - 40) << cbox1_ofs | 15 << 4;
70
                else if (event < 64)
71
                        ctl |= event - 48;
72
                else if (event < 72)
73
                        ctl |= (event - 64) << cbox2_ofs | 15;
74
        }
75
        reg->mux_select = ctl;
76
 
77
        /* Select processor mode.  */
78
        /* ??? Need to come up with some mechanism to trace only selected
79
           processes.  For now select from pal, kernel and user mode.  */
80
        ctl = 0;
81
        ctl |= !sys->enable_pal << 9;
82
        ctl |= !sys->enable_kernel << 8;
83
        ctl |= !sys->enable_user << 30;
84
        reg->proc_mode = ctl;
85
 
86
        /* Select interrupt frequencies.  Take the interrupt count selected
87
           by the user, and map it onto one of the possible counter widths.
88
           If the user value is in between, compute a value to which the
89
           counter is reset at each interrupt.  */
90
 
91
        ctl = reset = need_reset = 0;
92
        for (i = 0; i < 3; ++i) {
93
                unsigned long max, hilo, count = ctr[i].count;
94
                if (!ctr[i].enabled)
95
                        continue;
96
 
97
                if (count <= 256)
98
                        count = 256, hilo = 3, max = 256;
99
                else {
100
                        max = (i == 2 ? 16384 : 65536);
101
                        hilo = 2;
102
                        if (count > max)
103
                                count = max;
104
                }
105
                ctr[i].count = count;
106
 
107
                ctl |= hilo << (8 - i*2);
108
                reset |= (max - count) << (48 - 16*i);
109
                if (count != max)
110
                        need_reset |= 1 << i;
111
        }
112
        reg->freq = ctl;
113
        reg->reset_values = reset;
114
        reg->need_reset = need_reset;
115
}
116
 
117
static void
118
ev5_reg_setup(struct op_register_config *reg,
119
              struct op_counter_config *ctr,
120
              struct op_system_config *sys)
121
{
122
        common_reg_setup(reg, ctr, sys, 19, 22);
123
}
124
 
125
static void
126
pca56_reg_setup(struct op_register_config *reg,
127
                struct op_counter_config *ctr,
128
                struct op_system_config *sys)
129
{
130
        common_reg_setup(reg, ctr, sys, 8, 11);
131
}
132
 
133
/* Program all of the registers in preparation for enabling profiling.  */
134
 
135
static void
136
ev5_cpu_setup (void *x)
137
{
138
        struct op_register_config *reg = x;
139
 
140
        wrperfmon(2, reg->mux_select);
141
        wrperfmon(3, reg->proc_mode);
142
        wrperfmon(4, reg->freq);
143
        wrperfmon(6, reg->reset_values);
144
}
145
 
146
/* CTR is a counter for which the user has requested an interrupt count
147
   in between one of the widths selectable in hardware.  Reset the count
148
   for CTR to the value stored in REG->RESET_VALUES.
149
 
150
   For EV5, this means disabling profiling, reading the current values,
151
   masking in the value for the desired register, writing, then turning
152
   profiling back on.
153
 
154
   This can be streamlined if profiling is only enabled for user mode.
155
   In that case we know that the counters are not currently incrementing
156
   (due to being in kernel mode).  */
157
 
158
static void
159
ev5_reset_ctr(struct op_register_config *reg, unsigned long ctr)
160
{
161
        unsigned long values, mask, not_pk, reset_values;
162
 
163
        mask = (ctr == 0 ? 0xfffful << 48
164
                : ctr == 1 ? 0xfffful << 32
165
                : 0x3fff << 16);
166
 
167
        not_pk = 1 << 9 | 1 << 8;
168
 
169
        reset_values = reg->reset_values;
170
 
171
        if ((reg->proc_mode & not_pk) == not_pk) {
172
                values = wrperfmon(5, 0);
173
                values = (reset_values & mask) | (values & ~mask & -2);
174
                wrperfmon(6, values);
175
        } else {
176
                wrperfmon(0, -1);
177
                values = wrperfmon(5, 0);
178
                values = (reset_values & mask) | (values & ~mask & -2);
179
                wrperfmon(6, values);
180
                wrperfmon(1, reg->enable);
181
        }
182
}
183
 
184
static void
185
ev5_handle_interrupt(unsigned long which, struct pt_regs *regs,
186
                     struct op_counter_config *ctr)
187
{
188
        /* Record the sample.  */
189
        oprofile_add_sample(regs, which);
190
}
191
 
192
 
193
struct op_axp_model op_model_ev5 = {
194
        .reg_setup              = ev5_reg_setup,
195
        .cpu_setup              = ev5_cpu_setup,
196
        .reset_ctr              = ev5_reset_ctr,
197
        .handle_interrupt       = ev5_handle_interrupt,
198
        .cpu_type               = "alpha/ev5",
199
        .num_counters           = 3,
200
        .can_set_proc_mode      = 1,
201
};
202
 
203
struct op_axp_model op_model_pca56 = {
204
        .reg_setup              = pca56_reg_setup,
205
        .cpu_setup              = ev5_cpu_setup,
206
        .reset_ctr              = ev5_reset_ctr,
207
        .handle_interrupt       = ev5_handle_interrupt,
208
        .cpu_type               = "alpha/pca56",
209
        .num_counters           = 3,
210
        .can_set_proc_mode      = 1,
211
};

powered by: WebSVN 2.1.0

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