aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernd Schmidt <bernds_cb1@t-online.de>2008-04-23 14:58:26 -0400
committerBryan Wu <cooloney@kernel.org>2008-04-23 14:58:26 -0400
commit1ebc723cf04b55e7aeeec2e758293575d29a9c2b (patch)
treece070f280b8f3f4c2fbf52c51af3b67c0af99502
parentd56daae9bec92ae4b0c115db787a0fcc4c17b381 (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>
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c64
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;