diff options
Diffstat (limited to 'arch/blackfin/kernel/cplb-mpu/cplbmgr.c')
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 930c01c06813..87b25b1b30ed 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c | |||
@@ -31,6 +31,12 @@ int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS]; | |||
31 | int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS]; | 31 | int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS]; |
32 | int nr_cplb_flush[NR_CPUS]; | 32 | int nr_cplb_flush[NR_CPUS]; |
33 | 33 | ||
34 | #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 | ||
35 | #define MGR_ATTR __attribute__((l1_text)) | ||
36 | #else | ||
37 | #define MGR_ATTR | ||
38 | #endif | ||
39 | |||
34 | /* | 40 | /* |
35 | * Given the contents of the status register, return the index of the | 41 | * Given the contents of the status register, return the index of the |
36 | * CPLB that caused the fault. | 42 | * CPLB that caused the fault. |
@@ -59,7 +65,7 @@ static int icplb_rr_index[NR_CPUS], dcplb_rr_index[NR_CPUS]; | |||
59 | /* | 65 | /* |
60 | * Find an ICPLB entry to be evicted and return its index. | 66 | * Find an ICPLB entry to be evicted and return its index. |
61 | */ | 67 | */ |
62 | static int evict_one_icplb(unsigned int cpu) | 68 | MGR_ATTR static int evict_one_icplb(unsigned int cpu) |
63 | { | 69 | { |
64 | int i; | 70 | int i; |
65 | for (i = first_switched_icplb; i < MAX_CPLBS; i++) | 71 | for (i = first_switched_icplb; i < MAX_CPLBS; i++) |
@@ -74,7 +80,7 @@ static int evict_one_icplb(unsigned int cpu) | |||
74 | return i; | 80 | return i; |
75 | } | 81 | } |
76 | 82 | ||
77 | static int evict_one_dcplb(unsigned int cpu) | 83 | MGR_ATTR static int evict_one_dcplb(unsigned int cpu) |
78 | { | 84 | { |
79 | int i; | 85 | int i; |
80 | for (i = first_switched_dcplb; i < MAX_CPLBS; i++) | 86 | for (i = first_switched_dcplb; i < MAX_CPLBS; i++) |
@@ -89,7 +95,7 @@ static int evict_one_dcplb(unsigned int cpu) | |||
89 | return i; | 95 | return i; |
90 | } | 96 | } |
91 | 97 | ||
92 | static noinline int dcplb_miss(unsigned int cpu) | 98 | MGR_ATTR static noinline int dcplb_miss(unsigned int cpu) |
93 | { | 99 | { |
94 | unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); | 100 | unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); |
95 | int status = bfin_read_DCPLB_STATUS(); | 101 | int status = bfin_read_DCPLB_STATUS(); |
@@ -114,10 +120,15 @@ static noinline int dcplb_miss(unsigned int cpu) | |||
114 | d_data = L2_DMEMORY; | 120 | d_data = L2_DMEMORY; |
115 | } else if (addr >= physical_mem_end) { | 121 | } else if (addr >= physical_mem_end) { |
116 | if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { | 122 | if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { |
117 | addr &= ~(4 * 1024 * 1024 - 1); | 123 | mask = current_rwx_mask[cpu]; |
118 | d_data &= ~PAGE_SIZE_4KB; | 124 | if (mask) { |
119 | d_data |= PAGE_SIZE_4MB; | 125 | int page = (addr - (ASYNC_BANK0_BASE - _ramend)) >> PAGE_SHIFT; |
120 | d_data |= CPLB_USER_RD | CPLB_USER_WR; | 126 | int idx = page >> 5; |
127 | int bit = 1 << (page & 31); | ||
128 | |||
129 | if (mask[idx] & bit) | ||
130 | d_data |= CPLB_USER_RD; | ||
131 | } | ||
121 | } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH | 132 | } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH |
122 | && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) { | 133 | && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) { |
123 | addr &= ~(1 * 1024 * 1024 - 1); | 134 | addr &= ~(1 * 1024 * 1024 - 1); |
@@ -126,7 +137,9 @@ static noinline int dcplb_miss(unsigned int cpu) | |||
126 | } else | 137 | } else |
127 | return CPLB_PROT_VIOL; | 138 | return CPLB_PROT_VIOL; |
128 | } else if (addr >= _ramend) { | 139 | } else if (addr >= _ramend) { |
129 | d_data |= CPLB_USER_RD | CPLB_USER_WR; | 140 | d_data |= CPLB_USER_RD | CPLB_USER_WR; |
141 | if (reserved_mem_dcache_on) | ||
142 | d_data |= CPLB_L1_CHBL; | ||
130 | } else { | 143 | } else { |
131 | mask = current_rwx_mask[cpu]; | 144 | mask = current_rwx_mask[cpu]; |
132 | if (mask) { | 145 | if (mask) { |
@@ -156,7 +169,7 @@ static noinline int dcplb_miss(unsigned int cpu) | |||
156 | return 0; | 169 | return 0; |
157 | } | 170 | } |
158 | 171 | ||
159 | static noinline int icplb_miss(unsigned int cpu) | 172 | MGR_ATTR static noinline int icplb_miss(unsigned int cpu) |
160 | { | 173 | { |
161 | unsigned long addr = bfin_read_ICPLB_FAULT_ADDR(); | 174 | unsigned long addr = bfin_read_ICPLB_FAULT_ADDR(); |
162 | int status = bfin_read_ICPLB_STATUS(); | 175 | int status = bfin_read_ICPLB_STATUS(); |
@@ -204,10 +217,19 @@ static noinline int icplb_miss(unsigned int cpu) | |||
204 | i_data = L2_IMEMORY; | 217 | i_data = L2_IMEMORY; |
205 | } else if (addr >= physical_mem_end) { | 218 | } else if (addr >= physical_mem_end) { |
206 | if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { | 219 | if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { |
207 | addr &= ~(4 * 1024 * 1024 - 1); | 220 | if (!(status & FAULT_USERSUPV)) { |
208 | i_data &= ~PAGE_SIZE_4KB; | 221 | unsigned long *mask = current_rwx_mask[cpu]; |
209 | i_data |= PAGE_SIZE_4MB; | 222 | |
210 | i_data |= CPLB_USER_RD; | 223 | if (mask) { |
224 | int page = (addr - (ASYNC_BANK0_BASE - _ramend)) >> PAGE_SHIFT; | ||
225 | int idx = page >> 5; | ||
226 | int bit = 1 << (page & 31); | ||
227 | |||
228 | mask += 2 * page_mask_nelts; | ||
229 | if (mask[idx] & bit) | ||
230 | i_data |= CPLB_USER_RD; | ||
231 | } | ||
232 | } | ||
211 | } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH | 233 | } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH |
212 | && (status & FAULT_USERSUPV)) { | 234 | && (status & FAULT_USERSUPV)) { |
213 | addr &= ~(1 * 1024 * 1024 - 1); | 235 | addr &= ~(1 * 1024 * 1024 - 1); |
@@ -217,6 +239,8 @@ static noinline int icplb_miss(unsigned int cpu) | |||
217 | return CPLB_PROT_VIOL; | 239 | return CPLB_PROT_VIOL; |
218 | } else if (addr >= _ramend) { | 240 | } else if (addr >= _ramend) { |
219 | i_data |= CPLB_USER_RD; | 241 | i_data |= CPLB_USER_RD; |
242 | if (reserved_mem_icache_on) | ||
243 | i_data |= CPLB_L1_CHBL; | ||
220 | } else { | 244 | } else { |
221 | /* | 245 | /* |
222 | * Two cases to distinguish - a supervisor access must | 246 | * Two cases to distinguish - a supervisor access must |
@@ -251,7 +275,7 @@ static noinline int icplb_miss(unsigned int cpu) | |||
251 | return 0; | 275 | return 0; |
252 | } | 276 | } |
253 | 277 | ||
254 | static noinline int dcplb_protection_fault(unsigned int cpu) | 278 | MGR_ATTR static noinline int dcplb_protection_fault(unsigned int cpu) |
255 | { | 279 | { |
256 | int status = bfin_read_DCPLB_STATUS(); | 280 | int status = bfin_read_DCPLB_STATUS(); |
257 | 281 | ||
@@ -271,7 +295,7 @@ static noinline int dcplb_protection_fault(unsigned int cpu) | |||
271 | return CPLB_PROT_VIOL; | 295 | return CPLB_PROT_VIOL; |
272 | } | 296 | } |
273 | 297 | ||
274 | int cplb_hdr(int seqstat, struct pt_regs *regs) | 298 | MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs) |
275 | { | 299 | { |
276 | int cause = seqstat & 0x3f; | 300 | int cause = seqstat & 0x3f; |
277 | unsigned int cpu = raw_smp_processor_id(); | 301 | unsigned int cpu = raw_smp_processor_id(); |