summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorGraf Yang <graf.yang@analog.com>2008-11-18 17:48:22 +0800
committerBryan Wu <cooloney@kernel.org>2008-11-18 17:48:22 +0800
commitb8a989893cbdeb6c97a7b5af5f38fb0e480235f9 (patch)
tree658cf6df93dac687f0d6b94111d0f53b3dd0177c /arch/blackfin/kernel
parent6b3087c64a92a36ae20d33479b4df6d7afc910d4 (diff)
downloadblackbird-op-linux-b8a989893cbdeb6c97a7b5af5f38fb0e480235f9.tar.gz
blackbird-op-linux-b8a989893cbdeb6c97a7b5af5f38fb0e480235f9.zip
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')
-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
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cacheinit.c9
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinfo.c55
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinit.c89
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbmgr.S29
8 files changed, 189 insertions, 185 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 @@
#include <asm/cplbinit.h>
#if defined(CONFIG_BFIN_ICACHE)
-void __init bfin_icache_init(void)
+void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
{
unsigned long ctrl;
int i;
@@ -43,7 +43,7 @@ void __init bfin_icache_init(void)
#endif
#if defined(CONFIG_BFIN_DCACHE)
-void __init bfin_dcache_init(void)
+void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
{
unsigned long ctrl;
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)
return buf;
}
-int cplbinfo_proc_output(char *buf)
+int cplbinfo_proc_output(char *buf, void *data)
{
char *p;
+ unsigned int cpu = (unsigned int)data;;
p = buf;
- p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
-
+ p += sprintf(p, "------------- CPLB Information on CPU%u --------------\n\n", cpu);
if (bfin_read_IMEM_CONTROL() & ENICPLB) {
p += sprintf(p, "Instruction CPLB entry:\n");
- p = cplb_print_entry(p, icplb_tbl, first_switched_icplb);
+ p = cplb_print_entry(p, icplb_tbl[cpu], first_switched_icplb);
} else
p += sprintf(p, "Instruction CPLB is disabled.\n\n");
if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) {
p += sprintf(p, "Data CPLB entry:\n");
- p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb);
+ p = cplb_print_entry(p, dcplb_tbl[cpu], first_switched_dcplb);
} else
p += sprintf(p, "Data CPLB is disabled.\n");
p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n",
- nr_icplb_miss, nr_icplb_supv_miss);
+ nr_icplb_miss[cpu], nr_icplb_supv_miss[cpu]);
p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n",
- nr_dcplb_miss, nr_dcplb_prot);
+ nr_dcplb_miss[cpu], nr_dcplb_prot[cpu]);
p += sprintf(p, "CPLB flushes: %d\n",
- nr_cplb_flush);
+ nr_cplb_flush[cpu]);
return p - buf;
}
@@ -101,7 +101,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
{
int len;
- len = cplbinfo_proc_output(page);
+ len = cplbinfo_proc_output(page, data);
if (len <= off + count)
*eof = 1;
*start = page + off;
@@ -115,20 +115,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
static int __init cplbinfo_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *parent, *entry;
+ unsigned int cpu;
+ unsigned char str[10];
+
+ parent = proc_mkdir("cplbinfo", NULL);
- entry = create_proc_entry("cplbinfo", 0, NULL);
- if (!entry)
- return -ENOMEM;
+ for_each_online_cpu(cpu) {
+ sprintf(str, "cpu%u", cpu);
+ entry = create_proc_entry(str, 0, parent);
+ if (!entry)
+ return -ENOMEM;
- entry->read_proc = cplbinfo_read_proc;
- entry->data = NULL;
+ entry->read_proc = cplbinfo_read_proc;
+ entry->data = (void *)cpu;
+ }
return 0;
}
static void __exit cplbinfo_exit(void)
{
+ unsigned int cpu;
+ unsigned char str[20];
+ for_each_online_cpu(cpu) {
+ sprintf(str, "cplbinfo/cpu%u", cpu);
+ remove_proc_entry(str, NULL);
+ }
remove_proc_entry("cplbinfo", NULL);
}
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 @@
# error the MPU will not function safely while Anomaly 05000263 applies
#endif
-struct cplb_entry icplb_tbl[MAX_CPLBS];
-struct cplb_entry dcplb_tbl[MAX_CPLBS];
+struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
+struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
int first_switched_icplb, first_switched_dcplb;
int first_mask_dcplb;
-void __init generate_cplb_tables(void)
+void __init generate_cplb_tables_cpu(unsigned int cpu)
{
int i_d, i_i;
unsigned long addr;
@@ -55,15 +55,16 @@ void __init generate_cplb_tables(void)
d_cache |= CPLB_L1_AOW | CPLB_WT;
#endif
#endif
+
i_d = i_i = 0;
/* Set up the zero page. */
- dcplb_tbl[i_d].addr = 0;
- dcplb_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
+ dcplb_tbl[cpu][i_d].addr = 0;
+ dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
#if 0
- icplb_tbl[i_i].addr = 0;
- icplb_tbl[i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
+ icplb_tbl[cpu][i_i].addr = 0;
+ icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
#endif
/* Cover kernel memory with 4M pages. */
@@ -72,28 +73,28 @@ void __init generate_cplb_tables(void)
i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB;
for (; addr < memory_start; addr += 4 * 1024 * 1024) {
- dcplb_tbl[i_d].addr = addr;
- dcplb_tbl[i_d++].data = d_data;
- icplb_tbl[i_i].addr = addr;
- icplb_tbl[i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0);
+ dcplb_tbl[cpu][i_d].addr = addr;
+ dcplb_tbl[cpu][i_d++].data = d_data;
+ icplb_tbl[cpu][i_i].addr = addr;
+ icplb_tbl[cpu][i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0);
}
/* Cover L1 memory. One 4M area for code and data each is enough. */
#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0
- dcplb_tbl[i_d].addr = L1_DATA_A_START;
- dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+ dcplb_tbl[cpu][i_d].addr = get_l1_data_a_start_cpu(cpu);
+ dcplb_tbl[cpu][i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
#endif
#if L1_CODE_LENGTH > 0
- icplb_tbl[i_i].addr = L1_CODE_START;
- icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
+ icplb_tbl[cpu][i_i].addr = get_l1_code_start_cpu(cpu);
+ icplb_tbl[cpu][i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
#endif
/* Cover L2 memory */
#if L2_LENGTH > 0
- dcplb_tbl[i_d].addr = L2_START;
- dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
- icplb_tbl[i_i].addr = L2_START;
- icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
+ dcplb_tbl[cpu][i_d].addr = L2_START;
+ dcplb_tbl[cpu][i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
+ icplb_tbl[cpu][i_i].addr = L2_START;
+ icplb_tbl[cpu][i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
#endif
first_mask_dcplb = i_d;
@@ -101,7 +102,7 @@ void __init generate_cplb_tables(void)
first_switched_icplb = i_i;
while (i_d < MAX_CPLBS)
- dcplb_tbl[i_d++].data = 0;
+ dcplb_tbl[cpu][i_d++].data = 0;
while (i_i < MAX_CPLBS)
- icplb_tbl[i_i++].data = 0;
+ icplb_tbl[cpu][i_i++].data = 0;
}
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 @@
int page_mask_nelts;
int page_mask_order;
-unsigned long *current_rwx_mask;
+unsigned long *current_rwx_mask[NR_CPUS];
-int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot;
-int nr_cplb_flush;
+int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
+int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
+int nr_cplb_flush[NR_CPUS];
static inline void disable_dcplb(void)
{
@@ -98,42 +99,42 @@ static inline int write_permitted(int status, unsigned long data)
}
/* Counters to implement round-robin replacement. */
-static int icplb_rr_index, dcplb_rr_index;
+static int icplb_rr_index[NR_CPUS], dcplb_rr_index[NR_CPUS];
/*
* Find an ICPLB entry to be evicted and return its index.
*/
-static int evict_one_icplb(void)
+static int evict_one_icplb(unsigned int cpu)
{
int i;
for (i = first_switched_icplb; i < MAX_CPLBS; i++)
- if ((icplb_tbl[i].data & CPLB_VALID) == 0)
+ if ((icplb_tbl[cpu][i].data & CPLB_VALID) == 0)
return i;
- i = first_switched_icplb + icplb_rr_index;
+ i = first_switched_icplb + icplb_rr_index[cpu];
if (i >= MAX_CPLBS) {
i -= MAX_CPLBS - first_switched_icplb;
- icplb_rr_index -= MAX_CPLBS - first_switched_icplb;
+ icplb_rr_index[cpu] -= MAX_CPLBS - first_switched_icplb;
}
- icplb_rr_index++;
+ icplb_rr_index[cpu]++;
return i;
}
-static int evict_one_dcplb(void)
+static int evict_one_dcplb(unsigned int cpu)
{
int i;
for (i = first_switched_dcplb; i < MAX_CPLBS; i++)
- if ((dcplb_tbl[i].data & CPLB_VALID) == 0)
+ if ((dcplb_tbl[cpu][i].data & CPLB_VALID) == 0)
return i;
- i = first_switched_dcplb + dcplb_rr_index;
+ i = first_switched_dcplb + dcplb_rr_index[cpu];
if (i >= MAX_CPLBS) {
i -= MAX_CPLBS - first_switched_dcplb;
- dcplb_rr_index -= MAX_CPLBS - first_switched_dcplb;
+ dcplb_rr_index[cpu] -= MAX_CPLBS - first_switched_dcplb;
}
- dcplb_rr_index++;
+ dcplb_rr_index[cpu]++;
return i;
}
-static noinline int dcplb_miss(void)
+static noinline int dcplb_miss(unsigned int cpu)
{
unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
int status = bfin_read_DCPLB_STATUS();
@@ -141,7 +142,7 @@ static noinline int dcplb_miss(void)
int idx;
unsigned long d_data;
- nr_dcplb_miss++;
+ nr_dcplb_miss[cpu]++;
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE
@@ -168,25 +169,25 @@ static noinline int dcplb_miss(void)
} else if (addr >= _ramend) {
d_data |= CPLB_USER_RD | CPLB_USER_WR;
} else {
- mask = current_rwx_mask;
+ mask = current_rwx_mask[cpu];
if (mask) {
int page = addr >> PAGE_SHIFT;
- int offs = page >> 5;
+ int idx = page >> 5;
int bit = 1 << (page & 31);
- if (mask[offs] & bit)
+ if (mask[idx] & bit)
d_data |= CPLB_USER_RD;
mask += page_mask_nelts;
- if (mask[offs] & bit)
+ if (mask[idx] & bit)
d_data |= CPLB_USER_WR;
}
}
- idx = evict_one_dcplb();
+ idx = evict_one_dcplb(cpu);
addr &= PAGE_MASK;
- dcplb_tbl[idx].addr = addr;
- dcplb_tbl[idx].data = d_data;
+ dcplb_tbl[cpu][idx].addr = addr;
+ dcplb_tbl[cpu][idx].data = d_data;
disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
@@ -196,21 +197,21 @@ static noinline int dcplb_miss(void)
return 0;
}
-static noinline int icplb_miss(void)
+static noinline int icplb_miss(unsigned int cpu)
{
unsigned long addr = bfin_read_ICPLB_FAULT_ADDR();
int status = bfin_read_ICPLB_STATUS();
int idx;
unsigned long i_data;
- nr_icplb_miss++;
+ nr_icplb_miss[cpu]++;
/* If inside the uncached DMA region, fault. */
if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
return CPLB_PROT_VIOL;
if (status & FAULT_USERSUPV)
- nr_icplb_supv_miss++;
+ nr_icplb_supv_miss[cpu]++;
/*
* First, try to find a CPLB that matches this address. If we
@@ -218,8 +219,8 @@ static noinline int icplb_miss(void)
* that the instruction crosses a page boundary.
*/
for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) {
- if (icplb_tbl[idx].data & CPLB_VALID) {
- unsigned long this_addr = icplb_tbl[idx].addr;
+ if (icplb_tbl[cpu][idx].data & CPLB_VALID) {
+ unsigned long this_addr = icplb_tbl[cpu][idx].addr;
if (this_addr <= addr && this_addr + PAGE_SIZE > addr) {
addr += PAGE_SIZE;
break;
@@ -257,23 +258,23 @@ static noinline int icplb_miss(void)
* Otherwise, check the x bitmap of the current process.
*/
if (!(status & FAULT_USERSUPV)) {
- unsigned long *mask = current_rwx_mask;
+ unsigned long *mask = current_rwx_mask[cpu];
if (mask) {
int page = addr >> PAGE_SHIFT;
- int offs = page >> 5;
+ int idx = page >> 5;
int bit = 1 << (page & 31);
mask += 2 * page_mask_nelts;
- if (mask[offs] & bit)
+ if (mask[idx] & bit)
i_data |= CPLB_USER_RD;
}
}
}
- idx = evict_one_icplb();
+ idx = evict_one_icplb(cpu);
addr &= PAGE_MASK;
- icplb_tbl[idx].addr = addr;
- icplb_tbl[idx].data = i_data;
+ icplb_tbl[cpu][idx].addr = addr;
+ icplb_tbl[cpu][idx].data = i_data;
disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
@@ -283,19 +284,19 @@ static noinline int icplb_miss(void)
return 0;
}
-static noinline int dcplb_protection_fault(void)
+static noinline int dcplb_protection_fault(unsigned int cpu)
{
int status = bfin_read_DCPLB_STATUS();
- nr_dcplb_prot++;
+ nr_dcplb_prot[cpu]++;
if (status & FAULT_RW) {
int idx = faulting_cplb_index(status);
- unsigned long data = dcplb_tbl[idx].data;
+ unsigned long data = dcplb_tbl[cpu][idx].data;
if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
write_permitted(status, data)) {
data |= CPLB_DIRTY;
- dcplb_tbl[idx].data = data;
+ dcplb_tbl[cpu][idx].data = data;
bfin_write32(DCPLB_DATA0 + idx * 4, data);
return 0;
}
@@ -306,36 +307,37 @@ static noinline int dcplb_protection_fault(void)
int cplb_hdr(int seqstat, struct pt_regs *regs)
{
int cause = seqstat & 0x3f;
+ unsigned int cpu = smp_processor_id();
switch (cause) {
case 0x23:
- return dcplb_protection_fault();
+ return dcplb_protection_fault(cpu);
case 0x2C:
- return icplb_miss();
+ return icplb_miss(cpu);
case 0x26:
- return dcplb_miss();
+ return dcplb_miss(cpu);
default:
return 1;
}
}
-void flush_switched_cplbs(void)
+void flush_switched_cplbs(unsigned int cpu)
{
int i;
unsigned long flags;
- nr_cplb_flush++;
+ nr_cplb_flush[cpu]++;
local_irq_save(flags);
disable_icplb();
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
- icplb_tbl[i].data = 0;
+ icplb_tbl[cpu][i].data = 0;
bfin_write32(ICPLB_DATA0 + i * 4, 0);
}
enable_icplb();
disable_dcplb();
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
- dcplb_tbl[i].data = 0;
+ dcplb_tbl[cpu][i].data = 0;
bfin_write32(DCPLB_DATA0 + i * 4, 0);
}
enable_dcplb();
@@ -343,7 +345,7 @@ void flush_switched_cplbs(void)
}
-void set_mask_dcplbs(unsigned long *masks)
+void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
{
int i;
unsigned long addr = (unsigned long)masks;
@@ -351,12 +353,12 @@ void set_mask_dcplbs(unsigned long *masks)
unsigned long flags;
if (!masks) {
- current_rwx_mask = masks;
+ current_rwx_mask[cpu] = masks;
return;
}
local_irq_save(flags);
- current_rwx_mask = masks;
+ current_rwx_mask[cpu] = masks;
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE
@@ -368,8 +370,8 @@ void set_mask_dcplbs(unsigned long *masks)
disable_dcplb();
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
- dcplb_tbl[i].addr = addr;
- dcplb_tbl[i].data = d_data;
+ dcplb_tbl[cpu][i].addr = addr;
+ dcplb_tbl[cpu][i].data = d_data;
bfin_write32(DCPLB_DATA0 + i * 4, d_data);
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
addr += PAGE_SIZE;
diff --git a/arch/blackfin/kernel/cplb-nompu/cacheinit.c b/arch/blackfin/kernel/cplb-nompu/cacheinit.c
index bd0831592c2c..3a385aec67d5 100644
--- a/arch/blackfin/kernel/cplb-nompu/cacheinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cacheinit.c
@@ -25,9 +25,9 @@
#include <asm/cplbinit.h>
#if defined(CONFIG_BFIN_ICACHE)
-void __init bfin_icache_init(void)
+void __cpuinit bfin_icache_init(u_long icplb[])
{
- unsigned long *table = icplb_table;
+ unsigned long *table = icplb;
unsigned long ctrl;
int i;
@@ -47,9 +47,9 @@ void __init bfin_icache_init(void)
#endif
#if defined(CONFIG_BFIN_DCACHE)
-void __init bfin_dcache_init(void)
+void __cpuinit bfin_dcache_init(u_long dcplb[])
{
- unsigned long *table = dcplb_table;
+ unsigned long *table = dcplb;
unsigned long ctrl;
int i;
@@ -64,6 +64,7 @@ void __init bfin_dcache_init(void)
ctrl = bfin_read_DMEM_CONTROL();
ctrl |= DMEM_CNTR;
bfin_write_DMEM_CONTROL(ctrl);
+
SSYNC();
}
#endif
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
index 1e74f0b97996..3f0080954e6f 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
@@ -68,22 +68,22 @@ static int cplb_find_entry(unsigned long *cplb_addr,
return -1;
}
-static char *cplb_print_entry(char *buf, int type)
+static char *cplb_print_entry(char *buf, int type, unsigned int cpu)
{
- unsigned long *p_addr = dpdt_table;
- unsigned long *p_data = dpdt_table + 1;
- unsigned long *p_icount = dpdt_swapcount_table;
- unsigned long *p_ocount = dpdt_swapcount_table + 1;
+ unsigned long *p_addr = dpdt_tables[cpu];
+ unsigned long *p_data = dpdt_tables[cpu] + 1;
+ unsigned long *p_icount = dpdt_swapcount_tables[cpu];
+ unsigned long *p_ocount = dpdt_swapcount_tables[cpu] + 1;
unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0;
unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0;
int entry = 0, used_cplb = 0;
if (type == CPLB_I) {
buf += sprintf(buf, "Instruction CPLB entry:\n");
- p_addr = ipdt_table;
- p_data = ipdt_table + 1;
- p_icount = ipdt_swapcount_table;
- p_ocount = ipdt_swapcount_table + 1;
+ p_addr = ipdt_tables[cpu];
+ p_data = ipdt_tables[cpu] + 1;
+ p_icount = ipdt_swapcount_tables[cpu];
+ p_ocount = ipdt_swapcount_tables[cpu] + 1;
cplb_addr = (unsigned long *)ICPLB_ADDR0;
cplb_data = (unsigned long *)ICPLB_DATA0;
} else
@@ -134,24 +134,24 @@ static char *cplb_print_entry(char *buf, int type)
return buf;
}
-static int cplbinfo_proc_output(char *buf)
+static int cplbinfo_proc_output(char *buf, void *data)
{
+ unsigned int cpu = (unsigned int)data;
char *p;
p = buf;
- p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
+ p += sprintf(p, "------------- CPLB Information on CPU%u--------------\n\n", cpu);
if (bfin_read_IMEM_CONTROL() & ENICPLB)
- p = cplb_print_entry(p, CPLB_I);
+ p = cplb_print_entry(p, CPLB_I, cpu);
else
p += sprintf(p, "Instruction CPLB is disabled.\n\n");
if (bfin_read_DMEM_CONTROL() & ENDCPLB)
- p = cplb_print_entry(p, CPLB_D);
+ p = cplb_print_entry(p, CPLB_D, cpu);
else
p += sprintf(p, "Data CPLB is disabled.\n");
-
return p - buf;
}
@@ -160,7 +160,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
{
int len;
- len = cplbinfo_proc_output(page);
+ len = cplbinfo_proc_output(page, data);
if (len <= off + count)
*eof = 1;
*start = page + off;
@@ -174,20 +174,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
static int __init cplbinfo_init(void)
{
- struct proc_dir_entry *entry;
+ struct proc_dir_entry *parent, *entry;
+ unsigned int cpu;
+ unsigned char str[10];
+
+ parent = proc_mkdir("cplbinfo", NULL);
- entry = create_proc_entry("cplbinfo", 0, NULL);
- if (!entry)
- return -ENOMEM;
+ for_each_online_cpu(cpu) {
+ sprintf(str, "cpu%u", cpu);
+ entry = create_proc_entry(str, 0, parent);
+ if (!entry)
+ return -ENOMEM;
- entry->read_proc = cplbinfo_read_proc;
- entry->data = NULL;
+ entry->read_proc = cplbinfo_read_proc;
+ entry->data = (void *)cpu;
+ }
return 0;
}
static void __exit cplbinfo_exit(void)
{
+ unsigned int cpu;
+ unsigned char str[20];
+ for_each_online_cpu(cpu) {
+ sprintf(str, "cplbinfo/cpu%u", cpu);
+ remove_proc_entry(str, NULL);
+ }
remove_proc_entry("cplbinfo", NULL);
}
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index 2debc900e246..8966c706b71a 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -27,46 +27,20 @@
#include <asm/cplb.h>
#include <asm/cplbinit.h>
-#define CPLB_MEM CONFIG_MAX_MEM_SIZE
-
-/*
-* Number of required data CPLB switchtable entries
-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
-* approx 16 for smaller 1MB page size CPLBs for allignment purposes
-* 1 for L1 Data Memory
-* possibly 1 for L2 Data Memory
-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
-* 1 for ASYNC Memory
-*/
-#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \
- + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
-
-/*
-* Number of required instruction CPLB switchtable entries
-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
-* approx 12 for smaller 1MB page size CPLBs for allignment purposes
-* 1 for L1 Instruction Memory
-* possibly 1 for L2 Instruction Memory
-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
-*/
-#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2)
-
-
-u_long icplb_table[MAX_CPLBS + 1];
-u_long dcplb_table[MAX_CPLBS + 1];
+u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
+u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
#ifdef CONFIG_CPLB_SWITCH_TAB_L1
-# define PDT_ATTR __attribute__((l1_data))
+#define PDT_ATTR __attribute__((l1_data))
#else
-# define PDT_ATTR
+#define PDT_ATTR
#endif
-u_long ipdt_table[MAX_SWITCH_I_CPLBS + 1] PDT_ATTR;
-u_long dpdt_table[MAX_SWITCH_D_CPLBS + 1] PDT_ATTR;
-
+u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1] PDT_ATTR;
+u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1] PDT_ATTR;
#ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS] PDT_ATTR;
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS] PDT_ATTR;
+u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS] PDT_ATTR;
+u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS] PDT_ATTR;
#endif
struct s_cplb {
@@ -93,8 +67,8 @@ static struct cplb_desc cplb_data[] = {
.name = "Zero Pointer Guard Page",
},
{
- .start = L1_CODE_START,
- .end = L1_CODE_START + L1_CODE_LENGTH,
+ .start = 0, /* dyanmic */
+ .end = 0, /* dynamic */
.psize = SIZE_4M,
.attr = INITIAL_T | SWITCH_T | I_CPLB,
.i_conf = L1_IMEMORY,
@@ -103,8 +77,8 @@ static struct cplb_desc cplb_data[] = {
.name = "L1 I-Memory",
},
{
- .start = L1_DATA_A_START,
- .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
+ .start = 0, /* dynamic */
+ .end = 0, /* dynamic */
.psize = SIZE_4M,
.attr = INITIAL_T | SWITCH_T | D_CPLB,
.i_conf = 0,
@@ -117,6 +91,16 @@ static struct cplb_desc cplb_data[] = {
.name = "L1 D-Memory",
},
{
+ .start = L2_START,
+ .end = L2_START + L2_LENGTH,
+ .psize = SIZE_1M,
+ .attr = L2_ATTR,
+ .i_conf = L2_IMEMORY,
+ .d_conf = L2_DMEMORY,
+ .valid = (L2_LENGTH > 0),
+ .name = "L2 Memory",
+ },
+ {
.start = 0,
.end = 0, /* dynamic */
.psize = 0,
@@ -165,16 +149,6 @@ static struct cplb_desc cplb_data[] = {
.name = "Asynchronous Memory Banks",
},
{
- .start = L2_START,
- .end = L2_START + L2_LENGTH,
- .psize = SIZE_1M,
- .attr = SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = L2_IMEMORY,
- .d_conf = L2_DMEMORY,
- .valid = (L2_LENGTH > 0),
- .name = "L2 Memory",
- },
- {
.start = BOOT_ROM_START,
.end = BOOT_ROM_START + BOOT_ROM_LENGTH,
.psize = SIZE_1M,
@@ -310,7 +284,7 @@ __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
}
}
-void __init generate_cplb_tables(void)
+void __init generate_cplb_tables_cpu(unsigned int cpu)
{
u16 i, j, process;
@@ -322,8 +296,8 @@ void __init generate_cplb_tables(void)
printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n");
- cplb.init_i.size = MAX_CPLBS;
- cplb.init_d.size = MAX_CPLBS;
+ cplb.init_i.size = CPLB_TBL_ENTRIES;
+ cplb.init_d.size = CPLB_TBL_ENTRIES;
cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
@@ -332,11 +306,15 @@ void __init generate_cplb_tables(void)
cplb.switch_i.pos = 0;
cplb.switch_d.pos = 0;
- cplb.init_i.tab = icplb_table;
- cplb.init_d.tab = dcplb_table;
- cplb.switch_i.tab = ipdt_table;
- cplb.switch_d.tab = dpdt_table;
+ cplb.init_i.tab = icplb_tables[cpu];
+ cplb.init_d.tab = dcplb_tables[cpu];
+ cplb.switch_i.tab = ipdt_tables[cpu];
+ cplb.switch_d.tab = dpdt_tables[cpu];
+ cplb_data[L1I_MEM].start = get_l1_code_start_cpu(cpu);
+ cplb_data[L1I_MEM].end = cplb_data[L1I_MEM].start + L1_CODE_LENGTH;
+ cplb_data[L1D_MEM].start = get_l1_data_a_start_cpu(cpu);
+ cplb_data[L1D_MEM].end = get_l1_data_b_start_cpu(cpu) + L1_DATA_B_LENGTH;
cplb_data[SDRAM_KERN].end = memory_end;
#ifdef CONFIG_MTD_UCLINUX
@@ -459,6 +437,5 @@ void __init generate_cplb_tables(void)
cplb.switch_d.tab[cplb.switch_d.pos] = -1;
}
-
#endif
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.S b/arch/blackfin/kernel/cplb-nompu/cplbmgr.S
index f5cf3accef37..985f3fc793f6 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.S
+++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.S
@@ -52,6 +52,7 @@
#include <linux/linkage.h>
#include <asm/blackfin.h>
#include <asm/cplb.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text
@@ -164,10 +165,9 @@ ENTRY(_cplb_mgr)
.Lifound_victim:
#ifdef CONFIG_CPLB_INFO
R7 = [P0 - 0x104];
- P2.L = _ipdt_table;
- P2.H = _ipdt_table;
- P3.L = _ipdt_swapcount_table;
- P3.H = _ipdt_swapcount_table;
+ GET_PDA(P2, R2);
+ P3 = [P2 + PDA_IPDT_SWAPCOUNT];
+ P2 = [P2 + PDA_IPDT];
P3 += -4;
.Licount:
R2 = [P2]; /* address from config table */
@@ -208,11 +208,10 @@ ENTRY(_cplb_mgr)
* range.
*/
- P2.L = _ipdt_table;
- P2.H = _ipdt_table;
+ GET_PDA(P3, R0);
+ P2 = [P3 + PDA_IPDT];
#ifdef CONFIG_CPLB_INFO
- P3.L = _ipdt_swapcount_table;
- P3.H = _ipdt_swapcount_table;
+ P3 = [P3 + PDA_IPDT_SWAPCOUNT];
P3 += -8;
#endif
P0.L = _page_size_table;
@@ -469,10 +468,9 @@ ENTRY(_cplb_mgr)
#ifdef CONFIG_CPLB_INFO
R7 = [P0 - 0x104];
- P2.L = _dpdt_table;
- P2.H = _dpdt_table;
- P3.L = _dpdt_swapcount_table;
- P3.H = _dpdt_swapcount_table;
+ GET_PDA(P2, R2);
+ P3 = [P2 + PDA_DPDT_SWAPCOUNT];
+ P2 = [P2 + PDA_DPDT];
P3 += -4;
.Ldicount:
R2 = [P2];
@@ -541,11 +539,10 @@ ENTRY(_cplb_mgr)
R0 = I0; /* Our faulting address */
- P2.L = _dpdt_table;
- P2.H = _dpdt_table;
+ GET_PDA(P3, R1);
+ P2 = [P3 + PDA_DPDT];
#ifdef CONFIG_CPLB_INFO
- P3.L = _dpdt_swapcount_table;
- P3.H = _dpdt_swapcount_table;
+ P3 = [P3 + PDA_DPDT_SWAPCOUNT];
P3 += -8;
#endif
OpenPOWER on IntegriCloud