diff options
author | Bernd Schmidt <bernds_cb1@t-online.de> | 2008-10-07 16:27:01 +0800 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-10-07 16:27:01 +0800 |
commit | 5d2e321306f82550e6d354b3210a18b86bdb13c1 (patch) | |
tree | d86b51cbc3fd9778e323d0ac3252141a12885ae8 | |
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>
-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 99f2831e296..5094677fd09 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) void flush_switched_cplbs(void) { int i; + unsigned long flags; nr_cplb_flush++; + local_irq_save(flags); disable_icplb(); for (i = first_switched_icplb; i < MAX_CPLBS; i++) { icplb_tbl[i].data = 0; @@ -338,6 +340,8 @@ void flush_switched_cplbs(void) bfin_write32(DCPLB_DATA0 + i * 4, 0); } enable_dcplb(); + local_irq_restore(flags); + } void set_mask_dcplbs(unsigned long *masks) @@ -345,10 +349,15 @@ void set_mask_dcplbs(unsigned long *masks) int i; unsigned long addr = (unsigned long)masks; unsigned long d_data; - current_rwx_mask = masks; + unsigned long flags; - if (!masks) + if (!masks) { + current_rwx_mask = masks; return; + } + + local_irq_save(flags); + current_rwx_mask = masks; d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; #ifdef CONFIG_BFIN_DCACHE @@ -367,4 +376,5 @@ void set_mask_dcplbs(unsigned long *masks) addr += PAGE_SIZE; } enable_dcplb(); + local_irq_restore(flags); } |