diff options
author | Bernd Schmidt <bernds_cb1@t-online.de> | 2008-04-23 14:58:26 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-04-23 14:58:26 -0400 |
commit | 1ebc723cf04b55e7aeeec2e758293575d29a9c2b (patch) | |
tree | ce070f280b8f3f4c2fbf52c51af3b67c0af99502 /arch/blackfin/kernel | |
parent | d56daae9bec92ae4b0c115db787a0fcc4c17b381 (diff) |
[Blackfin] arch: support the reserved memory region in the MPU code
Pointed-out-by: Mike Frysinger <vapier.adi@gmail.com>
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.c | 64 |
1 files changed, 41 insertions, 23 deletions
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index f23bba5c6e63..3377cbf28fb4 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c | |||
@@ -146,14 +146,16 @@ static noinline int dcplb_miss(void) | |||
146 | 146 | ||
147 | d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; | 147 | d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; |
148 | #ifdef CONFIG_BFIN_DCACHE | 148 | #ifdef CONFIG_BFIN_DCACHE |
149 | if (addr < _ramend - DMA_UNCACHED_REGION) { | 149 | if (addr < _ramend - DMA_UNCACHED_REGION || |
150 | (reserved_mem_dcache_on && addr >= _ramend && | ||
151 | addr < physical_mem_end)) { | ||
150 | d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; | 152 | d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; |
151 | #ifdef CONFIG_BFIN_WT | 153 | #ifdef CONFIG_BFIN_WT |
152 | d_data |= CPLB_L1_AOW | CPLB_WT; | 154 | d_data |= CPLB_L1_AOW | CPLB_WT; |
153 | #endif | 155 | #endif |
154 | } | 156 | } |
155 | #endif | 157 | #endif |
156 | if (addr >= _ramend) { | 158 | if (addr >= physical_mem_end) { |
157 | if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE | 159 | if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE |
158 | && (status & FAULT_USERSUPV)) { | 160 | && (status & FAULT_USERSUPV)) { |
159 | addr &= ~0x3fffff; | 161 | addr &= ~0x3fffff; |
@@ -161,6 +163,8 @@ static noinline int dcplb_miss(void) | |||
161 | d_data |= PAGE_SIZE_4MB; | 163 | d_data |= PAGE_SIZE_4MB; |
162 | } else | 164 | } else |
163 | return CPLB_PROT_VIOL; | 165 | return CPLB_PROT_VIOL; |
166 | } else if (addr >= _ramend) { | ||
167 | d_data |= CPLB_USER_RD | CPLB_USER_WR; | ||
164 | } else { | 168 | } else { |
165 | mask = current_rwx_mask; | 169 | mask = current_rwx_mask; |
166 | if (mask) { | 170 | if (mask) { |
@@ -198,12 +202,14 @@ static noinline int icplb_miss(void) | |||
198 | unsigned long i_data; | 202 | unsigned long i_data; |
199 | 203 | ||
200 | nr_icplb_miss++; | 204 | nr_icplb_miss++; |
201 | if (status & FAULT_USERSUPV) | ||
202 | nr_icplb_supv_miss++; | ||
203 | 205 | ||
204 | if (addr >= _ramend) | 206 | /* If inside the uncached DMA region, fault. */ |
207 | if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend) | ||
205 | return CPLB_PROT_VIOL; | 208 | return CPLB_PROT_VIOL; |
206 | 209 | ||
210 | if (status & FAULT_USERSUPV) | ||
211 | nr_icplb_supv_miss++; | ||
212 | |||
207 | /* | 213 | /* |
208 | * First, try to find a CPLB that matches this address. If we | 214 | * First, try to find a CPLB that matches this address. If we |
209 | * find one, then the fact that we're in the miss handler means | 215 | * find one, then the fact that we're in the miss handler means |
@@ -220,30 +226,42 @@ static noinline int icplb_miss(void) | |||
220 | } | 226 | } |
221 | 227 | ||
222 | i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB; | 228 | i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB; |
223 | #ifdef CONFIG_BFIN_ICACHE | ||
224 | i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; | ||
225 | #endif | ||
226 | 229 | ||
230 | #ifdef CONFIG_BFIN_ICACHE | ||
227 | /* | 231 | /* |
228 | * Two cases to distinguish - a supervisor access must necessarily | 232 | * Normal RAM, and possibly the reserved memory area, are |
229 | * be for a module page; we grant it unconditionally (could do better | 233 | * cacheable. |
230 | * here in the future). Otherwise, check the x bitmap of the current | ||
231 | * process. | ||
232 | */ | 234 | */ |
233 | if (!(status & FAULT_USERSUPV)) { | 235 | if (addr < _ramend || |
234 | unsigned long *mask = current_rwx_mask; | 236 | (addr < physical_mem_end && reserved_mem_icache_on)) |
235 | 237 | i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; | |
236 | if (mask) { | 238 | #endif |
237 | int page = addr >> PAGE_SHIFT; | ||
238 | int offs = page >> 5; | ||
239 | int bit = 1 << (page & 31); | ||
240 | 239 | ||
241 | mask += 2 * page_mask_nelts; | 240 | if (addr >= physical_mem_end) { |
242 | if (mask[offs] & bit) | 241 | return CPLB_PROT_VIOL; |
243 | i_data |= CPLB_USER_RD; | 242 | } else if (addr >= _ramend) { |
243 | i_data |= CPLB_USER_RD; | ||
244 | } else { | ||
245 | /* | ||
246 | * Two cases to distinguish - a supervisor access must | ||
247 | * necessarily be for a module page; we grant it | ||
248 | * unconditionally (could do better here in the future). | ||
249 | * Otherwise, check the x bitmap of the current process. | ||
250 | */ | ||
251 | if (!(status & FAULT_USERSUPV)) { | ||
252 | unsigned long *mask = current_rwx_mask; | ||
253 | |||
254 | if (mask) { | ||
255 | int page = addr >> PAGE_SHIFT; | ||
256 | int offs = page >> 5; | ||
257 | int bit = 1 << (page & 31); | ||
258 | |||
259 | mask += 2 * page_mask_nelts; | ||
260 | if (mask[offs] & bit) | ||
261 | i_data |= CPLB_USER_RD; | ||
262 | } | ||
244 | } | 263 | } |
245 | } | 264 | } |
246 | |||
247 | idx = evict_one_icplb(); | 265 | idx = evict_one_icplb(); |
248 | addr &= PAGE_MASK; | 266 | addr &= PAGE_MASK; |
249 | icplb_tbl[idx].addr = addr; | 267 | icplb_tbl[idx].addr = addr; |