aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/lockdown.c
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-10-12 14:54:17 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-10-12 15:13:32 -0400
commitc3817724690e4d8a6b26bdf2c4fb95c90ad62f05 (patch)
treec1ef886ecf9f33ec074d61b7f7e8efd2f6e37502 /litmus/lockdown.c
parent1278828e332e1c697c35110dbe8dd2f0b18c80c5 (diff)
Fix lockdown.
Signed-off-by: Christopher Kenna <cjk@cs.unc.edu>
Diffstat (limited to 'litmus/lockdown.c')
-rw-r--r--litmus/lockdown.c92
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 */
79void 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
170static 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
182static 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 */
162int litmus_test_prefetch(struct ctl_table *table, int write, void __user *buffer, 237int 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}