summary refs log tree commit diff
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorBernd Schmidt <bernds_cb1@t-online.de>2008-10-07 16:27:01 +0800
committerBryan Wu <cooloney@kernel.org>2008-10-07 16:27:01 +0800
commit5d2e321306f82550e6d354b3210a18b86bdb13c1 (patch)
treed86b51cbc3fd9778e323d0ac3252141a12885ae8 /arch/blackfin/kernel
parent0c7a6b2135c1bcb5139ca9ca87f292caafcb9410 (diff)
downloadlinux-5d2e321306f82550e6d354b3210a18b86bdb13c1.tar.gz
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')
-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)
 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);
 }