diff options
author | Graf Yang <graf.yang@analog.com> | 2008-11-18 04:48:22 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-11-18 04:48:22 -0500 |
commit | b8a989893cbdeb6c97a7b5af5f38fb0e480235f9 (patch) | |
tree | 658cf6df93dac687f0d6b94111d0f53b3dd0177c /arch/blackfin/include | |
parent | 6b3087c64a92a36ae20d33479b4df6d7afc910d4 (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/include')
-rw-r--r-- | arch/blackfin/include/asm/cplb-mpu.h | 15 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cplb.h | 21 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cplbinit.h | 57 | ||||
-rw-r--r-- | arch/blackfin/include/asm/mmu_context.h | 27 |
4 files changed, 86 insertions, 34 deletions
diff --git a/arch/blackfin/include/asm/cplb-mpu.h b/arch/blackfin/include/asm/cplb-mpu.h index 75c67b99d607..80680ad7a378 100644 --- a/arch/blackfin/include/asm/cplb-mpu.h +++ b/arch/blackfin/include/asm/cplb-mpu.h | |||
@@ -28,6 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | #ifndef __ASM_BFIN_CPLB_MPU_H | 29 | #ifndef __ASM_BFIN_CPLB_MPU_H |
30 | #define __ASM_BFIN_CPLB_MPU_H | 30 | #define __ASM_BFIN_CPLB_MPU_H |
31 | #include <linux/threads.h> | ||
31 | 32 | ||
32 | struct cplb_entry { | 33 | struct cplb_entry { |
33 | unsigned long data, addr; | 34 | unsigned long data, addr; |
@@ -39,22 +40,22 @@ struct mem_region { | |||
39 | unsigned long icplb_data; | 40 | unsigned long icplb_data; |
40 | }; | 41 | }; |
41 | 42 | ||
42 | extern struct cplb_entry dcplb_tbl[MAX_CPLBS]; | 43 | extern struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS]; |
43 | extern struct cplb_entry icplb_tbl[MAX_CPLBS]; | 44 | extern struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS]; |
44 | extern int first_switched_icplb; | 45 | extern int first_switched_icplb; |
45 | extern int first_mask_dcplb; | 46 | extern int first_mask_dcplb; |
46 | extern int first_switched_dcplb; | 47 | extern int first_switched_dcplb; |
47 | 48 | ||
48 | extern int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot; | 49 | extern int nr_dcplb_miss[], nr_icplb_miss[], nr_icplb_supv_miss[]; |
49 | extern int nr_cplb_flush; | 50 | extern int nr_dcplb_prot[], nr_cplb_flush[]; |
50 | 51 | ||
51 | extern int page_mask_order; | 52 | extern int page_mask_order; |
52 | extern int page_mask_nelts; | 53 | extern int page_mask_nelts; |
53 | 54 | ||
54 | extern unsigned long *current_rwx_mask; | 55 | extern unsigned long *current_rwx_mask[NR_CPUS]; |
55 | 56 | ||
56 | extern void flush_switched_cplbs(void); | 57 | extern void flush_switched_cplbs(unsigned int); |
57 | extern void set_mask_dcplbs(unsigned long *); | 58 | extern void set_mask_dcplbs(unsigned long *, unsigned int); |
58 | 59 | ||
59 | extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *); | 60 | extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *); |
60 | 61 | ||
diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h index 9e8b4035fcec..5f7545d06200 100644 --- a/arch/blackfin/include/asm/cplb.h +++ b/arch/blackfin/include/asm/cplb.h | |||
@@ -30,7 +30,6 @@ | |||
30 | #ifndef _CPLB_H | 30 | #ifndef _CPLB_H |
31 | #define _CPLB_H | 31 | #define _CPLB_H |
32 | 32 | ||
33 | #include <asm/blackfin.h> | ||
34 | #include <mach/anomaly.h> | 33 | #include <mach/anomaly.h> |
35 | 34 | ||
36 | #define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO) | 35 | #define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO) |
@@ -55,13 +54,24 @@ | |||
55 | #endif | 54 | #endif |
56 | 55 | ||
57 | #define L1_DMEMORY (CPLB_LOCK | CPLB_COMMON) | 56 | #define L1_DMEMORY (CPLB_LOCK | CPLB_COMMON) |
57 | |||
58 | #ifdef CONFIG_SMP | ||
59 | #define L2_ATTR (INITIAL_T | I_CPLB | D_CPLB) | ||
60 | #define L2_IMEMORY (CPLB_COMMON | CPLB_LOCK) | ||
61 | #define L2_DMEMORY (CPLB_COMMON | CPLB_LOCK) | ||
62 | |||
63 | #else | ||
58 | #ifdef CONFIG_BFIN_L2_CACHEABLE | 64 | #ifdef CONFIG_BFIN_L2_CACHEABLE |
59 | #define L2_IMEMORY (SDRAM_IGENERIC) | 65 | #define L2_IMEMORY (SDRAM_IGENERIC) |
60 | #define L2_DMEMORY (SDRAM_DGENERIC) | 66 | #define L2_DMEMORY (SDRAM_DGENERIC) |
61 | #else | 67 | #else |
62 | #define L2_IMEMORY (CPLB_COMMON) | 68 | #define L2_IMEMORY (CPLB_COMMON) |
63 | #define L2_DMEMORY (CPLB_COMMON) | 69 | #define L2_DMEMORY (CPLB_COMMON) |
64 | #endif | 70 | #endif /* CONFIG_BFIN_L2_CACHEABLE */ |
71 | |||
72 | #define L2_ATTR (INITIAL_T | SWITCH_T | I_CPLB | D_CPLB) | ||
73 | #endif /* CONFIG_SMP */ | ||
74 | |||
65 | #define SDRAM_DNON_CHBL (CPLB_COMMON) | 75 | #define SDRAM_DNON_CHBL (CPLB_COMMON) |
66 | #define SDRAM_EBIU (CPLB_COMMON) | 76 | #define SDRAM_EBIU (CPLB_COMMON) |
67 | #define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY) | 77 | #define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY) |
@@ -71,14 +81,7 @@ | |||
71 | #define SIZE_1M 0x00100000 /* 1M */ | 81 | #define SIZE_1M 0x00100000 /* 1M */ |
72 | #define SIZE_4M 0x00400000 /* 4M */ | 82 | #define SIZE_4M 0x00400000 /* 4M */ |
73 | 83 | ||
74 | #ifdef CONFIG_MPU | ||
75 | #define MAX_CPLBS 16 | 84 | #define MAX_CPLBS 16 |
76 | #else | ||
77 | #define MAX_CPLBS (16 * 2) | ||
78 | #endif | ||
79 | |||
80 | #define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ | ||
81 | ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M) | ||
82 | 85 | ||
83 | #define CPLB_ENABLE_ICACHE_P 0 | 86 | #define CPLB_ENABLE_ICACHE_P 0 |
84 | #define CPLB_ENABLE_DCACHE_P 1 | 87 | #define CPLB_ENABLE_DCACHE_P 1 |
diff --git a/arch/blackfin/include/asm/cplbinit.h b/arch/blackfin/include/asm/cplbinit.h index f845b41147ba..6bfc25788161 100644 --- a/arch/blackfin/include/asm/cplbinit.h +++ b/arch/blackfin/include/asm/cplbinit.h | |||
@@ -36,6 +36,8 @@ | |||
36 | #ifdef CONFIG_MPU | 36 | #ifdef CONFIG_MPU |
37 | 37 | ||
38 | #include <asm/cplb-mpu.h> | 38 | #include <asm/cplb-mpu.h> |
39 | extern void bfin_icache_init(struct cplb_entry *icplb_tbl); | ||
40 | extern void bfin_dcache_init(struct cplb_entry *icplb_tbl); | ||
39 | 41 | ||
40 | #else | 42 | #else |
41 | 43 | ||
@@ -46,8 +48,40 @@ | |||
46 | 48 | ||
47 | #define IN_KERNEL 1 | 49 | #define IN_KERNEL 1 |
48 | 50 | ||
49 | enum | 51 | #define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ |
50 | {ZERO_P, L1I_MEM, L1D_MEM, SDRAM_KERN , SDRAM_RAM_MTD, SDRAM_DMAZ, RES_MEM, ASYNC_MEM, L2_MEM}; | 52 | ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M) |
53 | |||
54 | #define CPLB_MEM CONFIG_MAX_MEM_SIZE | ||
55 | |||
56 | /* | ||
57 | * Number of required data CPLB switchtable entries | ||
58 | * MEMSIZE / 4 (we mostly install 4M page size CPLBs | ||
59 | * approx 16 for smaller 1MB page size CPLBs for allignment purposes | ||
60 | * 1 for L1 Data Memory | ||
61 | * possibly 1 for L2 Data Memory | ||
62 | * 1 for CONFIG_DEBUG_HUNT_FOR_ZERO | ||
63 | * 1 for ASYNC Memory | ||
64 | */ | ||
65 | #define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \ | ||
66 | + ASYNC_MEMORY_CPLB_COVERAGE) * 2) | ||
67 | |||
68 | /* | ||
69 | * Number of required instruction CPLB switchtable entries | ||
70 | * MEMSIZE / 4 (we mostly install 4M page size CPLBs | ||
71 | * approx 12 for smaller 1MB page size CPLBs for allignment purposes | ||
72 | * 1 for L1 Instruction Memory | ||
73 | * possibly 1 for L2 Instruction Memory | ||
74 | * 1 for CONFIG_DEBUG_HUNT_FOR_ZERO | ||
75 | */ | ||
76 | #define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2) | ||
77 | |||
78 | /* Number of CPLB table entries, used for cplb-nompu. */ | ||
79 | #define CPLB_TBL_ENTRIES (16 * 4) | ||
80 | |||
81 | enum { | ||
82 | ZERO_P, L1I_MEM, L1D_MEM, L2_MEM, SDRAM_KERN, SDRAM_RAM_MTD, SDRAM_DMAZ, | ||
83 | RES_MEM, ASYNC_MEM, OCB_ROM | ||
84 | }; | ||
51 | 85 | ||
52 | struct cplb_desc { | 86 | struct cplb_desc { |
53 | u32 start; /* start address */ | 87 | u32 start; /* start address */ |
@@ -66,8 +100,8 @@ struct cplb_tab { | |||
66 | u16 size; | 100 | u16 size; |
67 | }; | 101 | }; |
68 | 102 | ||
69 | extern u_long icplb_table[]; | 103 | extern u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1]; |
70 | extern u_long dcplb_table[]; | 104 | extern u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1]; |
71 | 105 | ||
72 | /* Till here we are discussing about the static memory management model. | 106 | /* Till here we are discussing about the static memory management model. |
73 | * However, the operating envoronments commonly define more CPLB | 107 | * However, the operating envoronments commonly define more CPLB |
@@ -78,15 +112,18 @@ extern u_long dcplb_table[]; | |||
78 | * This is how Page descriptor Table is implemented in uClinux/Blackfin. | 112 | * This is how Page descriptor Table is implemented in uClinux/Blackfin. |
79 | */ | 113 | */ |
80 | 114 | ||
81 | extern u_long ipdt_table[]; | 115 | extern u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1]; |
82 | extern u_long dpdt_table[]; | 116 | extern u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1]; |
83 | #ifdef CONFIG_CPLB_INFO | 117 | #ifdef CONFIG_CPLB_INFO |
84 | extern u_long ipdt_swapcount_table[]; | 118 | extern u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS]; |
85 | extern u_long dpdt_swapcount_table[]; | 119 | extern u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS]; |
86 | #endif | 120 | #endif |
121 | extern void bfin_icache_init(u_long icplbs[]); | ||
122 | extern void bfin_dcache_init(u_long dcplbs[]); | ||
87 | 123 | ||
88 | #endif /* CONFIG_MPU */ | 124 | #endif /* CONFIG_MPU */ |
89 | 125 | ||
90 | extern void generate_cplb_tables(void); | 126 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) |
91 | 127 | extern void generate_cplb_tables_cpu(unsigned int cpu); | |
128 | #endif | ||
92 | #endif | 129 | #endif |
diff --git a/arch/blackfin/include/asm/mmu_context.h b/arch/blackfin/include/asm/mmu_context.h index 35593dda2a4d..944e29faae48 100644 --- a/arch/blackfin/include/asm/mmu_context.h +++ b/arch/blackfin/include/asm/mmu_context.h | |||
@@ -37,6 +37,10 @@ | |||
37 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
38 | #include <asm/cplbinit.h> | 38 | #include <asm/cplbinit.h> |
39 | 39 | ||
40 | /* Note: L1 stacks are CPU-private things, so we bluntly disable this | ||
41 | feature in SMP mode, and use the per-CPU scratch SRAM bank only to | ||
42 | store the PDA instead. */ | ||
43 | |||
40 | extern void *current_l1_stack_save; | 44 | extern void *current_l1_stack_save; |
41 | extern int nr_l1stack_tasks; | 45 | extern int nr_l1stack_tasks; |
42 | extern void *l1_stack_base; | 46 | extern void *l1_stack_base; |
@@ -88,12 +92,15 @@ activate_l1stack(struct mm_struct *mm, unsigned long sp_base) | |||
88 | static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, | 92 | static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, |
89 | struct task_struct *tsk) | 93 | struct task_struct *tsk) |
90 | { | 94 | { |
95 | #ifdef CONFIG_MPU | ||
96 | unsigned int cpu = smp_processor_id(); | ||
97 | #endif | ||
91 | if (prev_mm == next_mm) | 98 | if (prev_mm == next_mm) |
92 | return; | 99 | return; |
93 | #ifdef CONFIG_MPU | 100 | #ifdef CONFIG_MPU |
94 | if (prev_mm->context.page_rwx_mask == current_rwx_mask) { | 101 | if (prev_mm->context.page_rwx_mask == current_rwx_mask[cpu]) { |
95 | flush_switched_cplbs(); | 102 | flush_switched_cplbs(cpu); |
96 | set_mask_dcplbs(next_mm->context.page_rwx_mask); | 103 | set_mask_dcplbs(next_mm->context.page_rwx_mask, cpu); |
97 | } | 104 | } |
98 | #endif | 105 | #endif |
99 | 106 | ||
@@ -138,9 +145,10 @@ static inline void protect_page(struct mm_struct *mm, unsigned long addr, | |||
138 | 145 | ||
139 | static inline void update_protections(struct mm_struct *mm) | 146 | static inline void update_protections(struct mm_struct *mm) |
140 | { | 147 | { |
141 | if (mm->context.page_rwx_mask == current_rwx_mask) { | 148 | unsigned int cpu = smp_processor_id(); |
142 | flush_switched_cplbs(); | 149 | if (mm->context.page_rwx_mask == current_rwx_mask[cpu]) { |
143 | set_mask_dcplbs(mm->context.page_rwx_mask); | 150 | flush_switched_cplbs(cpu); |
151 | set_mask_dcplbs(mm->context.page_rwx_mask, cpu); | ||
144 | } | 152 | } |
145 | } | 153 | } |
146 | #endif | 154 | #endif |
@@ -165,6 +173,9 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) | |||
165 | static inline void destroy_context(struct mm_struct *mm) | 173 | static inline void destroy_context(struct mm_struct *mm) |
166 | { | 174 | { |
167 | struct sram_list_struct *tmp; | 175 | struct sram_list_struct *tmp; |
176 | #ifdef CONFIG_MPU | ||
177 | unsigned int cpu = smp_processor_id(); | ||
178 | #endif | ||
168 | 179 | ||
169 | #ifdef CONFIG_APP_STACK_L1 | 180 | #ifdef CONFIG_APP_STACK_L1 |
170 | if (current_l1_stack_save == mm->context.l1_stack_save) | 181 | if (current_l1_stack_save == mm->context.l1_stack_save) |
@@ -179,8 +190,8 @@ static inline void destroy_context(struct mm_struct *mm) | |||
179 | kfree(tmp); | 190 | kfree(tmp); |
180 | } | 191 | } |
181 | #ifdef CONFIG_MPU | 192 | #ifdef CONFIG_MPU |
182 | if (current_rwx_mask == mm->context.page_rwx_mask) | 193 | if (current_rwx_mask[cpu] == mm->context.page_rwx_mask) |
183 | current_rwx_mask = NULL; | 194 | current_rwx_mask[cpu] = NULL; |
184 | free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order); | 195 | free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order); |
185 | #endif | 196 | #endif |
186 | } | 197 | } |