aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
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
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')
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c30
-rw-r--r--arch/blackfin/kernel/setup.c5
2 files changed, 27 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);
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 69cbc1a81201..8dc7ee1ef336 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -597,7 +597,12 @@ static __init void memory_setup(void)
597 } 597 }
598 598
599#ifdef CONFIG_MPU 599#ifdef CONFIG_MPU
600#if defined(CONFIG_ROMFS_ON_MTD) && defined(CONFIG_MTD_ROM)
601 page_mask_nelts = (((_ramend + ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE -
602 ASYNC_BANK0_BASE) >> PAGE_SHIFT) + 31) / 32;
603#else
600 page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32; 604 page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32;
605#endif
601 page_mask_order = get_order(3 * page_mask_nelts * sizeof(long)); 606 page_mask_order = get_order(3 * page_mask_nelts * sizeof(long));
602#endif 607#endif
603 608