aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/cplb-mpu
diff options
context:
space:
mode:
authorBernd Schmidt <bernds_cb1@t-online.de>2008-10-07 04:27:01 -0400
committerBryan Wu <cooloney@kernel.org>2008-10-07 04:27:01 -0400
commit5d2e321306f82550e6d354b3210a18b86bdb13c1 (patch)
treed86b51cbc3fd9778e323d0ac3252141a12885ae8 /arch/blackfin/kernel/cplb-mpu
parent0c7a6b2135c1bcb5139ca9ca87f292caafcb9410 (diff)
Blackfin arch: fixing bug - under IRQ stress, running applications may wrongly trigger an ICPLB miss and be killed
Disable IRQs while frobbing the CPLB registers, to avoid accessing the data in current_rwx_mask while it isn't covered by CPLBs. Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de> Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/kernel/cplb-mpu')
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index 99f2831e2964..5094677fd09e 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -322,9 +322,11 @@ int cplb_hdr(int seqstat, struct pt_regs *regs)
322void flush_switched_cplbs(void) 322void flush_switched_cplbs(void)
323{ 323{
324 int i; 324 int i;
325 unsigned long flags;
325 326
326 nr_cplb_flush++; 327 nr_cplb_flush++;
327 328
329 local_irq_save(flags);
328 disable_icplb(); 330 disable_icplb();
329 for (i = first_switched_icplb; i < MAX_CPLBS; i++) { 331 for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
330 icplb_tbl[i].data = 0; 332 icplb_tbl[i].data = 0;
@@ -338,6 +340,8 @@ void flush_switched_cplbs(void)
338 bfin_write32(DCPLB_DATA0 + i * 4, 0); 340 bfin_write32(DCPLB_DATA0 + i * 4, 0);
339 } 341 }
340 enable_dcplb(); 342 enable_dcplb();
343 local_irq_restore(flags);
344
341} 345}
342 346
343void set_mask_dcplbs(unsigned long *masks) 347void set_mask_dcplbs(unsigned long *masks)
@@ -345,10 +349,15 @@ void set_mask_dcplbs(unsigned long *masks)
345 int i; 349 int i;
346 unsigned long addr = (unsigned long)masks; 350 unsigned long addr = (unsigned long)masks;
347 unsigned long d_data; 351 unsigned long d_data;
348 current_rwx_mask = masks; 352 unsigned long flags;
349 353
350 if (!masks) 354 if (!masks) {
355 current_rwx_mask = masks;
351 return; 356 return;
357 }
358
359 local_irq_save(flags);
360 current_rwx_mask = masks;
352 361
353 d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; 362 d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
354#ifdef CONFIG_BFIN_DCACHE 363#ifdef CONFIG_BFIN_DCACHE
@@ -367,4 +376,5 @@ void set_mask_dcplbs(unsigned long *masks)
367 addr += PAGE_SIZE; 376 addr += PAGE_SIZE;
368 } 377 }
369 enable_dcplb(); 378 enable_dcplb();
379 local_irq_restore(flags);
370} 380}