diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-10-12 14:54:17 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-10-12 15:13:32 -0400 |
commit | c3817724690e4d8a6b26bdf2c4fb95c90ad62f05 (patch) | |
tree | c1ef886ecf9f33ec074d61b7f7e8efd2f6e37502 /litmus/lockdown.c | |
parent | 1278828e332e1c697c35110dbe8dd2f0b18c80c5 (diff) |
Fix lockdown.
Signed-off-by: Christopher Kenna <cjk@cs.unc.edu>
Diffstat (limited to 'litmus/lockdown.c')
-rw-r--r-- | litmus/lockdown.c | 92 |
1 files changed, 80 insertions, 12 deletions
diff --git a/litmus/lockdown.c b/litmus/lockdown.c index b8c25006bc4f..1a38be23674f 100644 --- a/litmus/lockdown.c +++ b/litmus/lockdown.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
6 | #include <linux/time.h> | ||
6 | 7 | ||
7 | #include <linux/smp.h> /* smp_call_func */ | 8 | #include <linux/smp.h> /* smp_call_func */ |
8 | #include <asm/processor.h> /* cpu relax */ | 9 | #include <asm/processor.h> /* cpu relax */ |
@@ -54,7 +55,6 @@ static u32 read_in_page(u32 lock_val, | |||
54 | " .align 5\n" | 55 | " .align 5\n" |
55 | " str %[lockval], [%[cachereg]]\n" | 56 | " str %[lockval], [%[cachereg]]\n" |
56 | "1: ldr %[tmp], [%[addr]], #32 @ 32 bytes = 1 cache line\n" | 57 | "1: ldr %[tmp], [%[addr]], #32 @ 32 bytes = 1 cache line\n" |
57 | " add %[val], %[val], %[tmp]\n" | ||
58 | " cmp %[addr], %[end]\n" | 58 | " cmp %[addr], %[end]\n" |
59 | " bne 1b\n" | 59 | " bne 1b\n" |
60 | " str %[unlockval], [%[cachereg]]\n" | 60 | " str %[unlockval], [%[cachereg]]\n" |
@@ -72,6 +72,16 @@ static u32 read_in_page(u32 lock_val, | |||
72 | } | 72 | } |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * Ensure that this page is not in the L1 or L2 cache. | ||
76 | * Since the L1 cache is VIPT and the L2 cache is PIPT, we can use either the | ||
77 | * kernel or user vaddr. | ||
78 | */ | ||
79 | void color_flush_page(void *vaddr) | ||
80 | { | ||
81 | v7_flush_kern_dcache_area(vaddr, PAGE_SIZE); | ||
82 | } | ||
83 | |||
84 | /* | ||
75 | * unlocked[i] : allocation can occur in way i | 85 | * unlocked[i] : allocation can occur in way i |
76 | * | 86 | * |
77 | * 0 = allocation can occur in the corresponding way | 87 | * 0 = allocation can occur in the corresponding way |
@@ -157,15 +167,79 @@ static void test_lockdown(void *ignore) | |||
157 | printk("End lockdown test.\n"); | 167 | printk("End lockdown test.\n"); |
158 | } | 168 | } |
159 | 169 | ||
170 | static long update_timeval(struct timespec lhs, struct timespec rhs) | ||
171 | { | ||
172 | long val; | ||
173 | struct timespec ts; | ||
174 | |||
175 | ts = timespec_sub(rhs, lhs); | ||
176 | val = ts.tv_sec*NSEC_PER_SEC + ts.tv_nsec; | ||
177 | |||
178 | return val; | ||
179 | } | ||
180 | |||
181 | #define TRIALS 1000 | ||
182 | static int perf_test(void) { | ||
183 | struct timespec before, after; | ||
184 | struct page *page; | ||
185 | void *vaddr; | ||
186 | u32 *data; | ||
187 | long time; | ||
188 | int i; | ||
189 | |||
190 | page = alloc_page(GFP_HIGHUSER | __GFP_MOVABLE); | ||
191 | if (!page) { | ||
192 | printk(KERN_WARNING "No memory\n"); | ||
193 | return -ENOMEM; | ||
194 | } | ||
195 | |||
196 | vaddr = phys_to_virt(page_to_phys(page)); | ||
197 | data = (u32*) vaddr; | ||
198 | |||
199 | getnstimeofday(&before); | ||
200 | barrier(); | ||
201 | for (i = 0; i < TRIALS; i++) { | ||
202 | color_flush_page(vaddr); | ||
203 | } | ||
204 | barrier(); | ||
205 | getnstimeofday(&after); | ||
206 | time = update_timeval(before, after); | ||
207 | printk("Average for flushes without re-reading: %ld\n", time / TRIALS); | ||
208 | |||
209 | read_in_page(unlocked[0], UNLOCK_ALL, vaddr, vaddr + PAGE_SIZE); | ||
210 | barrier(); | ||
211 | getnstimeofday(&before); | ||
212 | barrier(); | ||
213 | for (i = 0; i < TRIALS; i++) { | ||
214 | read_in_page(unlocked[0], UNLOCK_ALL, vaddr, vaddr + PAGE_SIZE); | ||
215 | } | ||
216 | barrier(); | ||
217 | getnstimeofday(&after); | ||
218 | time = update_timeval(before, after); | ||
219 | printk("Average for read in (no flush): %ld\n", time / TRIALS); | ||
220 | |||
221 | getnstimeofday(&before); | ||
222 | barrier(); | ||
223 | for (i = 0; i < TRIALS; i++) { | ||
224 | read_in_page(unlocked[0], UNLOCK_ALL, vaddr, vaddr + PAGE_SIZE); | ||
225 | color_flush_page(vaddr); | ||
226 | } | ||
227 | barrier(); | ||
228 | getnstimeofday(&after); | ||
229 | time = update_timeval(before, after); | ||
230 | printk("Average for read in and then flush: %ld\n", time / TRIALS); | ||
231 | |||
232 | free_page(page); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
160 | #define LOCKREG_TEST_VAL 0x00000002 | 236 | #define LOCKREG_TEST_VAL 0x00000002 |
161 | #define PREFETCH_SUM_TEST_VAL 65024 /* = 0 + 8 + ... + 127 */ | ||
162 | int litmus_test_prefetch(struct ctl_table *table, int write, void __user *buffer, | 237 | int litmus_test_prefetch(struct ctl_table *table, int write, void __user *buffer, |
163 | size_t *lenp, loff_t *ppos) | 238 | size_t *lenp, loff_t *ppos) |
164 | { | 239 | { |
165 | struct page *page; | 240 | struct page *page; |
166 | void *vaddr; | 241 | void *vaddr; |
167 | u32 *data; | 242 | u32 *data; |
168 | u32 sum = 0; | ||
169 | int i; | 243 | int i; |
170 | 244 | ||
171 | if (!write) | 245 | if (!write) |
@@ -183,14 +257,6 @@ int litmus_test_prefetch(struct ctl_table *table, int write, void __user *buffer | |||
183 | for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) | 257 | for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) |
184 | data[i] = i; | 258 | data[i] = i; |
185 | 259 | ||
186 | sum = read_in_page(UNLOCK_ALL, LOCKREG_TEST_VAL, vaddr, vaddr + PAGE_SIZE); | ||
187 | if (PREFETCH_SUM_TEST_VAL != sum) { | ||
188 | printk("%s: Expected sum %u but got %u!\n", __FUNCTION__, | ||
189 | PREFETCH_SUM_TEST_VAL, sum); | ||
190 | } else { | ||
191 | printk("%s: Prefetch test passed.\n", __FUNCTION__); | ||
192 | } | ||
193 | |||
194 | if (LOCKREG_TEST_VAL != readl_relaxed(lockreg_d)) { | 260 | if (LOCKREG_TEST_VAL != readl_relaxed(lockreg_d)) { |
195 | printk("%s: Expected lockreg value 0x%8x but got 0x%8x!\n", | 261 | printk("%s: Expected lockreg value 0x%8x but got 0x%8x!\n", |
196 | __FUNCTION__, LOCKREG_TEST_VAL, | 262 | __FUNCTION__, LOCKREG_TEST_VAL, |
@@ -202,7 +268,9 @@ int litmus_test_prefetch(struct ctl_table *table, int write, void __user *buffer | |||
202 | 268 | ||
203 | writel_relaxed(UNLOCK_ALL, ld_d_reg(i)); | 269 | writel_relaxed(UNLOCK_ALL, ld_d_reg(i)); |
204 | 270 | ||
205 | free_page(page_to_pfn(page)); | 271 | free_page(page); |
272 | |||
273 | perf_test(); | ||
206 | 274 | ||
207 | return 0; | 275 | return 0; |
208 | } | 276 | } |