aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/Makefile_323
-rw-r--r--arch/x86/kernel/ft_event.c104
2 files changed, 107 insertions, 0 deletions
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c27662..5f87f32ada6f 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -49,6 +49,9 @@ obj-y += pcspeaker.o
49 49
50obj-$(CONFIG_SCx200) += scx200_32.o 50obj-$(CONFIG_SCx200) += scx200_32.o
51 51
52obj-$(CONFIG_FEATHER_TRACE) += ft_event.o
53
54
52# vsyscall_32.o contains the vsyscall DSO images as __initdata. 55# vsyscall_32.o contains the vsyscall DSO images as __initdata.
53# We must build both images before we can assemble it. 56# We must build both images before we can assemble it.
54# Note: kbuild does not track this dependency due to usage of .incbin 57# Note: kbuild does not track this dependency due to usage of .incbin
diff --git a/arch/x86/kernel/ft_event.c b/arch/x86/kernel/ft_event.c
new file mode 100644
index 000000000000..b1d80c52d793
--- /dev/null
+++ b/arch/x86/kernel/ft_event.c
@@ -0,0 +1,104 @@
1#include <linux/types.h>
2
3#include <litmus/feather_trace.h>
4
5/* the feather trace management functions assume
6 * exclusive access to the event table
7 */
8
9
10#define BYTE_JUMP 0xeb
11#define BYTE_JUMP_LEN 0x02
12
13/* for each event, there is an entry in the event table */
14struct trace_event {
15 long id;
16 long count;
17 long start_addr;
18 long end_addr;
19};
20
21extern struct trace_event __start___event_table[];
22extern struct trace_event __stop___event_table[];
23
24int ft_enable_event(unsigned long id)
25{
26 struct trace_event* te = __start___event_table;
27 int count = 0;
28 char* delta;
29 unsigned char* instr;
30
31 while (te < __stop___event_table) {
32 if (te->id == id && ++te->count == 1) {
33 instr = (unsigned char*) te->start_addr;
34 /* make sure we don't clobber something wrong */
35 if (*instr == BYTE_JUMP) {
36 delta = (((unsigned char*) te->start_addr) + 1);
37 *delta = 0;
38 }
39 }
40 if (te->id == id)
41 count++;
42 te++;
43 }
44 return count;
45}
46
47int ft_disable_event(unsigned long id)
48{
49 struct trace_event* te = __start___event_table;
50 int count = 0;
51 char* delta;
52 unsigned char* instr;
53
54 while (te < __stop___event_table) {
55 if (te->id == id && --te->count == 0) {
56 instr = (unsigned char*) te->start_addr;
57 if (*instr == BYTE_JUMP) {
58 delta = (((unsigned char*) te->start_addr) + 1);
59 *delta = te->end_addr - te->start_addr -
60 BYTE_JUMP_LEN;
61 }
62 }
63 if (te->id == id)
64 count++;
65 te++;
66 }
67 return count;
68}
69
70int ft_disable_all_events(void)
71{
72 struct trace_event* te = __start___event_table;
73 int count = 0;
74 char* delta;
75 unsigned char* instr;
76
77 while (te < __stop___event_table) {
78 if (te->count) {
79 instr = (unsigned char*) te->start_addr;
80 if (*instr == BYTE_JUMP) {
81 delta = (((unsigned char*) te->start_addr)
82 + 1);
83 *delta = te->end_addr - te->start_addr -
84 BYTE_JUMP_LEN;
85 te->count = 0;
86 count++;
87 }
88 }
89 te++;
90 }
91 return count;
92}
93
94int ft_is_event_enabled(unsigned long id)
95{
96 struct trace_event* te = __start___event_table;
97
98 while (te < __stop___event_table) {
99 if (te->id == id)
100 return te->count;
101 te++;
102 }
103 return 0;
104}