aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/setup.c
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2009-04-23 16:49:43 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-12 06:11:27 -0400
commitfecbd7366bf5a39eaae2c03541f0b412f319534f (patch)
treeb8b034938d916cc3398708ff6a0749f871a64828 /arch/blackfin/kernel/setup.c
parentf5879fda09ea98d7aa845a0e0fa7e508452e5f9f (diff)
Blackfin: fix early L1 relocation crash
Our early L1 relocate code may implicitly call code which lives in L1 memory. This is due to the dma_memcpy() rewrite that made the DMA code lockless and safe to be used by multiple processes. If we start the early DMA memcpy to relocate things into L1 instruction but then our DMA memcpy code calls a function that lives in L1, things fall apart. As such, create a small dedicated DMA memcpy routine that we can assume sanity at boot time. Reported-by: Filip Van Rillaer <filip.vanrillaer@oneaccess-net.com> Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/setup.c')
-rw-r--r--arch/blackfin/kernel/setup.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index a58687bdee6a..0838eafed172 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -150,40 +150,45 @@ void __init bfin_relocate_l1_mem(void)
150 unsigned long l1_data_b_length; 150 unsigned long l1_data_b_length;
151 unsigned long l2_length; 151 unsigned long l2_length;
152 152
153 /*
154 * due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S
155 * we know that everything about l1 text/data is nice and aligned,
156 * so copy by 4 byte chunks, and don't worry about overlapping
157 * src/dest.
158 *
159 * We can't use the dma_memcpy functions, since they can call
160 * scheduler functions which might be in L1 :( and core writes
161 * into L1 instruction cause bad access errors, so we are stuck,
162 * we are required to use DMA, but can't use the common dma
163 * functions. We can't use memcpy either - since that might be
164 * going to be in the relocated L1
165 */
166
153 blackfin_dma_early_init(); 167 blackfin_dma_early_init();
154 168
169 /* if necessary, copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
155 l1_code_length = _etext_l1 - _stext_l1; 170 l1_code_length = _etext_l1 - _stext_l1;
156 if (l1_code_length > L1_CODE_LENGTH) 171 if (l1_code_length)
157 panic("L1 Instruction SRAM Overflow\n"); 172 early_dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
158 /* cannot complain as printk is not available as yet.
159 * But we can continue booting and complain later!
160 */
161
162 /* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
163 dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
164 173
174 /* if necessary, copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
165 l1_data_a_length = _sbss_l1 - _sdata_l1; 175 l1_data_a_length = _sbss_l1 - _sdata_l1;
166 if (l1_data_a_length > L1_DATA_A_LENGTH) 176 if (l1_data_a_length)
167 panic("L1 Data SRAM Bank A Overflow\n"); 177 early_dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
168
169 /* Copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
170 dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
171 178
179 /* if necessary, copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
172 l1_data_b_length = _sbss_b_l1 - _sdata_b_l1; 180 l1_data_b_length = _sbss_b_l1 - _sdata_b_l1;
173 if (l1_data_b_length > L1_DATA_B_LENGTH) 181 if (l1_data_b_length)
174 panic("L1 Data SRAM Bank B Overflow\n"); 182 early_dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
175
176 /* Copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
177 dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
178 l1_data_a_length, l1_data_b_length); 183 l1_data_a_length, l1_data_b_length);
179 184
185 early_dma_memcpy_done();
186
187 /* if necessary, copy _stext_l2 to _edata_l2 to L2 SRAM */
180 if (L2_LENGTH != 0) { 188 if (L2_LENGTH != 0) {
181 l2_length = _sbss_l2 - _stext_l2; 189 l2_length = _sbss_l2 - _stext_l2;
182 if (l2_length > L2_LENGTH) 190 if (l2_length)
183 panic("L2 SRAM Overflow\n"); 191 memcpy(_stext_l2, _l2_lma_start, l2_length);
184
185 /* Copy _stext_l2 to _edata_l2 to L2 SRAM */
186 dma_memcpy(_stext_l2, _l2_lma_start, l2_length);
187 } 192 }
188} 193}
189 194