diff options
author | Barry Song <barry.song@analog.com> | 2009-12-07 05:05:58 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-03-09 00:30:46 -0500 |
commit | e18e7dd33454f277b9438af66d25984362278021 (patch) | |
tree | 3c809ab2ebf8ad6276570f7eab238bd45e7216e8 /arch/blackfin/kernel/cplb-mpu | |
parent | c9784ebb23be1e2ef23f537d6df04e0ea0206802 (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.c | 30 |
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); |