diff options
author | Bernd Schmidt <bernds_cb1@t-online.de> | 2008-10-07 04:27:01 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-10-07 04:27:01 -0400 |
commit | 5d2e321306f82550e6d354b3210a18b86bdb13c1 (patch) | |
tree | d86b51cbc3fd9778e323d0ac3252141a12885ae8 /arch | |
parent | 0c7a6b2135c1bcb5139ca9ca87f292caafcb9410 (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')
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 14 |
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) | |||
322 | void flush_switched_cplbs(void) | 322 | void 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 | ||
343 | void set_mask_dcplbs(unsigned long *masks) | 347 | void 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 | } |