aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-19 22:48:53 -0400
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2008-05-19 22:48:53 -0400
commit522493257f03b9a9021ac6b18a2c15c0af581b32 (patch)
tree3f066511631946919c703c4598b75f1364122f0e
parent0acc5e8a1d7caa74f644ac92cab2d958cf508d6e (diff)
Refactor Feather-Trace
- move platform dependent bits into arch/ - provide a default implementation (used for sparc64)
-rw-r--r--arch/x86/kernel/Makefile_323
-rw-r--r--arch/x86/kernel/ft_event.c104
-rw-r--r--include/asm-sparc64/feather_trace.h22
-rw-r--r--include/asm-x86/feather_trace.h104
-rw-r--r--include/litmus/feather_buffer.h14
-rw-r--r--include/litmus/feather_trace.h100
-rw-r--r--litmus/ft_event.c103
-rw-r--r--litmus/trace.c2
8 files changed, 277 insertions, 175 deletions
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index a7bc93c276..5f87f32ada 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 0000000000..b1d80c52d7
--- /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}
diff --git a/include/asm-sparc64/feather_trace.h b/include/asm-sparc64/feather_trace.h
new file mode 100644
index 0000000000..35ec70f178
--- /dev/null
+++ b/include/asm-sparc64/feather_trace.h
@@ -0,0 +1,22 @@
1#ifndef _ARCH_FEATHER_TRACE_H
2#define _ARCH_FEATHER_TRACE_H
3
4#include <asm/atomic.h>
5#include <asm/timex.h>
6
7static inline int fetch_and_inc(int *val)
8{
9 return atomic_add_ret(1, (atomic_t*) val) - 1;
10}
11
12static inline int fetch_and_dec(int *val)
13{
14 return atomic_sub_ret(1, (atomic_t*) val) + 1;
15}
16
17static inline unsigned long long ft_timestamp(void)
18{
19 return get_cycles();
20}
21
22#endif
diff --git a/include/asm-x86/feather_trace.h b/include/asm-x86/feather_trace.h
new file mode 100644
index 0000000000..253067ecee
--- /dev/null
+++ b/include/asm-x86/feather_trace.h
@@ -0,0 +1,104 @@
1#ifndef _ARCH_FEATHER_TRACE_H
2#define _ARCH_FEATHER_TRACE_H
3
4static inline int fetch_and_inc(int *val)
5{
6 int ret = 1;
7 __asm__ __volatile__("lock; xaddl %0, %1" : "+r" (ret), "+m" (*val) : : "memory" );
8 return ret;
9}
10
11static inline int fetch_and_dec(int *val)
12{
13 int ret = -1;
14 __asm__ __volatile__("lock; xaddl %0, %1" : "+r" (ret), "+m" (*val) : : "memory" );
15 return ret;
16}
17
18#define feather_callback __attribute__((regparm(0)))
19
20/* make the compiler reload any register that is not saved in
21 * a cdecl function call
22 */
23#define CLOBBER_LIST "memory", "cc", "eax", "ecx", "edx"
24
25#define ft_event(id, callback) \
26 __asm__ __volatile__( \
27 "1: jmp 2f \n\t" \
28 " call " #callback " \n\t" \
29 ".section __event_table, \"aw\" \n\t" \
30 ".long " #id ", 0, 1b, 2f \n\t" \
31 ".previous \n\t" \
32 "2: \n\t" \
33 : : : CLOBBER_LIST)
34
35#define ft_event0(id, callback) \
36 __asm__ __volatile__( \
37 "1: jmp 2f \n\t" \
38 " subl $4, %%esp \n\t" \
39 " movl $" #id ", (%%esp) \n\t" \
40 " call " #callback " \n\t" \
41 " addl $4, %%esp \n\t" \
42 ".section __event_table, \"aw\" \n\t" \
43 ".long " #id ", 0, 1b, 2f \n\t" \
44 ".previous \n\t" \
45 "2: \n\t" \
46 : : : CLOBBER_LIST)
47
48#define ft_event1(id, callback, param) \
49 __asm__ __volatile__( \
50 "1: jmp 2f \n\t" \
51 " subl $8, %%esp \n\t" \
52 " movl %0, 4(%%esp) \n\t" \
53 " movl $" #id ", (%%esp) \n\t" \
54 " call " #callback " \n\t" \
55 " addl $8, %%esp \n\t" \
56 ".section __event_table, \"aw\" \n\t" \
57 ".long " #id ", 0, 1b, 2f \n\t" \
58 ".previous \n\t" \
59 "2: \n\t" \
60 : : "r" (param) : CLOBBER_LIST)
61
62#define ft_event2(id, callback, param, param2) \
63 __asm__ __volatile__( \
64 "1: jmp 2f \n\t" \
65 " subl $12, %%esp \n\t" \
66 " movl %1, 8(%%esp) \n\t" \
67 " movl %0, 4(%%esp) \n\t" \
68 " movl $" #id ", (%%esp) \n\t" \
69 " call " #callback " \n\t" \
70 " addl $12, %%esp \n\t" \
71 ".section __event_table, \"aw\" \n\t" \
72 ".long " #id ", 0, 1b, 2f \n\t" \
73 ".previous \n\t" \
74 "2: \n\t" \
75 : : "r" (param), "r" (param2) : CLOBBER_LIST)
76
77
78#define ft_event3(id, callback, p, p2, p3) \
79 __asm__ __volatile__( \
80 "1: jmp 2f \n\t" \
81 " subl $16, %%esp \n\t" \
82 " movl %1, 12(%%esp) \n\t" \
83 " movl %1, 8(%%esp) \n\t" \
84 " movl %0, 4(%%esp) \n\t" \
85 " movl $" #id ", (%%esp) \n\t" \
86 " call " #callback " \n\t" \
87 " addl $16, %%esp \n\t" \
88 ".section __event_table, \"aw\" \n\t" \
89 ".long " #id ", 0, 1b, 2f \n\t" \
90 ".previous \n\t" \
91 "2: \n\t" \
92 : : "r" (p), "r" (p2), "r" (p3) : CLOBBER_LIST)
93
94
95static inline unsigned long long ft_timestamp(void)
96{
97 unsigned long long ret;
98 __asm__ __volatile__("rdtsc" : "=A" (ret));
99 return ret;
100}
101
102#define __ARCH_HAS_FEATHER_TRACE
103
104#endif
diff --git a/include/litmus/feather_buffer.h b/include/litmus/feather_buffer.h
index c788227905..6c18277fdf 100644
--- a/include/litmus/feather_buffer.h
+++ b/include/litmus/feather_buffer.h
@@ -3,20 +3,6 @@
3 3
4/* requires UINT_MAX and memcpy */ 4/* requires UINT_MAX and memcpy */
5 5
6static inline int fetch_and_inc(int *val)
7{
8 int ret = 1;
9 __asm__ __volatile__("lock; xaddl %0, %1" : "+r" (ret), "+m" (*val) : : "memory" );
10 return ret;
11}
12
13static inline int fetch_and_dec(int *val)
14{
15 int ret = -1;
16 __asm__ __volatile__("lock; xaddl %0, %1" : "+r" (ret), "+m" (*val) : : "memory" );
17 return ret;
18}
19
20#define SLOT_FREE 0 6#define SLOT_FREE 0
21#define SLOT_BUSY 1 7#define SLOT_BUSY 1
22#define SLOT_READY 2 8#define SLOT_READY 2
diff --git a/include/litmus/feather_trace.h b/include/litmus/feather_trace.h
index 5c37ea71ea..f4e59718a2 100644
--- a/include/litmus/feather_trace.h
+++ b/include/litmus/feather_trace.h
@@ -1,93 +1,37 @@
1#ifndef _FEATHER_TRACE_H_ 1#ifndef _FEATHER_TRACE_H_
2#define _FEATHER_TRACE_H_ 2#define _FEATHER_TRACE_H_
3 3
4#define feather_callback __attribute__((regparm(0))) 4#include <asm/feather_trace.h>
5 5
6/* make the compiler reload any register that is not saved in 6int ft_enable_event(unsigned long id);
7 * a cdecl function call 7int ft_disable_event(unsigned long id);
8 */ 8int ft_is_event_enabled(unsigned long id);
9#define CLOBBER_LIST "memory", "cc", "eax", "ecx", "edx" 9int ft_disable_all_events(void);
10 10
11#define ft_event(id, callback) \ 11#ifndef __ARCH_HAS_FEATHER_TRACE
12 __asm__ __volatile__( \ 12/* provide default implementation */
13 "1: jmp 2f \n\t" \
14 " call " #callback " \n\t" \
15 ".section __event_table, \"aw\" \n\t" \
16 ".long " #id ", 0, 1b, 2f \n\t" \
17 ".previous \n\t" \
18 "2: \n\t" \
19 : : : CLOBBER_LIST)
20 13
21#define ft_event0(id, callback) \ 14#define feather_callback
22 __asm__ __volatile__( \
23 "1: jmp 2f \n\t" \
24 " subl $4, %%esp \n\t" \
25 " movl $" #id ", (%%esp) \n\t" \
26 " call " #callback " \n\t" \
27 " addl $4, %%esp \n\t" \
28 ".section __event_table, \"aw\" \n\t" \
29 ".long " #id ", 0, 1b, 2f \n\t" \
30 ".previous \n\t" \
31 "2: \n\t" \
32 : : : CLOBBER_LIST)
33 15
34#define ft_event1(id, callback, param) \ 16#define MAX_EVENTS 1024
35 __asm__ __volatile__( \
36 "1: jmp 2f \n\t" \
37 " subl $8, %%esp \n\t" \
38 " movl %0, 4(%%esp) \n\t" \
39 " movl $" #id ", (%%esp) \n\t" \
40 " call " #callback " \n\t" \
41 " addl $8, %%esp \n\t" \
42 ".section __event_table, \"aw\" \n\t" \
43 ".long " #id ", 0, 1b, 2f \n\t" \
44 ".previous \n\t" \
45 "2: \n\t" \
46 : : "r" (param) : CLOBBER_LIST)
47 17
48#define ft_event2(id, callback, param, param2) \ 18extern int ft_events[MAX_EVENTS];
49 __asm__ __volatile__( \
50 "1: jmp 2f \n\t" \
51 " subl $12, %%esp \n\t" \
52 " movl %1, 8(%%esp) \n\t" \
53 " movl %0, 4(%%esp) \n\t" \
54 " movl $" #id ", (%%esp) \n\t" \
55 " call " #callback " \n\t" \
56 " addl $12, %%esp \n\t" \
57 ".section __event_table, \"aw\" \n\t" \
58 ".long " #id ", 0, 1b, 2f \n\t" \
59 ".previous \n\t" \
60 "2: \n\t" \
61 : : "r" (param), "r" (param2) : CLOBBER_LIST)
62 19
20#define ft_event(id, callback) \
21 if (ft_events[id]) callback();
63 22
64#define ft_event3(id, callback, p, p2, p3) \ 23#define ft_event0(id, callback) \
65 __asm__ __volatile__( \ 24 if (ft_events[id]) callback(id);
66 "1: jmp 2f \n\t" \
67 " subl $16, %%esp \n\t" \
68 " movl %1, 12(%%esp) \n\t" \
69 " movl %1, 8(%%esp) \n\t" \
70 " movl %0, 4(%%esp) \n\t" \
71 " movl $" #id ", (%%esp) \n\t" \
72 " call " #callback " \n\t" \
73 " addl $16, %%esp \n\t" \
74 ".section __event_table, \"aw\" \n\t" \
75 ".long " #id ", 0, 1b, 2f \n\t" \
76 ".previous \n\t" \
77 "2: \n\t" \
78 : : "r" (p), "r" (p2), "r" (p3) : CLOBBER_LIST)
79 25
26#define ft_event1(id, callback, param) \
27 if (ft_events[id]) callback(id), param;
80 28
81static inline unsigned long long ft_read_tsc(void) 29#define ft_event2(id, callback, param, param2) \
82{ 30 if (ft_events[id]) callback(id, param, param2);
83 unsigned long long ret; 31
84 __asm__ __volatile__("rdtsc" : "=A" (ret)); 32#define ft_event3(id, callback, p, p2, p3) \
85 return ret; 33 if (ft_events[id]) callback(id, p, p2, p3);
86} 34#endif
87 35
88int ft_enable_event(unsigned long id);
89int ft_disable_event(unsigned long id);
90int ft_is_event_enabled(unsigned long id);
91int ft_disable_all_events(void);
92 36
93#endif 37#endif
diff --git a/litmus/ft_event.c b/litmus/ft_event.c
index b1d80c52d7..6084b6d6b3 100644
--- a/litmus/ft_event.c
+++ b/litmus/ft_event.c
@@ -2,103 +2,42 @@
2 2
3#include <litmus/feather_trace.h> 3#include <litmus/feather_trace.h>
4 4
5/* the feather trace management functions assume 5#ifndef __ARCH_HAS_FEATHER_TRACE
6 * exclusive access to the event table 6/* provide dummy implementation */
7 */
8 7
9 8int ft_events[MAX_EVENTS];
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 9
24int ft_enable_event(unsigned long id) 10int ft_enable_event(unsigned long id)
25{ 11{
26 struct trace_event* te = __start___event_table; 12 if (id < MAX_EVENTS) {
27 int count = 0; 13 ft_events[id]++;
28 char* delta; 14 return 1;
29 unsigned char* instr; 15 } else
30 16 return 0;
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} 17}
46 18
47int ft_disable_event(unsigned long id) 19int ft_disable_event(unsigned long id)
48{ 20{
49 struct trace_event* te = __start___event_table; 21 if (id < MAX_EVENTS && ft_events[id]) {
50 int count = 0; 22 ft_events[id]--;
51 char* delta; 23 return 1;
52 unsigned char* instr; 24 } else
53 25 return 0;
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} 26}
69 27
70int ft_disable_all_events(void) 28int ft_disable_all_events(void)
71{ 29{
72 struct trace_event* te = __start___event_table; 30 int i;
73 int count = 0; 31
74 char* delta; 32 for (i = 0; i < MAX_EVENTS; i++)
75 unsigned char* instr; 33 ft_events[i] = 0;
76 34
77 while (te < __stop___event_table) { 35 return MAX_EVENTS;
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} 36}
93 37
94int ft_is_event_enabled(unsigned long id) 38int ft_is_event_enabled(unsigned long id)
95{ 39{
96 struct trace_event* te = __start___event_table; 40 return id < MAX_EVENTS && ft_events[id];
97
98 while (te < __stop___event_table) {
99 if (te->id == id)
100 return te->count;
101 te++;
102 }
103 return 0;
104} 41}
42
43#endif
diff --git a/litmus/trace.c b/litmus/trace.c
index 489e23e8a6..28cfa5b072 100644
--- a/litmus/trace.c
+++ b/litmus/trace.c
@@ -21,7 +21,7 @@ feather_callback void save_timestamp(unsigned long event)
21 struct timestamp *ts; 21 struct timestamp *ts;
22 if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) { 22 if (ft_buffer_start_write(trace_ts_buf, (void**) &ts)) {
23 ts->event = event; 23 ts->event = event;
24 ts->timestamp = ft_read_tsc(); 24 ts->timestamp = ft_timestamp();
25 ts->seq_no = seq_no; 25 ts->seq_no = seq_no;
26 ts->cpu = raw_smp_processor_id(); 26 ts->cpu = raw_smp_processor_id();
27 ft_buffer_finish_write(trace_ts_buf, ts); 27 ft_buffer_finish_write(trace_ts_buf, ts);