aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/cplb-mpu
diff options
context:
space:
mode:
authorGraf Yang <graf.yang@analog.com>2008-11-18 04:48:22 -0500
committerBryan Wu <cooloney@kernel.org>2008-11-18 04:48:22 -0500
commitb8a989893cbdeb6c97a7b5af5f38fb0e480235f9 (patch)
tree658cf6df93dac687f0d6b94111d0f53b3dd0177c /arch/blackfin/kernel/cplb-mpu
parent6b3087c64a92a36ae20d33479b4df6d7afc910d4 (diff)
Blackfin arch: SMP supporting patchset: Blackfin CPLB related code
Blackfin dual core BF561 processor can support SMP like features. https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like In this patch, we provide SMP extend to Blackfin CPLB related code Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/kernel/cplb-mpu')
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cacheinit.c4
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbinfo.c43
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbinit.c43
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c102
4 files changed, 104 insertions, 88 deletions
diff --git a/arch/blackfin/kernel/cplb-mpu/cacheinit.c b/arch/blackfin/kernel/cplb-mpu/cacheinit.c
index a8b712a24c59..c6ff947f9d37 100644
--- a/arch/blackfin/kernel/cplb-mpu/cacheinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cacheinit.c
@@ -25,7 +25,7 @@
25#include <asm/cplbinit.h> 25#include <asm/cplbinit.h>
26 26
27#if defined(CONFIG_BFIN_ICACHE) 27#if defined(CONFIG_BFIN_ICACHE)
28void __init bfin_icache_init(void) 28void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
29{ 29{
30 unsigned long ctrl; 30 unsigned long ctrl;
31 int i; 31 int i;
@@ -43,7 +43,7 @@ void __init bfin_icache_init(void)
43#endif 43#endif
44 44
45#if defined(CONFIG_BFIN_DCACHE) 45#if defined(CONFIG_BFIN_DCACHE)
46void __init bfin_dcache_init(void) 46void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
47{ 47{
48 unsigned long ctrl; 48 unsigned long ctrl;
49 int i; 49 int i;
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
index 822beefa3a4b..00cb2cf3a420 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
@@ -66,32 +66,32 @@ static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
66 return buf; 66 return buf;
67} 67}
68 68
69int cplbinfo_proc_output(char *buf) 69int cplbinfo_proc_output(char *buf, void *data)
70{ 70{
71 char *p; 71 char *p;
72 unsigned int cpu = (unsigned int)data;;
72 73
73 p = buf; 74 p = buf;
74 75
75 p += sprintf(p, "------------------ CPLB Information ------------------\n\n"); 76 p += sprintf(p, "------------- CPLB Information on CPU%u --------------\n\n", cpu);
76
77 if (bfin_read_IMEM_CONTROL() & ENICPLB) { 77 if (bfin_read_IMEM_CONTROL() & ENICPLB) {
78 p += sprintf(p, "Instruction CPLB entry:\n"); 78 p += sprintf(p, "Instruction CPLB entry:\n");
79 p = cplb_print_entry(p, icplb_tbl, first_switched_icplb); 79 p = cplb_print_entry(p, icplb_tbl[cpu], first_switched_icplb);
80 } else 80 } else
81 p += sprintf(p, "Instruction CPLB is disabled.\n\n"); 81 p += sprintf(p, "Instruction CPLB is disabled.\n\n");
82 82
83 if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) { 83 if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) {
84 p += sprintf(p, "Data CPLB entry:\n"); 84 p += sprintf(p, "Data CPLB entry:\n");
85 p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb); 85 p = cplb_print_entry(p, dcplb_tbl[cpu], first_switched_dcplb);
86 } else 86 } else
87 p += sprintf(p, "Data CPLB is disabled.\n"); 87 p += sprintf(p, "Data CPLB is disabled.\n");
88 88
89 p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n", 89 p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n",
90 nr_icplb_miss, nr_icplb_supv_miss); 90 nr_icplb_miss[cpu], nr_icplb_supv_miss[cpu]);
91 p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n", 91 p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n",
92 nr_dcplb_miss, nr_dcplb_prot); 92 nr_dcplb_miss[cpu], nr_dcplb_prot[cpu]);
93 p += sprintf(p, "CPLB flushes: %d\n", 93 p += sprintf(p, "CPLB flushes: %d\n",
94 nr_cplb_flush); 94 nr_cplb_flush[cpu]);
95 95
96 return p - buf; 96 return p - buf;
97} 97}
@@ -101,7 +101,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
101{ 101{
102 int len; 102 int len;
103 103
104 len = cplbinfo_proc_output(page); 104 len = cplbinfo_proc_output(page, data);
105 if (len <= off + count) 105 if (len <= off + count)
106 *eof = 1; 106 *eof = 1;
107 *start = page + off; 107 *start = page + off;
@@ -115,20 +115,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
115 115
116static int __init cplbinfo_init(void) 116static int __init cplbinfo_init(void)
117{ 117{
118 struct proc_dir_entry *entry; 118 struct proc_dir_entry *parent, *entry;
119 unsigned int cpu;
120 unsigned char str[10];
121
122 parent = proc_mkdir("cplbinfo", NULL);
119 123
120 entry = create_proc_entry("cplbinfo", 0, NULL); 124 for_each_online_cpu(cpu) {
121 if (!entry) 125 sprintf(str, "cpu%u", cpu);
122 return -ENOMEM; 126 entry = create_proc_entry(str, 0, parent);
127 if (!entry)
128 return -ENOMEM;
123 129
124 entry->read_proc = cplbinfo_read_proc; 130 entry->read_proc = cplbinfo_read_proc;
125 entry->data = NULL; 131 entry->data = (void *)cpu;
132 }
126 133
127 return 0; 134 return 0;
128} 135}
129 136
130static void __exit cplbinfo_exit(void) 137static void __exit cplbinfo_exit(void)
131{ 138{
139 unsigned int cpu;
140 unsigned char str[20];
141 for_each_online_cpu(cpu) {
142 sprintf(str, "cplbinfo/cpu%u", cpu);
143 remove_proc_entry(str, NULL);
144 }
132 remove_proc_entry("cplbinfo", NULL); 145 remove_proc_entry("cplbinfo", NULL);
133} 146}
134 147
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
index 55af729f8495..269d2a3530a6 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
@@ -30,13 +30,13 @@
30# error the MPU will not function safely while Anomaly 05000263 applies 30# error the MPU will not function safely while Anomaly 05000263 applies
31#endif 31#endif
32 32
33struct cplb_entry icplb_tbl[MAX_CPLBS]; 33struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
34struct cplb_entry dcplb_tbl[MAX_CPLBS]; 34struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
35 35
36int first_switched_icplb, first_switched_dcplb; 36int first_switched_icplb, first_switched_dcplb;
37int first_mask_dcplb; 37int first_mask_dcplb;
38 38
39void __init generate_cplb_tables(void) 39void __init generate_cplb_tables_cpu(unsigned int cpu)
40{ 40{
41 int i_d, i_i; 41 int i_d, i_i;
42 unsigned long addr; 42 unsigned long addr;
@@ -55,15 +55,16 @@ void __init generate_cplb_tables(void)
55 d_cache |= CPLB_L1_AOW | CPLB_WT; 55 d_cache |= CPLB_L1_AOW | CPLB_WT;
56#endif 56#endif
57#endif 57#endif
58
58 i_d = i_i = 0; 59 i_d = i_i = 0;
59 60
60 /* Set up the zero page. */ 61 /* Set up the zero page. */
61 dcplb_tbl[i_d].addr = 0; 62 dcplb_tbl[cpu][i_d].addr = 0;
62 dcplb_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; 63 dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
63 64
64#if 0 65#if 0
65 icplb_tbl[i_i].addr = 0; 66 icplb_tbl[cpu][i_i].addr = 0;
66 icplb_tbl[i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB; 67 icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
67#endif 68#endif
68 69
69 /* Cover kernel memory with 4M pages. */ 70 /* Cover kernel memory with 4M pages. */
@@ -72,28 +73,28 @@ void __init generate_cplb_tables(void)
72 i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB; 73 i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB;
73 74
74 for (; addr < memory_start; addr += 4 * 1024 * 1024) { 75 for (; addr < memory_start; addr += 4 * 1024 * 1024) {
75 dcplb_tbl[i_d].addr = addr; 76 dcplb_tbl[cpu][i_d].addr = addr;
76 dcplb_tbl[i_d++].data = d_data; 77 dcplb_tbl[cpu][i_d++].data = d_data;
77 icplb_tbl[i_i].addr = addr; 78 icplb_tbl[cpu][i_i].addr = addr;
78 icplb_tbl[i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0); 79 icplb_tbl[cpu][i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0);
79 } 80 }
80 81
81 /* Cover L1 memory. One 4M area for code and data each is enough. */ 82 /* Cover L1 memory. One 4M area for code and data each is enough. */
82#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0 83#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0
83 dcplb_tbl[i_d].addr = L1_DATA_A_START; 84 dcplb_tbl[cpu][i_d].addr = get_l1_data_a_start_cpu(cpu);
84 dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; 85 dcplb_tbl[cpu][i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
85#endif 86#endif
86#if L1_CODE_LENGTH > 0 87#if L1_CODE_LENGTH > 0
87 icplb_tbl[i_i].addr = L1_CODE_START; 88 icplb_tbl[cpu][i_i].addr = get_l1_code_start_cpu(cpu);
88 icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; 89 icplb_tbl[cpu][i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
89#endif 90#endif
90 91
91 /* Cover L2 memory */ 92 /* Cover L2 memory */
92#if L2_LENGTH > 0 93#if L2_LENGTH > 0
93 dcplb_tbl[i_d].addr = L2_START; 94 dcplb_tbl[cpu][i_d].addr = L2_START;
94 dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB; 95 dcplb_tbl[cpu][i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
95 icplb_tbl[i_i].addr = L2_START; 96 icplb_tbl[cpu][i_i].addr = L2_START;
96 icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB; 97 icplb_tbl[cpu][i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
97#endif 98#endif
98 99
99 first_mask_dcplb = i_d; 100 first_mask_dcplb = i_d;
@@ -101,7 +102,7 @@ void __init generate_cplb_tables(void)
101 first_switched_icplb = i_i; 102 first_switched_icplb = i_i;
102 103
103 while (i_d < MAX_CPLBS) 104 while (i_d < MAX_CPLBS)
104 dcplb_tbl[i_d++].data = 0; 105 dcplb_tbl[cpu][i_d++].data = 0;
105 while (i_i < MAX_CPLBS) 106 while (i_i < MAX_CPLBS)
106 icplb_tbl[i_i++].data = 0; 107 icplb_tbl[cpu][i_i++].data = 0;
107} 108}
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index baa52e261f0d..76bd99177de5 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -30,10 +30,11 @@
30 30
31int page_mask_nelts; 31int page_mask_nelts;
32int page_mask_order; 32int page_mask_order;
33unsigned long *current_rwx_mask; 33unsigned long *current_rwx_mask[NR_CPUS];
34 34
35int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot; 35int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
36int nr_cplb_flush; 36int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
37int nr_cplb_flush[NR_CPUS];
37 38
38static inline void disable_dcplb(void) 39static inline void disable_dcplb(void)
39{ 40{
@@ -98,42 +99,42 @@ static inline int write_permitted(int status, unsigned long data)
98} 99}
99 100
100/* Counters to implement round-robin replacement. */ 101/* Counters to implement round-robin replacement. */
101static int icplb_rr_index, dcplb_rr_index; 102static int icplb_rr_index[NR_CPUS], dcplb_rr_index[NR_CPUS];
102 103
103/* 104/*
104 * Find an ICPLB entry to be evicted and return its index. 105 * Find an ICPLB entry to be evicted and return its index.
105 */ 106 */
106static int evict_one_icplb(void) 107static int evict_one_icplb(unsigned int cpu)
107{ 108{
108 int i; 109 int i;
109 for (i = first_switched_icplb; i < MAX_CPLBS; i++) 110 for (i = first_switched_icplb; i < MAX_CPLBS; i++)
110 if ((icplb_tbl[i].data & CPLB_VALID) == 0) 111 if ((icplb_tbl[cpu][i].data & CPLB_VALID) == 0)
111 return i; 112 return i;
112 i = first_switched_icplb + icplb_rr_index; 113 i = first_switched_icplb + icplb_rr_index[cpu];
113 if (i >= MAX_CPLBS) { 114 if (i >= MAX_CPLBS) {
114 i -= MAX_CPLBS - first_switched_icplb; 115 i -= MAX_CPLBS - first_switched_icplb;
115 icplb_rr_index -= MAX_CPLBS - first_switched_icplb; 116 icplb_rr_index[cpu] -= MAX_CPLBS - first_switched_icplb;
116 } 117 }
117 icplb_rr_index++; 118 icplb_rr_index[cpu]++;
118 return i; 119 return i;
119} 120}
120 121
121static int evict_one_dcplb(void) 122static int evict_one_dcplb(unsigned int cpu)
122{ 123{
123 int i; 124 int i;
124 for (i = first_switched_dcplb; i < MAX_CPLBS; i++) 125 for (i = first_switched_dcplb; i < MAX_CPLBS; i++)
125 if ((dcplb_tbl[i].data & CPLB_VALID) == 0) 126 if ((dcplb_tbl[cpu][i].data & CPLB_VALID) == 0)
126 return i; 127 return i;
127 i = first_switched_dcplb + dcplb_rr_index; 128 i = first_switched_dcplb + dcplb_rr_index[cpu];
128 if (i >= MAX_CPLBS) { 129 if (i >= MAX_CPLBS) {
129 i -= MAX_CPLBS - first_switched_dcplb; 130 i -= MAX_CPLBS - first_switched_dcplb;
130 dcplb_rr_index -= MAX_CPLBS - first_switched_dcplb; 131 dcplb_rr_index[cpu] -= MAX_CPLBS - first_switched_dcplb;
131 } 132 }
132 dcplb_rr_index++; 133 dcplb_rr_index[cpu]++;
133 return i; 134 return i;
134} 135}
135 136
136static noinline int dcplb_miss(void) 137static noinline int dcplb_miss(unsigned int cpu)
137{ 138{
138 unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); 139 unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
139 int status = bfin_read_DCPLB_STATUS(); 140 int status = bfin_read_DCPLB_STATUS();
@@ -141,7 +142,7 @@ static noinline int dcplb_miss(void)
141 int idx; 142 int idx;
142 unsigned long d_data; 143 unsigned long d_data;
143 144
144 nr_dcplb_miss++; 145 nr_dcplb_miss[cpu]++;
145 146
146 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;
147#ifdef CONFIG_BFIN_DCACHE 148#ifdef CONFIG_BFIN_DCACHE
@@ -168,25 +169,25 @@ static noinline int dcplb_miss(void)
168 } else if (addr >= _ramend) { 169 } else if (addr >= _ramend) {
169 d_data |= CPLB_USER_RD | CPLB_USER_WR; 170 d_data |= CPLB_USER_RD | CPLB_USER_WR;
170 } else { 171 } else {
171 mask = current_rwx_mask; 172 mask = current_rwx_mask[cpu];
172 if (mask) { 173 if (mask) {
173 int page = addr >> PAGE_SHIFT; 174 int page = addr >> PAGE_SHIFT;
174 int offs = page >> 5; 175 int idx = page >> 5;
175 int bit = 1 << (page & 31); 176 int bit = 1 << (page & 31);
176 177
177 if (mask[offs] & bit) 178 if (mask[idx] & bit)
178 d_data |= CPLB_USER_RD; 179 d_data |= CPLB_USER_RD;
179 180
180 mask += page_mask_nelts; 181 mask += page_mask_nelts;
181 if (mask[offs] & bit) 182 if (mask[idx] & bit)
182 d_data |= CPLB_USER_WR; 183 d_data |= CPLB_USER_WR;
183 } 184 }
184 } 185 }
185 idx = evict_one_dcplb(); 186 idx = evict_one_dcplb(cpu);
186 187
187 addr &= PAGE_MASK; 188 addr &= PAGE_MASK;
188 dcplb_tbl[idx].addr = addr; 189 dcplb_tbl[cpu][idx].addr = addr;
189 dcplb_tbl[idx].data = d_data; 190 dcplb_tbl[cpu][idx].data = d_data;
190 191
191 disable_dcplb(); 192 disable_dcplb();
192 bfin_write32(DCPLB_DATA0 + idx * 4, d_data); 193 bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
@@ -196,21 +197,21 @@ static noinline int dcplb_miss(void)
196 return 0; 197 return 0;
197} 198}
198 199
199static noinline int icplb_miss(void) 200static noinline int icplb_miss(unsigned int cpu)
200{ 201{
201 unsigned long addr = bfin_read_ICPLB_FAULT_ADDR(); 202 unsigned long addr = bfin_read_ICPLB_FAULT_ADDR();
202 int status = bfin_read_ICPLB_STATUS(); 203 int status = bfin_read_ICPLB_STATUS();
203 int idx; 204 int idx;
204 unsigned long i_data; 205 unsigned long i_data;
205 206
206 nr_icplb_miss++; 207 nr_icplb_miss[cpu]++;
207 208
208 /* If inside the uncached DMA region, fault. */ 209 /* If inside the uncached DMA region, fault. */
209 if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend) 210 if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
210 return CPLB_PROT_VIOL; 211 return CPLB_PROT_VIOL;
211 212
212 if (status & FAULT_USERSUPV) 213 if (status & FAULT_USERSUPV)
213 nr_icplb_supv_miss++; 214 nr_icplb_supv_miss[cpu]++;
214 215
215 /* 216 /*
216 * First, try to find a CPLB that matches this address. If we 217 * First, try to find a CPLB that matches this address. If we
@@ -218,8 +219,8 @@ static noinline int icplb_miss(void)
218 * that the instruction crosses a page boundary. 219 * that the instruction crosses a page boundary.
219 */ 220 */
220 for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) { 221 for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) {
221 if (icplb_tbl[idx].data & CPLB_VALID) { 222 if (icplb_tbl[cpu][idx].data & CPLB_VALID) {
222 unsigned long this_addr = icplb_tbl[idx].addr; 223 unsigned long this_addr = icplb_tbl[cpu][idx].addr;
223 if (this_addr <= addr && this_addr + PAGE_SIZE > addr) { 224 if (this_addr <= addr && this_addr + PAGE_SIZE > addr) {
224 addr += PAGE_SIZE; 225 addr += PAGE_SIZE;
225 break; 226 break;
@@ -257,23 +258,23 @@ static noinline int icplb_miss(void)
257 * Otherwise, check the x bitmap of the current process. 258 * Otherwise, check the x bitmap of the current process.
258 */ 259 */
259 if (!(status & FAULT_USERSUPV)) { 260 if (!(status & FAULT_USERSUPV)) {
260 unsigned long *mask = current_rwx_mask; 261 unsigned long *mask = current_rwx_mask[cpu];
261 262
262 if (mask) { 263 if (mask) {
263 int page = addr >> PAGE_SHIFT; 264 int page = addr >> PAGE_SHIFT;
264 int offs = page >> 5; 265 int idx = page >> 5;
265 int bit = 1 << (page & 31); 266 int bit = 1 << (page & 31);
266 267
267 mask += 2 * page_mask_nelts; 268 mask += 2 * page_mask_nelts;
268 if (mask[offs] & bit) 269 if (mask[idx] & bit)
269 i_data |= CPLB_USER_RD; 270 i_data |= CPLB_USER_RD;
270 } 271 }
271 } 272 }
272 } 273 }
273 idx = evict_one_icplb(); 274 idx = evict_one_icplb(cpu);
274 addr &= PAGE_MASK; 275 addr &= PAGE_MASK;
275 icplb_tbl[idx].addr = addr; 276 icplb_tbl[cpu][idx].addr = addr;
276 icplb_tbl[idx].data = i_data; 277 icplb_tbl[cpu][idx].data = i_data;
277 278
278 disable_icplb(); 279 disable_icplb();
279 bfin_write32(ICPLB_DATA0 + idx * 4, i_data); 280 bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
@@ -283,19 +284,19 @@ static noinline int icplb_miss(void)
283 return 0; 284 return 0;
284} 285}
285 286
286static noinline int dcplb_protection_fault(void) 287static noinline int dcplb_protection_fault(unsigned int cpu)
287{ 288{
288 int status = bfin_read_DCPLB_STATUS(); 289 int status = bfin_read_DCPLB_STATUS();
289 290
290 nr_dcplb_prot++; 291 nr_dcplb_prot[cpu]++;
291 292
292 if (status & FAULT_RW) { 293 if (status & FAULT_RW) {
293 int idx = faulting_cplb_index(status); 294 int idx = faulting_cplb_index(status);
294 unsigned long data = dcplb_tbl[idx].data; 295 unsigned long data = dcplb_tbl[cpu][idx].data;
295 if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) && 296 if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
296 write_permitted(status, data)) { 297 write_permitted(status, data)) {
297 data |= CPLB_DIRTY; 298 data |= CPLB_DIRTY;
298 dcplb_tbl[idx].data = data; 299 dcplb_tbl[cpu][idx].data = data;
299 bfin_write32(DCPLB_DATA0 + idx * 4, data); 300 bfin_write32(DCPLB_DATA0 + idx * 4, data);
300 return 0; 301 return 0;
301 } 302 }
@@ -306,36 +307,37 @@ static noinline int dcplb_protection_fault(void)
306int cplb_hdr(int seqstat, struct pt_regs *regs) 307int cplb_hdr(int seqstat, struct pt_regs *regs)
307{ 308{
308 int cause = seqstat & 0x3f; 309 int cause = seqstat & 0x3f;
310 unsigned int cpu = smp_processor_id();
309 switch (cause) { 311 switch (cause) {
310 case 0x23: 312 case 0x23:
311 return dcplb_protection_fault(); 313 return dcplb_protection_fault(cpu);
312 case 0x2C: 314 case 0x2C:
313 return icplb_miss(); 315 return icplb_miss(cpu);
314 case 0x26: 316 case 0x26:
315 return dcplb_miss(); 317 return dcplb_miss(cpu);
316 default: 318 default:
317 return 1; 319 return 1;
318 } 320 }
319} 321}
320 322
321void flush_switched_cplbs(void) 323void flush_switched_cplbs(unsigned int cpu)
322{ 324{
323 int i; 325 int i;
324 unsigned long flags; 326 unsigned long flags;
325 327
326 nr_cplb_flush++; 328 nr_cplb_flush[cpu]++;
327 329
328 local_irq_save(flags); 330 local_irq_save(flags);
329 disable_icplb(); 331 disable_icplb();
330 for (i = first_switched_icplb; i < MAX_CPLBS; i++) { 332 for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
331 icplb_tbl[i].data = 0; 333 icplb_tbl[cpu][i].data = 0;
332 bfin_write32(ICPLB_DATA0 + i * 4, 0); 334 bfin_write32(ICPLB_DATA0 + i * 4, 0);
333 } 335 }
334 enable_icplb(); 336 enable_icplb();
335 337
336 disable_dcplb(); 338 disable_dcplb();
337 for (i = first_switched_dcplb; i < MAX_CPLBS; i++) { 339 for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
338 dcplb_tbl[i].data = 0; 340 dcplb_tbl[cpu][i].data = 0;
339 bfin_write32(DCPLB_DATA0 + i * 4, 0); 341 bfin_write32(DCPLB_DATA0 + i * 4, 0);
340 } 342 }
341 enable_dcplb(); 343 enable_dcplb();
@@ -343,7 +345,7 @@ void flush_switched_cplbs(void)
343 345
344} 346}
345 347
346void set_mask_dcplbs(unsigned long *masks) 348void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
347{ 349{
348 int i; 350 int i;
349 unsigned long addr = (unsigned long)masks; 351 unsigned long addr = (unsigned long)masks;
@@ -351,12 +353,12 @@ void set_mask_dcplbs(unsigned long *masks)
351 unsigned long flags; 353 unsigned long flags;
352 354
353 if (!masks) { 355 if (!masks) {
354 current_rwx_mask = masks; 356 current_rwx_mask[cpu] = masks;
355 return; 357 return;
356 } 358 }
357 359
358 local_irq_save(flags); 360 local_irq_save(flags);
359 current_rwx_mask = masks; 361 current_rwx_mask[cpu] = masks;
360 362
361 d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; 363 d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
362#ifdef CONFIG_BFIN_DCACHE 364#ifdef CONFIG_BFIN_DCACHE
@@ -368,8 +370,8 @@ void set_mask_dcplbs(unsigned long *masks)
368 370
369 disable_dcplb(); 371 disable_dcplb();
370 for (i = first_mask_dcplb; i < first_switched_dcplb; i++) { 372 for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
371 dcplb_tbl[i].addr = addr; 373 dcplb_tbl[cpu][i].addr = addr;
372 dcplb_tbl[i].data = d_data; 374 dcplb_tbl[cpu][i].data = d_data;
373 bfin_write32(DCPLB_DATA0 + i * 4, d_data); 375 bfin_write32(DCPLB_DATA0 + i * 4, d_data);
374 bfin_write32(DCPLB_ADDR0 + i * 4, addr); 376 bfin_write32(DCPLB_ADDR0 + i * 4, addr);
375 addr += PAGE_SIZE; 377 addr += PAGE_SIZE;