aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/cplb-mpu
diff options
context:
space:
mode:
authorBarry Song <barry.song@analog.com>2009-12-07 05:05:58 -0500
committerMike Frysinger <vapier@gentoo.org>2010-03-09 00:30:46 -0500
commite18e7dd33454f277b9438af66d25984362278021 (patch)
tree3c809ab2ebf8ad6276570f7eab238bd45e7216e8 /arch/blackfin/kernel/cplb-mpu
parentc9784ebb23be1e2ef23f537d6df04e0ea0206802 (diff)
Blackfin: fix MPU page permission masks overflow when dealing with async memory
Attempting to use the MPU while doing XIP out of parallel flash hooked up to the async memory bus would often result in random crashes as the MPU slowly corrupted memory. The fallout here is that the async banks gain MPU protection from user space too. So any accesses have to go through the mmap() interface rather than just using hardcoded pointers. Signed-off-by: Barry Song <barry.song@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/cplb-mpu')
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index 930c01c06813..d4cc53a0ef89 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -114,10 +114,15 @@ static noinline int dcplb_miss(unsigned int cpu)
114 d_data = L2_DMEMORY; 114 d_data = L2_DMEMORY;
115 } else if (addr >= physical_mem_end) { 115 } else if (addr >= physical_mem_end) {
116 if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { 116 if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) {
117 addr &= ~(4 * 1024 * 1024 - 1); 117 mask = current_rwx_mask[cpu];
118 d_data &= ~PAGE_SIZE_4KB; 118 if (mask) {
119 d_data |= PAGE_SIZE_4MB; 119 int page = (addr - (ASYNC_BANK0_BASE - _ramend)) >> PAGE_SHIFT;
120 d_data |= CPLB_USER_RD | CPLB_USER_WR; 120 int idx = page >> 5;
121 int bit = 1 << (page & 31);
122
123 if (mask[idx] & bit)
124 d_data |= CPLB_USER_RD;
125 }
121 } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH 126 } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
122 && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) { 127 && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) {
123 addr &= ~(1 * 1024 * 1024 - 1); 128 addr &= ~(1 * 1024 * 1024 - 1);
@@ -204,10 +209,19 @@ static noinline int icplb_miss(unsigned int cpu)
204 i_data = L2_IMEMORY; 209 i_data = L2_IMEMORY;
205 } else if (addr >= physical_mem_end) { 210 } else if (addr >= physical_mem_end) {
206 if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { 211 if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) {
207 addr &= ~(4 * 1024 * 1024 - 1); 212 if (!(status & FAULT_USERSUPV)) {
208 i_data &= ~PAGE_SIZE_4KB; 213 unsigned long *mask = current_rwx_mask[cpu];
209 i_data |= PAGE_SIZE_4MB; 214
210 i_data |= CPLB_USER_RD; 215 if (mask) {
216 int page = (addr - (ASYNC_BANK0_BASE - _ramend)) >> PAGE_SHIFT;
217 int idx = page >> 5;
218 int bit = 1 << (page & 31);
219
220 mask += 2 * page_mask_nelts;
221 if (mask[idx] & bit)
222 i_data |= CPLB_USER_RD;
223 }
224 }
211 } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH 225 } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
212 && (status & FAULT_USERSUPV)) { 226 && (status & FAULT_USERSUPV)) {
213 addr &= ~(1 * 1024 * 1024 - 1); 227 addr &= ~(1 * 1024 * 1024 - 1);