diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/alpha/oprofile/op_model_ev4.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/alpha/oprofile/op_model_ev4.c')
-rw-r--r-- | arch/alpha/oprofile/op_model_ev4.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c new file mode 100644 index 000000000000..80d764dbf22f --- /dev/null +++ b/arch/alpha/oprofile/op_model_ev4.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /** | ||
2 | * @file arch/alpha/oprofile/op_model_ev4.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 | static void | ||
22 | ev4_reg_setup(struct op_register_config *reg, | ||
23 | struct op_counter_config *ctr, | ||
24 | struct op_system_config *sys) | ||
25 | { | ||
26 | unsigned long ctl = 0, count, hilo; | ||
27 | |||
28 | /* Select desired events. We've mapped the event numbers | ||
29 | such that they fit directly into the event selection fields. | ||
30 | |||
31 | Note that there is no "off" setting. In both cases we select | ||
32 | the EXTERNAL event source, hoping that it'll be the lowest | ||
33 | frequency, and set the frequency counter to LOW. The interrupts | ||
34 | for these "disabled" counter overflows are ignored by the | ||
35 | interrupt handler. | ||
36 | |||
37 | This is most irritating, because the hardware *can* enable and | ||
38 | disable the interrupts for these counters independently, but the | ||
39 | wrperfmon interface doesn't allow it. */ | ||
40 | |||
41 | ctl |= (ctr[0].enabled ? ctr[0].event << 8 : 14 << 8); | ||
42 | ctl |= (ctr[1].enabled ? (ctr[1].event - 16) << 32 : 7ul << 32); | ||
43 | |||
44 | /* EV4 can not read or write its counter registers. The only | ||
45 | thing one can do at all is see if you overflow and get an | ||
46 | interrupt. We can set the width of the counters, to some | ||
47 | extent. Take the interrupt count selected by the user, | ||
48 | map it onto one of the possible values, and write it back. */ | ||
49 | |||
50 | count = ctr[0].count; | ||
51 | if (count <= 4096) | ||
52 | count = 4096, hilo = 1; | ||
53 | else | ||
54 | count = 65536, hilo = 0; | ||
55 | ctr[0].count = count; | ||
56 | ctl |= (ctr[0].enabled && hilo) << 3; | ||
57 | |||
58 | count = ctr[1].count; | ||
59 | if (count <= 256) | ||
60 | count = 256, hilo = 1; | ||
61 | else | ||
62 | count = 4096, hilo = 0; | ||
63 | ctr[1].count = count; | ||
64 | ctl |= (ctr[1].enabled && hilo); | ||
65 | |||
66 | reg->mux_select = ctl; | ||
67 | |||
68 | /* Select performance monitoring options. */ | ||
69 | /* ??? Need to come up with some mechanism to trace only | ||
70 | selected processes. EV4 does not have a mechanism to | ||
71 | select kernel or user mode only. For now, enable always. */ | ||
72 | reg->proc_mode = 0; | ||
73 | |||
74 | /* Frequency is folded into mux_select for EV4. */ | ||
75 | reg->freq = 0; | ||
76 | |||
77 | /* See above regarding no writes. */ | ||
78 | reg->reset_values = 0; | ||
79 | reg->need_reset = 0; | ||
80 | |||
81 | } | ||
82 | |||
83 | /* Program all of the registers in preparation for enabling profiling. */ | ||
84 | |||
85 | static void | ||
86 | ev4_cpu_setup(void *x) | ||
87 | { | ||
88 | struct op_register_config *reg = x; | ||
89 | |||
90 | wrperfmon(2, reg->mux_select); | ||
91 | wrperfmon(3, reg->proc_mode); | ||
92 | } | ||
93 | |||
94 | static void | ||
95 | ev4_handle_interrupt(unsigned long which, struct pt_regs *regs, | ||
96 | struct op_counter_config *ctr) | ||
97 | { | ||
98 | /* EV4 can't properly disable counters individually. | ||
99 | Discard "disabled" events now. */ | ||
100 | if (!ctr[which].enabled) | ||
101 | return; | ||
102 | |||
103 | /* Record the sample. */ | ||
104 | oprofile_add_sample(regs, which); | ||
105 | } | ||
106 | |||
107 | |||
108 | struct op_axp_model op_model_ev4 = { | ||
109 | .reg_setup = ev4_reg_setup, | ||
110 | .cpu_setup = ev4_cpu_setup, | ||
111 | .reset_ctr = NULL, | ||
112 | .handle_interrupt = ev4_handle_interrupt, | ||
113 | .cpu_type = "alpha/ev4", | ||
114 | .num_counters = 2, | ||
115 | .can_set_proc_mode = 0, | ||
116 | }; | ||