diff options
author | Namhoon Kim <namhoonk@cs.unc.edu> | 2014-11-03 21:53:47 -0500 |
---|---|---|
committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2014-11-03 21:53:47 -0500 |
commit | d0cc5b0897b74201fe1ca363ce1d980b5dbefff5 (patch) | |
tree | 870373a54076eb7ac8b9e246ea3bec004c0c7e87 | |
parent | 5c2112a210e8654d96e3f4c0395f1a326f28666f (diff) |
Added cache /proc
-rw-r--r-- | arch/arm/mach-imx/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 6 | ||||
-rw-r--r-- | include/litmus/cache_proc.h | 10 | ||||
-rw-r--r-- | litmus/cache_proc.c | 245 |
4 files changed, 263 insertions, 2 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 25366995d4df..02d0208dce31 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
@@ -107,13 +107,13 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o mach-imx6sx.o | |||
107 | AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a | 107 | AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a |
108 | obj-$(CONFIG_PM) += pm-imx6.o headsmp.o suspend-imx6.o | 108 | obj-$(CONFIG_PM) += pm-imx6.o headsmp.o suspend-imx6.o |
109 | 109 | ||
110 | ifeq ($(CONFIG_ARM_IMX6_CPUFREQ),y) | 110 | #ifeq ($(CONFIG_ARM_IMX6_CPUFREQ),y) |
111 | obj-y += busfreq-imx6.o | 111 | obj-y += busfreq-imx6.o |
112 | obj-$(CONFIG_SOC_IMX6Q) += ddr3_freq_imx6.o busfreq_ddr3.o | 112 | obj-$(CONFIG_SOC_IMX6Q) += ddr3_freq_imx6.o busfreq_ddr3.o |
113 | obj-$(CONFIG_SOC_IMX6SL) += lpddr2_freq_imx6.o busfreq_lpddr2.o imx6sl_wfi.o | 113 | obj-$(CONFIG_SOC_IMX6SL) += lpddr2_freq_imx6.o busfreq_lpddr2.o imx6sl_wfi.o |
114 | obj-$(CONFIG_SOC_IMX6SX) += ddr3_freq_imx6sx.o lpddr2_freq_imx6sx.o | 114 | obj-$(CONFIG_SOC_IMX6SX) += ddr3_freq_imx6sx.o lpddr2_freq_imx6sx.o |
115 | 115 | ||
116 | endif | 116 | #endif |
117 | 117 | ||
118 | 118 | ||
119 | # i.MX5 based machines | 119 | # i.MX5 based machines |
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c465faca51b0..5efe6b6e9d53 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <asm/hardware/cache-l2x0.h> | 27 | #include <asm/hardware/cache-l2x0.h> |
28 | #include "cache-aurora-l2.h" | 28 | #include "cache-aurora-l2.h" |
29 | 29 | ||
30 | #include <litmus/cache_proc.h> | ||
31 | |||
30 | #define CACHE_LINE_SIZE 32 | 32 | #define CACHE_LINE_SIZE 32 |
31 | 33 | ||
32 | static void __iomem *l2x0_base; | 34 | static void __iomem *l2x0_base; |
@@ -393,6 +395,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) | |||
393 | l2x0_unlock(cache_id); | 395 | l2x0_unlock(cache_id); |
394 | 396 | ||
395 | /* l2x0 controller is disabled */ | 397 | /* l2x0 controller is disabled */ |
398 | //aux |= (1 << 12); | ||
399 | //printk("AUX BIT = %08x\n", aux); | ||
396 | writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); | 400 | writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); |
397 | 401 | ||
398 | l2x0_inv_all(); | 402 | l2x0_inv_all(); |
@@ -420,6 +424,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) | |||
420 | printk(KERN_INFO "%s cache controller enabled\n", type); | 424 | printk(KERN_INFO "%s cache controller enabled\n", type); |
421 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", | 425 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", |
422 | ways, cache_id, aux, l2x0_size); | 426 | ways, cache_id, aux, l2x0_size); |
427 | |||
428 | litmus_setup_lockdown(l2x0_base, cache_id); | ||
423 | } | 429 | } |
424 | 430 | ||
425 | #ifdef CONFIG_OF | 431 | #ifdef CONFIG_OF |
diff --git a/include/litmus/cache_proc.h b/include/litmus/cache_proc.h new file mode 100644 index 000000000000..a7a740e7bc01 --- /dev/null +++ b/include/litmus/cache_proc.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef LITMUS_CACHE_PROC_H | ||
2 | #define LITMUS_CACHE_PROC_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | |||
6 | void litmus_setup_lockdown(void __iomem*, u32); | ||
7 | |||
8 | #endif | ||
9 | |||
10 | #endif | ||
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 | |||
20 | u32 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 | |||
40 | static void __iomem *cache_base; | ||
41 | static void __iomem *lockreg_d; | ||
42 | static void __iomem *lockreg_i; | ||
43 | |||
44 | static u32 cache_id; | ||
45 | |||
46 | struct mutex actlr_mutex; | ||
47 | struct mutex l2x0_prefetch_mutex; | ||
48 | struct mutex lockdown_proc; | ||
49 | |||
50 | static int min_usable_ways = 0; | ||
51 | static int max_usable_ways = 16; | ||
52 | static int zero = 0; | ||
53 | static 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 | |||
62 | int l2_usable_ways; | ||
63 | int lock_all; | ||
64 | int nr_lockregs; | ||
65 | |||
66 | static 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 | |||
78 | static 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 | |||
119 | void 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 | } | ||
139 | int 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 | |||
160 | out: | ||
161 | mutex_unlock(&lockdown_proc); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | int 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 | |||
188 | out: | ||
189 | mutex_unlock(&lockdown_proc); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static 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 | |||
216 | static struct ctl_table litmus_dir_table[] = { | ||
217 | { | ||
218 | .procname = "litmus", | ||
219 | .mode = 0555, | ||
220 | .child = cache_table, | ||
221 | }, | ||
222 | { } | ||
223 | }; | ||
224 | |||
225 | static struct ctl_table_header *litmus_sysctls; | ||
226 | |||
227 | static 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 | |||
241 | out: | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | module_init(litmus_sysctl_init); \ No newline at end of file | ||