提交 b8a98989 编写于 作者: G Graf Yang 提交者: Bryan Wu

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: NGraf Yang <graf.yang@analog.com>
Signed-off-by: NBryan Wu <cooloney@kernel.org>
上级 6b3087c6
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*/ */
#ifndef __ASM_BFIN_CPLB_MPU_H #ifndef __ASM_BFIN_CPLB_MPU_H
#define __ASM_BFIN_CPLB_MPU_H #define __ASM_BFIN_CPLB_MPU_H
#include <linux/threads.h>
struct cplb_entry { struct cplb_entry {
unsigned long data, addr; unsigned long data, addr;
...@@ -39,22 +40,22 @@ struct mem_region { ...@@ -39,22 +40,22 @@ struct mem_region {
unsigned long icplb_data; unsigned long icplb_data;
}; };
extern struct cplb_entry dcplb_tbl[MAX_CPLBS]; extern struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
extern struct cplb_entry icplb_tbl[MAX_CPLBS]; extern struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
extern int first_switched_icplb; extern int first_switched_icplb;
extern int first_mask_dcplb; extern int first_mask_dcplb;
extern int first_switched_dcplb; extern int first_switched_dcplb;
extern int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot; extern int nr_dcplb_miss[], nr_icplb_miss[], nr_icplb_supv_miss[];
extern int nr_cplb_flush; extern int nr_dcplb_prot[], nr_cplb_flush[];
extern int page_mask_order; extern int page_mask_order;
extern int page_mask_nelts; extern int page_mask_nelts;
extern unsigned long *current_rwx_mask; extern unsigned long *current_rwx_mask[NR_CPUS];
extern void flush_switched_cplbs(void); extern void flush_switched_cplbs(unsigned int);
extern void set_mask_dcplbs(unsigned long *); extern void set_mask_dcplbs(unsigned long *, unsigned int);
extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *); extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#ifndef _CPLB_H #ifndef _CPLB_H
#define _CPLB_H #define _CPLB_H
#include <asm/blackfin.h>
#include <mach/anomaly.h> #include <mach/anomaly.h>
#define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO) #define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
...@@ -55,13 +54,24 @@ ...@@ -55,13 +54,24 @@
#endif #endif
#define L1_DMEMORY (CPLB_LOCK | CPLB_COMMON) #define L1_DMEMORY (CPLB_LOCK | CPLB_COMMON)
#ifdef CONFIG_SMP
#define L2_ATTR (INITIAL_T | I_CPLB | D_CPLB)
#define L2_IMEMORY (CPLB_COMMON | CPLB_LOCK)
#define L2_DMEMORY (CPLB_COMMON | CPLB_LOCK)
#else
#ifdef CONFIG_BFIN_L2_CACHEABLE #ifdef CONFIG_BFIN_L2_CACHEABLE
#define L2_IMEMORY (SDRAM_IGENERIC) #define L2_IMEMORY (SDRAM_IGENERIC)
#define L2_DMEMORY (SDRAM_DGENERIC) #define L2_DMEMORY (SDRAM_DGENERIC)
#else #else
#define L2_IMEMORY (CPLB_COMMON) #define L2_IMEMORY (CPLB_COMMON)
#define L2_DMEMORY (CPLB_COMMON) #define L2_DMEMORY (CPLB_COMMON)
#endif #endif /* CONFIG_BFIN_L2_CACHEABLE */
#define L2_ATTR (INITIAL_T | SWITCH_T | I_CPLB | D_CPLB)
#endif /* CONFIG_SMP */
#define SDRAM_DNON_CHBL (CPLB_COMMON) #define SDRAM_DNON_CHBL (CPLB_COMMON)
#define SDRAM_EBIU (CPLB_COMMON) #define SDRAM_EBIU (CPLB_COMMON)
#define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY) #define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
...@@ -71,14 +81,7 @@ ...@@ -71,14 +81,7 @@
#define SIZE_1M 0x00100000 /* 1M */ #define SIZE_1M 0x00100000 /* 1M */
#define SIZE_4M 0x00400000 /* 4M */ #define SIZE_4M 0x00400000 /* 4M */
#ifdef CONFIG_MPU
#define MAX_CPLBS 16 #define MAX_CPLBS 16
#else
#define MAX_CPLBS (16 * 2)
#endif
#define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
#define CPLB_ENABLE_ICACHE_P 0 #define CPLB_ENABLE_ICACHE_P 0
#define CPLB_ENABLE_DCACHE_P 1 #define CPLB_ENABLE_DCACHE_P 1
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#ifdef CONFIG_MPU #ifdef CONFIG_MPU
#include <asm/cplb-mpu.h> #include <asm/cplb-mpu.h>
extern void bfin_icache_init(struct cplb_entry *icplb_tbl);
extern void bfin_dcache_init(struct cplb_entry *icplb_tbl);
#else #else
...@@ -46,8 +48,40 @@ ...@@ -46,8 +48,40 @@
#define IN_KERNEL 1 #define IN_KERNEL 1
enum #define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
{ZERO_P, L1I_MEM, L1D_MEM, SDRAM_KERN , SDRAM_RAM_MTD, SDRAM_DMAZ, RES_MEM, ASYNC_MEM, L2_MEM}; ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
#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)
/* Number of CPLB table entries, used for cplb-nompu. */
#define CPLB_TBL_ENTRIES (16 * 4)
enum {
ZERO_P, L1I_MEM, L1D_MEM, L2_MEM, SDRAM_KERN, SDRAM_RAM_MTD, SDRAM_DMAZ,
RES_MEM, ASYNC_MEM, OCB_ROM
};
struct cplb_desc { struct cplb_desc {
u32 start; /* start address */ u32 start; /* start address */
...@@ -66,8 +100,8 @@ struct cplb_tab { ...@@ -66,8 +100,8 @@ struct cplb_tab {
u16 size; u16 size;
}; };
extern u_long icplb_table[]; extern u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
extern u_long dcplb_table[]; extern u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
/* Till here we are discussing about the static memory management model. /* Till here we are discussing about the static memory management model.
* However, the operating envoronments commonly define more CPLB * However, the operating envoronments commonly define more CPLB
...@@ -78,15 +112,18 @@ extern u_long dcplb_table[]; ...@@ -78,15 +112,18 @@ extern u_long dcplb_table[];
* This is how Page descriptor Table is implemented in uClinux/Blackfin. * This is how Page descriptor Table is implemented in uClinux/Blackfin.
*/ */
extern u_long ipdt_table[]; extern u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1];
extern u_long dpdt_table[]; extern u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1];
#ifdef CONFIG_CPLB_INFO #ifdef CONFIG_CPLB_INFO
extern u_long ipdt_swapcount_table[]; extern u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS];
extern u_long dpdt_swapcount_table[]; extern u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS];
#endif #endif
extern void bfin_icache_init(u_long icplbs[]);
extern void bfin_dcache_init(u_long dcplbs[]);
#endif /* CONFIG_MPU */ #endif /* CONFIG_MPU */
extern void generate_cplb_tables(void); #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
extern void generate_cplb_tables_cpu(unsigned int cpu);
#endif
#endif #endif
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/cplbinit.h> #include <asm/cplbinit.h>
/* Note: L1 stacks are CPU-private things, so we bluntly disable this
feature in SMP mode, and use the per-CPU scratch SRAM bank only to
store the PDA instead. */
extern void *current_l1_stack_save; extern void *current_l1_stack_save;
extern int nr_l1stack_tasks; extern int nr_l1stack_tasks;
extern void *l1_stack_base; extern void *l1_stack_base;
...@@ -88,12 +92,15 @@ activate_l1stack(struct mm_struct *mm, unsigned long sp_base) ...@@ -88,12 +92,15 @@ activate_l1stack(struct mm_struct *mm, unsigned long sp_base)
static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
struct task_struct *tsk) struct task_struct *tsk)
{ {
#ifdef CONFIG_MPU
unsigned int cpu = smp_processor_id();
#endif
if (prev_mm == next_mm) if (prev_mm == next_mm)
return; return;
#ifdef CONFIG_MPU #ifdef CONFIG_MPU
if (prev_mm->context.page_rwx_mask == current_rwx_mask) { if (prev_mm->context.page_rwx_mask == current_rwx_mask[cpu]) {
flush_switched_cplbs(); flush_switched_cplbs(cpu);
set_mask_dcplbs(next_mm->context.page_rwx_mask); set_mask_dcplbs(next_mm->context.page_rwx_mask, cpu);
} }
#endif #endif
...@@ -138,9 +145,10 @@ static inline void protect_page(struct mm_struct *mm, unsigned long addr, ...@@ -138,9 +145,10 @@ static inline void protect_page(struct mm_struct *mm, unsigned long addr,
static inline void update_protections(struct mm_struct *mm) static inline void update_protections(struct mm_struct *mm)
{ {
if (mm->context.page_rwx_mask == current_rwx_mask) { unsigned int cpu = smp_processor_id();
flush_switched_cplbs(); if (mm->context.page_rwx_mask == current_rwx_mask[cpu]) {
set_mask_dcplbs(mm->context.page_rwx_mask); flush_switched_cplbs(cpu);
set_mask_dcplbs(mm->context.page_rwx_mask, cpu);
} }
} }
#endif #endif
...@@ -165,6 +173,9 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) ...@@ -165,6 +173,9 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
static inline void destroy_context(struct mm_struct *mm) static inline void destroy_context(struct mm_struct *mm)
{ {
struct sram_list_struct *tmp; struct sram_list_struct *tmp;
#ifdef CONFIG_MPU
unsigned int cpu = smp_processor_id();
#endif
#ifdef CONFIG_APP_STACK_L1 #ifdef CONFIG_APP_STACK_L1
if (current_l1_stack_save == mm->context.l1_stack_save) if (current_l1_stack_save == mm->context.l1_stack_save)
...@@ -179,8 +190,8 @@ static inline void destroy_context(struct mm_struct *mm) ...@@ -179,8 +190,8 @@ static inline void destroy_context(struct mm_struct *mm)
kfree(tmp); kfree(tmp);
} }
#ifdef CONFIG_MPU #ifdef CONFIG_MPU
if (current_rwx_mask == mm->context.page_rwx_mask) if (current_rwx_mask[cpu] == mm->context.page_rwx_mask)
current_rwx_mask = NULL; current_rwx_mask[cpu] = NULL;
free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order); free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order);
#endif #endif
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <asm/cplbinit.h> #include <asm/cplbinit.h>
#if defined(CONFIG_BFIN_ICACHE) #if defined(CONFIG_BFIN_ICACHE)
void __init bfin_icache_init(void) void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
{ {
unsigned long ctrl; unsigned long ctrl;
int i; int i;
...@@ -43,7 +43,7 @@ void __init bfin_icache_init(void) ...@@ -43,7 +43,7 @@ void __init bfin_icache_init(void)
#endif #endif
#if defined(CONFIG_BFIN_DCACHE) #if defined(CONFIG_BFIN_DCACHE)
void __init bfin_dcache_init(void) void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
{ {
unsigned long ctrl; unsigned long ctrl;
int i; int i;
......
...@@ -66,32 +66,32 @@ static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched) ...@@ -66,32 +66,32 @@ static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
return buf; return buf;
} }
int cplbinfo_proc_output(char *buf) int cplbinfo_proc_output(char *buf, void *data)
{ {
char *p; char *p;
unsigned int cpu = (unsigned int)data;;
p = buf; 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) { if (bfin_read_IMEM_CONTROL() & ENICPLB) {
p += sprintf(p, "Instruction CPLB entry:\n"); 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 } else
p += sprintf(p, "Instruction CPLB is disabled.\n\n"); p += sprintf(p, "Instruction CPLB is disabled.\n\n");
if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) { if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) {
p += sprintf(p, "Data CPLB entry:\n"); 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 } else
p += sprintf(p, "Data CPLB is disabled.\n"); p += sprintf(p, "Data CPLB is disabled.\n");
p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\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", 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", p += sprintf(p, "CPLB flushes: %d\n",
nr_cplb_flush); nr_cplb_flush[cpu]);
return p - buf; return p - buf;
} }
...@@ -101,7 +101,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off, ...@@ -101,7 +101,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
{ {
int len; int len;
len = cplbinfo_proc_output(page); len = cplbinfo_proc_output(page, data);
if (len <= off + count) if (len <= off + count)
*eof = 1; *eof = 1;
*start = page + off; *start = page + off;
...@@ -115,20 +115,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off, ...@@ -115,20 +115,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
static int __init cplbinfo_init(void) 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); for_each_online_cpu(cpu) {
if (!entry) sprintf(str, "cpu%u", cpu);
return -ENOMEM; entry = create_proc_entry(str, 0, parent);
if (!entry)
return -ENOMEM;
entry->read_proc = cplbinfo_read_proc; entry->read_proc = cplbinfo_read_proc;
entry->data = NULL; entry->data = (void *)cpu;
}
return 0; return 0;
} }
static void __exit cplbinfo_exit(void) 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); remove_proc_entry("cplbinfo", NULL);
} }
......
...@@ -30,13 +30,13 @@ ...@@ -30,13 +30,13 @@
# error the MPU will not function safely while Anomaly 05000263 applies # error the MPU will not function safely while Anomaly 05000263 applies
#endif #endif
struct cplb_entry icplb_tbl[MAX_CPLBS]; struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
struct cplb_entry dcplb_tbl[MAX_CPLBS]; struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
int first_switched_icplb, first_switched_dcplb; int first_switched_icplb, first_switched_dcplb;
int first_mask_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; int i_d, i_i;
unsigned long addr; unsigned long addr;
...@@ -55,15 +55,16 @@ void __init generate_cplb_tables(void) ...@@ -55,15 +55,16 @@ void __init generate_cplb_tables(void)
d_cache |= CPLB_L1_AOW | CPLB_WT; d_cache |= CPLB_L1_AOW | CPLB_WT;
#endif #endif
#endif #endif
i_d = i_i = 0; i_d = i_i = 0;
/* Set up the zero page. */ /* Set up the zero page. */
dcplb_tbl[i_d].addr = 0; dcplb_tbl[cpu][i_d].addr = 0;
dcplb_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
#if 0 #if 0
icplb_tbl[i_i].addr = 0; icplb_tbl[cpu][i_i].addr = 0;
icplb_tbl[i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB; icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
#endif #endif
/* Cover kernel memory with 4M pages. */ /* Cover kernel memory with 4M pages. */
...@@ -72,28 +73,28 @@ void __init generate_cplb_tables(void) ...@@ -72,28 +73,28 @@ void __init generate_cplb_tables(void)
i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB; i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB;
for (; addr < memory_start; addr += 4 * 1024 * 1024) { for (; addr < memory_start; addr += 4 * 1024 * 1024) {
dcplb_tbl[i_d].addr = addr; dcplb_tbl[cpu][i_d].addr = addr;
dcplb_tbl[i_d++].data = d_data; dcplb_tbl[cpu][i_d++].data = d_data;
icplb_tbl[i_i].addr = addr; icplb_tbl[cpu][i_i].addr = addr;
icplb_tbl[i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0); 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. */ /* Cover L1 memory. One 4M area for code and data each is enough. */
#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0 #if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0
dcplb_tbl[i_d].addr = L1_DATA_A_START; dcplb_tbl[cpu][i_d].addr = get_l1_data_a_start_cpu(cpu);
dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; dcplb_tbl[cpu][i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
#endif #endif
#if L1_CODE_LENGTH > 0 #if L1_CODE_LENGTH > 0
icplb_tbl[i_i].addr = L1_CODE_START; icplb_tbl[cpu][i_i].addr = get_l1_code_start_cpu(cpu);
icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; icplb_tbl[cpu][i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
#endif #endif
/* Cover L2 memory */ /* Cover L2 memory */
#if L2_LENGTH > 0 #if L2_LENGTH > 0
dcplb_tbl[i_d].addr = L2_START; dcplb_tbl[cpu][i_d].addr = L2_START;
dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB; dcplb_tbl[cpu][i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
icplb_tbl[i_i].addr = L2_START; icplb_tbl[cpu][i_i].addr = L2_START;
icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB; icplb_tbl[cpu][i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
#endif #endif
first_mask_dcplb = i_d; first_mask_dcplb = i_d;
...@@ -101,7 +102,7 @@ void __init generate_cplb_tables(void) ...@@ -101,7 +102,7 @@ void __init generate_cplb_tables(void)
first_switched_icplb = i_i; first_switched_icplb = i_i;
while (i_d < MAX_CPLBS) while (i_d < MAX_CPLBS)
dcplb_tbl[i_d++].data = 0; dcplb_tbl[cpu][i_d++].data = 0;
while (i_i < MAX_CPLBS) while (i_i < MAX_CPLBS)
icplb_tbl[i_i++].data = 0; icplb_tbl[cpu][i_i++].data = 0;
} }
...@@ -30,10 +30,11 @@ ...@@ -30,10 +30,11 @@
int page_mask_nelts; int page_mask_nelts;
int page_mask_order; 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_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
int nr_cplb_flush; int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
int nr_cplb_flush[NR_CPUS];
static inline void disable_dcplb(void) static inline void disable_dcplb(void)
{ {
...@@ -98,42 +99,42 @@ static inline int write_permitted(int status, unsigned long data) ...@@ -98,42 +99,42 @@ static inline int write_permitted(int status, unsigned long data)
} }
/* Counters to implement round-robin replacement. */ /* 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. * 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; int i;
for (i = first_switched_icplb; i < MAX_CPLBS; 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; return i;
i = first_switched_icplb + icplb_rr_index; i = first_switched_icplb + icplb_rr_index[cpu];
if (i >= MAX_CPLBS) { if (i >= MAX_CPLBS) {
i -= MAX_CPLBS - first_switched_icplb; 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; return i;
} }
static int evict_one_dcplb(void) static int evict_one_dcplb(unsigned int cpu)
{ {
int i; int i;
for (i = first_switched_dcplb; i < MAX_CPLBS; 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; return i;
i = first_switched_dcplb + dcplb_rr_index; i = first_switched_dcplb + dcplb_rr_index[cpu];
if (i >= MAX_CPLBS) { if (i >= MAX_CPLBS) {
i -= MAX_CPLBS - first_switched_dcplb; 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; return i;
} }
static noinline int dcplb_miss(void) static noinline int dcplb_miss(unsigned int cpu)
{ {
unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
int status = bfin_read_DCPLB_STATUS(); int status = bfin_read_DCPLB_STATUS();
...@@ -141,7 +142,7 @@ static noinline int dcplb_miss(void) ...@@ -141,7 +142,7 @@ static noinline int dcplb_miss(void)
int idx; int idx;
unsigned long d_data; unsigned long d_data;
nr_dcplb_miss++; nr_dcplb_miss[cpu]++;
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE #ifdef CONFIG_BFIN_DCACHE
...@@ -168,25 +169,25 @@ static noinline int dcplb_miss(void) ...@@ -168,25 +169,25 @@ static noinline int dcplb_miss(void)
} else if (addr >= _ramend) { } else if (addr >= _ramend) {
d_data |= CPLB_USER_RD | CPLB_USER_WR; d_data |= CPLB_USER_RD | CPLB_USER_WR;
} else { } else {
mask = current_rwx_mask; mask = current_rwx_mask[cpu];
if (mask) { if (mask) {
int page = addr >> PAGE_SHIFT; int page = addr >> PAGE_SHIFT;
int offs = page >> 5; int idx = page >> 5;
int bit = 1 << (page & 31); int bit = 1 << (page & 31);
if (mask[offs] & bit) if (mask[idx] & bit)
d_data |= CPLB_USER_RD; d_data |= CPLB_USER_RD;
mask += page_mask_nelts; mask += page_mask_nelts;
if (mask[offs] & bit) if (mask[idx] & bit)
d_data |= CPLB_USER_WR; d_data |= CPLB_USER_WR;
} }
} }
idx = evict_one_dcplb(); idx = evict_one_dcplb(cpu);
addr &= PAGE_MASK; addr &= PAGE_MASK;
dcplb_tbl[idx].addr = addr; dcplb_tbl[cpu][idx].addr = addr;
dcplb_tbl[idx].data = d_data; dcplb_tbl[cpu][idx].data = d_data;
disable_dcplb(); disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, d_data); bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
...@@ -196,21 +197,21 @@ static noinline int dcplb_miss(void) ...@@ -196,21 +197,21 @@ static noinline int dcplb_miss(void)
return 0; return 0;
} }
static noinline int icplb_miss(void) static noinline int icplb_miss(unsigned int cpu)
{ {
unsigned long addr = bfin_read_ICPLB_FAULT_ADDR(); unsigned long addr = bfin_read_ICPLB_FAULT_ADDR();
int status = bfin_read_ICPLB_STATUS(); int status = bfin_read_ICPLB_STATUS();
int idx; int idx;
unsigned long i_data; unsigned long i_data;
nr_icplb_miss++; nr_icplb_miss[cpu]++;
/* If inside the uncached DMA region, fault. */ /* If inside the uncached DMA region, fault. */
if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend) if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
return CPLB_PROT_VIOL; return CPLB_PROT_VIOL;
if (status & FAULT_USERSUPV) 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 * First, try to find a CPLB that matches this address. If we
...@@ -218,8 +219,8 @@ static noinline int icplb_miss(void) ...@@ -218,8 +219,8 @@ static noinline int icplb_miss(void)
* that the instruction crosses a page boundary. * that the instruction crosses a page boundary.
*/ */
for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) { for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) {
if (icplb_tbl[idx].data & CPLB_VALID) { if (icplb_tbl[cpu][idx].data & CPLB_VALID) {
unsigned long this_addr = icplb_tbl[idx].addr; unsigned long this_addr = icplb_tbl[cpu][idx].addr;
if (this_addr <= addr && this_addr + PAGE_SIZE > addr) { if (this_addr <= addr && this_addr + PAGE_SIZE > addr) {
addr += PAGE_SIZE; addr += PAGE_SIZE;
break; break;
...@@ -257,23 +258,23 @@ static noinline int icplb_miss(void) ...@@ -257,23 +258,23 @@ static noinline int icplb_miss(void)
* Otherwise, check the x bitmap of the current process. * Otherwise, check the x bitmap of the current process.
*/ */
if (!(status & FAULT_USERSUPV)) { if (!(status & FAULT_USERSUPV)) {
unsigned long *mask = current_rwx_mask; unsigned long *mask = current_rwx_mask[cpu];
if (mask) { if (mask) {
int page = addr >> PAGE_SHIFT; int page = addr >> PAGE_SHIFT;
int offs = page >> 5; int idx = page >> 5;
int bit = 1 << (page & 31); int bit = 1 << (page & 31);
mask += 2 * page_mask_nelts; mask += 2 * page_mask_nelts;
if (mask[offs] & bit) if (mask[idx] & bit)
i_data |= CPLB_USER_RD; i_data |= CPLB_USER_RD;
} }
} }
} }
idx = evict_one_icplb(); idx = evict_one_icplb(cpu);
addr &= PAGE_MASK; addr &= PAGE_MASK;
icplb_tbl[idx].addr = addr; icplb_tbl[cpu][idx].addr = addr;
icplb_tbl[idx].data = i_data; icplb_tbl[cpu][idx].data = i_data;
disable_icplb(); disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, i_data); bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
...@@ -283,19 +284,19 @@ static noinline int icplb_miss(void) ...@@ -283,19 +284,19 @@ static noinline int icplb_miss(void)
return 0; return 0;
} }
static noinline int dcplb_protection_fault(void) static noinline int dcplb_protection_fault(unsigned int cpu)
{ {
int status = bfin_read_DCPLB_STATUS(); int status = bfin_read_DCPLB_STATUS();
nr_dcplb_prot++; nr_dcplb_prot[cpu]++;
if (status & FAULT_RW) { if (status & FAULT_RW) {
int idx = faulting_cplb_index(status); 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) && if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
write_permitted(status, data)) { write_permitted(status, data)) {
data |= CPLB_DIRTY; data |= CPLB_DIRTY;
dcplb_tbl[idx].data = data; dcplb_tbl[cpu][idx].data = data;
bfin_write32(DCPLB_DATA0 + idx * 4, data); bfin_write32(DCPLB_DATA0 + idx * 4, data);
return 0; return 0;
} }
...@@ -306,36 +307,37 @@ static noinline int dcplb_protection_fault(void) ...@@ -306,36 +307,37 @@ static noinline int dcplb_protection_fault(void)
int cplb_hdr(int seqstat, struct pt_regs *regs) int cplb_hdr(int seqstat, struct pt_regs *regs)
{ {
int cause = seqstat & 0x3f; int cause = seqstat & 0x3f;
unsigned int cpu = smp_processor_id();
switch (cause) { switch (cause) {
case 0x23: case 0x23:
return dcplb_protection_fault(); return dcplb_protection_fault(cpu);
case 0x2C: case 0x2C:
return icplb_miss(); return icplb_miss(cpu);
case 0x26: case 0x26:
return dcplb_miss(); return dcplb_miss(cpu);
default: default:
return 1; return 1;
} }
} }
void flush_switched_cplbs(void) void flush_switched_cplbs(unsigned int cpu)
{ {
int i; int i;
unsigned long flags; unsigned long flags;
nr_cplb_flush++; nr_cplb_flush[cpu]++;
local_irq_save(flags); local_irq_save(flags);
disable_icplb(); disable_icplb();
for (i = first_switched_icplb; i < MAX_CPLBS; i++) { 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); bfin_write32(ICPLB_DATA0 + i * 4, 0);
} }
enable_icplb(); enable_icplb();
disable_dcplb(); disable_dcplb();
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) { 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); bfin_write32(DCPLB_DATA0 + i * 4, 0);
} }
enable_dcplb(); enable_dcplb();
...@@ -343,7 +345,7 @@ void flush_switched_cplbs(void) ...@@ -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; int i;
unsigned long addr = (unsigned long)masks; unsigned long addr = (unsigned long)masks;
...@@ -351,12 +353,12 @@ void set_mask_dcplbs(unsigned long *masks) ...@@ -351,12 +353,12 @@ void set_mask_dcplbs(unsigned long *masks)
unsigned long flags; unsigned long flags;
if (!masks) { if (!masks) {
current_rwx_mask = masks; current_rwx_mask[cpu] = masks;
return; return;
} }
local_irq_save(flags); 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; d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE #ifdef CONFIG_BFIN_DCACHE
...@@ -368,8 +370,8 @@ void set_mask_dcplbs(unsigned long *masks) ...@@ -368,8 +370,8 @@ void set_mask_dcplbs(unsigned long *masks)
disable_dcplb(); disable_dcplb();
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) { for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
dcplb_tbl[i].addr = addr; dcplb_tbl[cpu][i].addr = addr;
dcplb_tbl[i].data = d_data; dcplb_tbl[cpu][i].data = d_data;
bfin_write32(DCPLB_DATA0 + i * 4, d_data); bfin_write32(DCPLB_DATA0 + i * 4, d_data);
bfin_write32(DCPLB_ADDR0 + i * 4, addr); bfin_write32(DCPLB_ADDR0 + i * 4, addr);
addr += PAGE_SIZE; addr += PAGE_SIZE;
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
#include <asm/cplbinit.h> #include <asm/cplbinit.h>
#if defined(CONFIG_BFIN_ICACHE) #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; unsigned long ctrl;
int i; int i;
...@@ -47,9 +47,9 @@ void __init bfin_icache_init(void) ...@@ -47,9 +47,9 @@ void __init bfin_icache_init(void)
#endif #endif
#if defined(CONFIG_BFIN_DCACHE) #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; unsigned long ctrl;
int i; int i;
...@@ -64,6 +64,7 @@ void __init bfin_dcache_init(void) ...@@ -64,6 +64,7 @@ void __init bfin_dcache_init(void)
ctrl = bfin_read_DMEM_CONTROL(); ctrl = bfin_read_DMEM_CONTROL();
ctrl |= DMEM_CNTR; ctrl |= DMEM_CNTR;
bfin_write_DMEM_CONTROL(ctrl); bfin_write_DMEM_CONTROL(ctrl);
SSYNC(); SSYNC();
} }
#endif #endif
...@@ -68,22 +68,22 @@ static int cplb_find_entry(unsigned long *cplb_addr, ...@@ -68,22 +68,22 @@ static int cplb_find_entry(unsigned long *cplb_addr,
return -1; 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_addr = dpdt_tables[cpu];
unsigned long *p_data = dpdt_table + 1; unsigned long *p_data = dpdt_tables[cpu] + 1;
unsigned long *p_icount = dpdt_swapcount_table; unsigned long *p_icount = dpdt_swapcount_tables[cpu];
unsigned long *p_ocount = dpdt_swapcount_table + 1; unsigned long *p_ocount = dpdt_swapcount_tables[cpu] + 1;
unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0; unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0;
unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0; unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0;
int entry = 0, used_cplb = 0; int entry = 0, used_cplb = 0;
if (type == CPLB_I) { if (type == CPLB_I) {
buf += sprintf(buf, "Instruction CPLB entry:\n"); buf += sprintf(buf, "Instruction CPLB entry:\n");
p_addr = ipdt_table; p_addr = ipdt_tables[cpu];
p_data = ipdt_table + 1; p_data = ipdt_tables[cpu] + 1;
p_icount = ipdt_swapcount_table; p_icount = ipdt_swapcount_tables[cpu];
p_ocount = ipdt_swapcount_table + 1; p_ocount = ipdt_swapcount_tables[cpu] + 1;
cplb_addr = (unsigned long *)ICPLB_ADDR0; cplb_addr = (unsigned long *)ICPLB_ADDR0;
cplb_data = (unsigned long *)ICPLB_DATA0; cplb_data = (unsigned long *)ICPLB_DATA0;
} else } else
...@@ -134,24 +134,24 @@ static char *cplb_print_entry(char *buf, int type) ...@@ -134,24 +134,24 @@ static char *cplb_print_entry(char *buf, int type)
return buf; 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; char *p;
p = buf; 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) if (bfin_read_IMEM_CONTROL() & ENICPLB)
p = cplb_print_entry(p, CPLB_I); p = cplb_print_entry(p, CPLB_I, cpu);
else else
p += sprintf(p, "Instruction CPLB is disabled.\n\n"); p += sprintf(p, "Instruction CPLB is disabled.\n\n");
if (bfin_read_DMEM_CONTROL() & ENDCPLB) if (bfin_read_DMEM_CONTROL() & ENDCPLB)
p = cplb_print_entry(p, CPLB_D); p = cplb_print_entry(p, CPLB_D, cpu);
else else
p += sprintf(p, "Data CPLB is disabled.\n"); p += sprintf(p, "Data CPLB is disabled.\n");
return p - buf; return p - buf;
} }
...@@ -160,7 +160,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off, ...@@ -160,7 +160,7 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
{ {
int len; int len;
len = cplbinfo_proc_output(page); len = cplbinfo_proc_output(page, data);
if (len <= off + count) if (len <= off + count)
*eof = 1; *eof = 1;
*start = page + off; *start = page + off;
...@@ -174,20 +174,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off, ...@@ -174,20 +174,33 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
static int __init cplbinfo_init(void) 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); for_each_online_cpu(cpu) {
if (!entry) sprintf(str, "cpu%u", cpu);
return -ENOMEM; entry = create_proc_entry(str, 0, parent);
if (!entry)
return -ENOMEM;
entry->read_proc = cplbinfo_read_proc; entry->read_proc = cplbinfo_read_proc;
entry->data = NULL; entry->data = (void *)cpu;
}
return 0; return 0;
} }
static void __exit cplbinfo_exit(void) 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); remove_proc_entry("cplbinfo", NULL);
} }
......
...@@ -27,46 +27,20 @@ ...@@ -27,46 +27,20 @@
#include <asm/cplb.h> #include <asm/cplb.h>
#include <asm/cplbinit.h> #include <asm/cplbinit.h>
#define CPLB_MEM CONFIG_MAX_MEM_SIZE u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1];
/*
* 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];
#ifdef CONFIG_CPLB_SWITCH_TAB_L1 #ifdef CONFIG_CPLB_SWITCH_TAB_L1
# define PDT_ATTR __attribute__((l1_data)) #define PDT_ATTR __attribute__((l1_data))
#else #else
# define PDT_ATTR #define PDT_ATTR
#endif #endif
u_long ipdt_table[MAX_SWITCH_I_CPLBS + 1] PDT_ATTR; u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1] PDT_ATTR;
u_long dpdt_table[MAX_SWITCH_D_CPLBS + 1] PDT_ATTR; u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1] PDT_ATTR;
#ifdef CONFIG_CPLB_INFO #ifdef CONFIG_CPLB_INFO
u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS] PDT_ATTR; u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS] PDT_ATTR;
u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS] PDT_ATTR; u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS] PDT_ATTR;
#endif #endif
struct s_cplb { struct s_cplb {
...@@ -93,8 +67,8 @@ static struct cplb_desc cplb_data[] = { ...@@ -93,8 +67,8 @@ static struct cplb_desc cplb_data[] = {
.name = "Zero Pointer Guard Page", .name = "Zero Pointer Guard Page",
}, },
{ {
.start = L1_CODE_START, .start = 0, /* dyanmic */
.end = L1_CODE_START + L1_CODE_LENGTH, .end = 0, /* dynamic */
.psize = SIZE_4M, .psize = SIZE_4M,
.attr = INITIAL_T | SWITCH_T | I_CPLB, .attr = INITIAL_T | SWITCH_T | I_CPLB,
.i_conf = L1_IMEMORY, .i_conf = L1_IMEMORY,
...@@ -103,8 +77,8 @@ static struct cplb_desc cplb_data[] = { ...@@ -103,8 +77,8 @@ static struct cplb_desc cplb_data[] = {
.name = "L1 I-Memory", .name = "L1 I-Memory",
}, },
{ {
.start = L1_DATA_A_START, .start = 0, /* dynamic */
.end = L1_DATA_B_START + L1_DATA_B_LENGTH, .end = 0, /* dynamic */
.psize = SIZE_4M, .psize = SIZE_4M,
.attr = INITIAL_T | SWITCH_T | D_CPLB, .attr = INITIAL_T | SWITCH_T | D_CPLB,
.i_conf = 0, .i_conf = 0,
...@@ -116,6 +90,16 @@ static struct cplb_desc cplb_data[] = { ...@@ -116,6 +90,16 @@ static struct cplb_desc cplb_data[] = {
#endif #endif
.name = "L1 D-Memory", .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, .start = 0,
.end = 0, /* dynamic */ .end = 0, /* dynamic */
...@@ -164,16 +148,6 @@ static struct cplb_desc cplb_data[] = { ...@@ -164,16 +148,6 @@ static struct cplb_desc cplb_data[] = {
.valid = 1, .valid = 1,
.name = "Asynchronous Memory Banks", .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, .start = BOOT_ROM_START,
.end = BOOT_ROM_START + BOOT_ROM_LENGTH, .end = BOOT_ROM_START + BOOT_ROM_LENGTH,
...@@ -310,7 +284,7 @@ __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end) ...@@ -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; u16 i, j, process;
...@@ -322,8 +296,8 @@ void __init generate_cplb_tables(void) ...@@ -322,8 +296,8 @@ void __init generate_cplb_tables(void)
printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n"); printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n");
cplb.init_i.size = MAX_CPLBS; cplb.init_i.size = CPLB_TBL_ENTRIES;
cplb.init_d.size = MAX_CPLBS; cplb.init_d.size = CPLB_TBL_ENTRIES;
cplb.switch_i.size = MAX_SWITCH_I_CPLBS; cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
cplb.switch_d.size = MAX_SWITCH_D_CPLBS; cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
...@@ -332,11 +306,15 @@ void __init generate_cplb_tables(void) ...@@ -332,11 +306,15 @@ void __init generate_cplb_tables(void)
cplb.switch_i.pos = 0; cplb.switch_i.pos = 0;
cplb.switch_d.pos = 0; cplb.switch_d.pos = 0;
cplb.init_i.tab = icplb_table; cplb.init_i.tab = icplb_tables[cpu];
cplb.init_d.tab = dcplb_table; cplb.init_d.tab = dcplb_tables[cpu];
cplb.switch_i.tab = ipdt_table; cplb.switch_i.tab = ipdt_tables[cpu];
cplb.switch_d.tab = dpdt_table; 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; cplb_data[SDRAM_KERN].end = memory_end;
#ifdef CONFIG_MTD_UCLINUX #ifdef CONFIG_MTD_UCLINUX
...@@ -459,6 +437,5 @@ void __init generate_cplb_tables(void) ...@@ -459,6 +437,5 @@ void __init generate_cplb_tables(void)
cplb.switch_d.tab[cplb.switch_d.pos] = -1; cplb.switch_d.tab[cplb.switch_d.pos] = -1;
} }
#endif #endif
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/blackfin.h> #include <asm/blackfin.h>
#include <asm/cplb.h> #include <asm/cplb.h>
#include <asm/asm-offsets.h>
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text .section .l1.text
...@@ -164,10 +165,9 @@ ENTRY(_cplb_mgr) ...@@ -164,10 +165,9 @@ ENTRY(_cplb_mgr)
.Lifound_victim: .Lifound_victim:
#ifdef CONFIG_CPLB_INFO #ifdef CONFIG_CPLB_INFO
R7 = [P0 - 0x104]; R7 = [P0 - 0x104];
P2.L = _ipdt_table; GET_PDA(P2, R2);
P2.H = _ipdt_table; P3 = [P2 + PDA_IPDT_SWAPCOUNT];
P3.L = _ipdt_swapcount_table; P2 = [P2 + PDA_IPDT];
P3.H = _ipdt_swapcount_table;
P3 += -4; P3 += -4;
.Licount: .Licount:
R2 = [P2]; /* address from config table */ R2 = [P2]; /* address from config table */
...@@ -208,11 +208,10 @@ ENTRY(_cplb_mgr) ...@@ -208,11 +208,10 @@ ENTRY(_cplb_mgr)
* range. * range.
*/ */
P2.L = _ipdt_table; GET_PDA(P3, R0);
P2.H = _ipdt_table; P2 = [P3 + PDA_IPDT];
#ifdef CONFIG_CPLB_INFO #ifdef CONFIG_CPLB_INFO
P3.L = _ipdt_swapcount_table; P3 = [P3 + PDA_IPDT_SWAPCOUNT];
P3.H = _ipdt_swapcount_table;
P3 += -8; P3 += -8;
#endif #endif
P0.L = _page_size_table; P0.L = _page_size_table;
...@@ -469,10 +468,9 @@ ENTRY(_cplb_mgr) ...@@ -469,10 +468,9 @@ ENTRY(_cplb_mgr)
#ifdef CONFIG_CPLB_INFO #ifdef CONFIG_CPLB_INFO
R7 = [P0 - 0x104]; R7 = [P0 - 0x104];
P2.L = _dpdt_table; GET_PDA(P2, R2);
P2.H = _dpdt_table; P3 = [P2 + PDA_DPDT_SWAPCOUNT];
P3.L = _dpdt_swapcount_table; P2 = [P2 + PDA_DPDT];
P3.H = _dpdt_swapcount_table;
P3 += -4; P3 += -4;
.Ldicount: .Ldicount:
R2 = [P2]; R2 = [P2];
...@@ -541,11 +539,10 @@ ENTRY(_cplb_mgr) ...@@ -541,11 +539,10 @@ ENTRY(_cplb_mgr)
R0 = I0; /* Our faulting address */ R0 = I0; /* Our faulting address */
P2.L = _dpdt_table; GET_PDA(P3, R1);
P2.H = _dpdt_table; P2 = [P3 + PDA_DPDT];
#ifdef CONFIG_CPLB_INFO #ifdef CONFIG_CPLB_INFO
P3.L = _dpdt_swapcount_table; P3 = [P3 + PDA_DPDT_SWAPCOUNT];
P3.H = _dpdt_swapcount_table;
P3 += -8; P3 += -8;
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册