aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/cache_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'litmus/cache_proc.c')
-rw-r--r--litmus/cache_proc.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/litmus/cache_proc.c b/litmus/cache_proc.c
new file mode 100644
index 000000000000..4425bfb8bbd4
--- /dev/null
+++ b/litmus/cache_proc.c
@@ -0,0 +1,245 @@
1#include <linux/init.h>
2#include <linux/types.h>
3#include <linux/kernel.h>
4#include <linux/module.h>
5#include <linux/sysctl.h>
6#include <linux/slab.h>
7#include <linux/io.h>
8#include <linux/mutex.h>
9
10#include <litmus/litmus_proc.h>
11#include <litmus/sched_trace.h>
12
13#include <asm/hardware/cache-l2x0.h>
14#include <asm/cacheflush.h>
15
16#define UNLOCK_ALL 0x00000000 /* allocation in any way */
17#define LOCK_ALL (~UNLOCK_ALL)
18#define MAX_NR_WAYS 16
19
20u32 nr_unlocked_way[MAX_NR_WAYS+1] = {
21 0xFFFFFFFF, /* all ways are locked. usable = 0*/
22 0xFFFFFFFE, /* way ~0 unlocked. usable = 1 */
23 0xFFFFFFFC,
24 0xFFFFFFF8,
25 0xFFFFFFF0,
26 0xFFFFFFE0,
27 0xFFFFFFC0,
28 0xFFFFFF80,
29 0xFFFFFF00,
30 0xFFFFFE00,
31 0xFFFFFC00,
32 0xFFFFF800,
33 0xFFFFF000,
34 0xFFFFE000,
35 0xFFFFC000,
36 0xFFFF8000,
37 0xFFFF0000, /* way ~15 unlocked. usable = 16 */
38};
39
40static void __iomem *cache_base;
41static void __iomem *lockreg_d;
42static void __iomem *lockreg_i;
43
44static u32 cache_id;
45
46struct mutex actlr_mutex;
47struct mutex l2x0_prefetch_mutex;
48struct mutex lockdown_proc;
49
50static int min_usable_ways = 0;
51static int max_usable_ways = 16;
52static int zero = 0;
53static int one = 1;
54
55#define ld_d_reg(cpu) ({ int __cpu = cpu; \
56 void __iomem *__v = cache_base + L2X0_LOCKDOWN_WAY_D_BASE + \
57 __cpu * L2X0_LOCKDOWN_STRIDE; __v; })
58#define ld_i_reg(cpu) ({ int __cpu = cpu; \
59 void __iomem *__v = cache_base + L2X0_LOCKDOWN_WAY_I_BASE + \
60 __cpu * L2X0_LOCKDOWN_STRIDE; __v; })
61
62int l2_usable_ways;
63int lock_all;
64int nr_lockregs;
65
66static void print_lockdown_registers(void)
67{
68 int i;
69
70 for (i = 0; i < nr_lockregs; i++) {
71 printk("Lockdown Data CPU %2d: 0x%8x\n",
72 i, readl_relaxed(ld_d_reg(i)));
73 printk("Lockdown Inst CPU %2d: 0x%8x\n",
74 i, readl_relaxed(ld_i_reg(i)));
75 }
76}
77
78static void test_lockdown(void *ignore)
79{
80 int i;
81
82 printk("Start lockdown test on CPU %d.\n", smp_processor_id());
83
84 for (i = 0; i < nr_lockregs; i++) {
85 printk("CPU %2d data reg: 0x%8p\n", i, ld_d_reg(i));
86 printk("CPU %2d inst reg: 0x%8p\n", i, ld_i_reg(i));
87 }
88
89 printk("Lockdown initial state:\n");
90 print_lockdown_registers();
91 printk("---\n");
92
93 for (i = 0; i < nr_lockregs; i++) {
94 writel_relaxed(1, ld_d_reg(i));
95 writel_relaxed(2, ld_i_reg(i));
96 }
97 printk("Lockdown all data=1 instr=2:\n");
98 print_lockdown_registers();
99 printk("---\n");
100
101 for (i = 0; i < nr_lockregs; i++) {
102 writel_relaxed((1 << i), ld_d_reg(i));
103 writel_relaxed(((1 << 8) >> i), ld_i_reg(i));
104 }
105 printk("Lockdown varies:\n");
106 print_lockdown_registers();
107 printk("---\n");
108
109 for (i = 0; i < nr_lockregs; i++) {
110 writel_relaxed(UNLOCK_ALL, ld_d_reg(i));
111 writel_relaxed(UNLOCK_ALL, ld_i_reg(i));
112 }
113 printk("Lockdown all zero:\n");
114 print_lockdown_registers();
115
116 printk("End lockdown test.\n");
117}
118
119void litmus_setup_lockdown(void __iomem *base, u32 id)
120{
121 cache_base = base;
122 cache_id = id;
123 lockreg_d = cache_base + L2X0_LOCKDOWN_WAY_D_BASE;
124 lockreg_i = cache_base + L2X0_LOCKDOWN_WAY_I_BASE;
125
126 if (L2X0_CACHE_ID_PART_L310 == (cache_id & L2X0_CACHE_ID_PART_MASK)) {
127 nr_lockregs = 8;
128 } else {
129 printk("Unknown cache ID!\n");
130 nr_lockregs = 1;
131 }
132
133 mutex_init(&actlr_mutex);
134 mutex_init(&l2x0_prefetch_mutex);
135 mutex_init(&lockdown_proc);
136
137 test_lockdown(NULL);
138}
139int lock_all_handler(struct ctl_table *table, int write, void __user *buffer,
140 size_t *lenp, loff_t *ppos)
141{
142 int ret = 0, i;
143
144 mutex_lock(&lockdown_proc);
145
146 flush_cache_all();
147
148 ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
149 if (ret)
150 goto out;
151
152 if (write && lock_all == 1) {
153 for (i = 0; i < nr_lockregs; i++) {
154 writel_relaxed(nr_unlocked_way[0], ld_d_reg(i));
155 writel_relaxed(nr_unlocked_way[0], ld_i_reg(i));
156 }
157 print_lockdown_registers();
158 }
159
160out:
161 mutex_unlock(&lockdown_proc);
162 return ret;
163}
164
165int l2_usable_ways_handler(struct ctl_table *table, int write, void __user *buffer,
166 size_t *lenp, loff_t *ppos)
167{
168 int ret = 0, i = 0;
169
170 mutex_lock(&lockdown_proc);
171
172 flush_cache_all();
173
174 ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
175 if (ret)
176 goto out;
177
178 TRACE_CUR("l2_usable_ways : %d\n", l2_usable_ways);
179
180 if (write) {
181 //for (i = 0; i < nr_lockregs; i++) {
182 writel_relaxed(nr_unlocked_way[l2_usable_ways], ld_d_reg(i));
183 writel_relaxed(nr_unlocked_way[l2_usable_ways], ld_i_reg(i));
184 //}
185 print_lockdown_registers();
186 }
187
188out:
189 mutex_unlock(&lockdown_proc);
190 return ret;
191}
192
193static struct ctl_table cache_table[] =
194{
195 {
196 .procname = "l2_usable_ways",
197 .mode = 0666,
198 .proc_handler = l2_usable_ways_handler,
199 .data = &l2_usable_ways,
200 .maxlen = sizeof(l2_usable_ways),
201 .extra1 = &min_usable_ways,
202 .extra2 = &max_usable_ways,
203 },
204 {
205 .procname = "lock_all",
206 .mode = 0666,
207 .proc_handler = lock_all_handler,
208 .data = &lock_all,
209 .maxlen = sizeof(lock_all),
210 .extra1 = &zero,
211 .extra2 = &one,
212 },
213 { }
214};
215
216static struct ctl_table litmus_dir_table[] = {
217 {
218 .procname = "litmus",
219 .mode = 0555,
220 .child = cache_table,
221 },
222 { }
223};
224
225static struct ctl_table_header *litmus_sysctls;
226
227static int __init litmus_sysctl_init(void)
228{
229 int ret = 0;
230
231 printk(KERN_INFO "Registering LITMUS^RT proc sysctl.\n");
232 litmus_sysctls = register_sysctl_table(litmus_dir_table);
233 if (!litmus_sysctls) {
234 printk(KERN_WARNING "Could not register LITMUS^RT sysctl.\n");
235 ret = -EFAULT;
236 goto out;
237 }
238
239 l2_usable_ways = 16;
240
241out:
242 return ret;
243}
244
245module_init(litmus_sysctl_init); \ No newline at end of file