12b8274f |
1 | /* test-nop-speed.c |
2 | * |
3 | */ |
4 | |
5 | #include <linux/module.h> |
6 | #include <linux/proc_fs.h> |
7 | #include <linux/sched.h> |
8 | #include <linux/timex.h> |
9 | #include <linux/marker.h> |
10 | #include <asm/ptrace.h> |
11 | |
7283e5cf |
12 | #define NR_TESTS 10000000 |
12b8274f |
13 | |
99bf728c |
14 | int var, var2; |
15 | |
12b8274f |
16 | struct proc_dir_entry *pentry = NULL; |
17 | |
18 | void empty(void) |
19 | { |
20 | asm volatile (""); |
99bf728c |
21 | var += 50; |
22 | var /= 10; |
23 | var *= var2; |
12b8274f |
24 | } |
25 | |
26 | void twobytesjump(void) |
27 | { |
28 | asm volatile ("jmp 1f\n\t" |
29 | ".byte 0x00, 0x00, 0x00\n\t" |
30 | "1:\n\t"); |
99bf728c |
31 | var += 50; |
32 | var /= 10; |
33 | var *= var2; |
12b8274f |
34 | } |
35 | |
36 | void fivebytesjump(void) |
37 | { |
38 | asm (".byte 0xe9, 0x00, 0x00, 0x00, 0x00\n\t"); |
99bf728c |
39 | var += 50; |
40 | var /= 10; |
41 | var *= var2; |
12b8274f |
42 | } |
43 | |
44 | void threetwonops(void) |
45 | { |
46 | asm (".byte 0x66,0x66,0x90,0x66,0x90\n\t"); |
99bf728c |
47 | var += 50; |
48 | var /= 10; |
49 | var *= var2; |
12b8274f |
50 | } |
51 | |
52 | void fivebytesnop(void) |
53 | { |
54 | asm (".byte 0x66,0x66,0x66,0x66,0x90\n\t"); |
99bf728c |
55 | var += 50; |
56 | var /= 10; |
57 | var *= var2; |
12b8274f |
58 | } |
59 | |
60 | void fivebytespsixnop(void) |
61 | { |
62 | asm (".byte 0x0f,0x1f,0x44,0x00,0\n\t"); |
99bf728c |
63 | var += 50; |
64 | var /= 10; |
65 | var *= var2; |
12b8274f |
66 | } |
67 | |
68 | void perform_test(const char *name, void (*callback)(void)) |
69 | { |
70 | unsigned int i; |
71 | cycles_t cycles1, cycles2; |
72 | unsigned long flags; |
73 | |
74 | local_irq_save(flags); |
75 | rdtsc_barrier(); |
76 | cycles1 = get_cycles(); |
77 | rdtsc_barrier(); |
78 | for(i=0; i<NR_TESTS; i++) { |
79 | callback(); |
80 | } |
81 | rdtsc_barrier(); |
82 | cycles2 = get_cycles(); |
83 | rdtsc_barrier(); |
84 | local_irq_restore(flags); |
85 | printk("test %s cycles : %llu\n", name, cycles2-cycles1); |
86 | } |
87 | |
88 | static int my_open(struct inode *inode, struct file *file) |
89 | { |
90 | printk("NR_TESTS %d\n", NR_TESTS); |
91 | |
92 | perform_test("empty", empty); |
93 | perform_test("2-bytes jump", twobytesjump); |
94 | perform_test("5-bytes jump", fivebytesjump); |
95 | perform_test("3/2 nops", threetwonops); |
96 | perform_test("5-bytes nop with long prefix", fivebytesnop); |
97 | perform_test("5-bytes P6 nop", fivebytespsixnop); |
98 | |
99 | return -EPERM; |
100 | } |
101 | |
102 | |
103 | static struct file_operations my_operations = { |
104 | .open = my_open, |
105 | }; |
106 | |
107 | int init_module(void) |
108 | { |
109 | pentry = create_proc_entry("testnops", 0444, NULL); |
110 | if (pentry) |
111 | pentry->proc_fops = &my_operations; |
112 | |
113 | return 0; |
114 | } |
115 | |
116 | void cleanup_module(void) |
117 | { |
118 | remove_proc_entry("testnops", NULL); |
119 | } |
120 | |
121 | MODULE_LICENSE("GPL"); |
122 | MODULE_AUTHOR("Mathieu Desnoyers"); |
d7ff2f7d |
123 | MODULE_DESCRIPTION("NOP Test"); |