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 930c01c0681..87b25b1b30e 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(); |
