mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-18 18:43:59 +08:00
Blackfin: SMP: work around anomaly 05000491
In order to safely work around anomaly 05000491, we have to execute IFLUSH from L1 instruction sram. The trouble with multi-core systems is that all L1 sram is visible only to the active core. So we can't just place the functions into L1 and call it directly. We need to setup a jump table and place the entry point in external memory. This will call the right func based on the active core. In the process, convert from the manual relocation of a small bit of code into Core B's L1 to the more general framework we already have in place for loading arbitrary pieces of code into L1. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
6f546bc3ac
commit
c6345ab1a3
@ -850,7 +850,6 @@ config CPLB_SWITCH_TAB_L1
|
||||
config ICACHE_FLUSH_L1
|
||||
bool "Locate icache flush funcs in L1 Inst Memory"
|
||||
default y
|
||||
depends on !SMP
|
||||
help
|
||||
If enabled, the Blackfin icache flushing functions are linked
|
||||
into L1 instruction memory.
|
||||
|
@ -17,7 +17,12 @@
|
||||
|
||||
#define raw_smp_processor_id() blackfin_core_id()
|
||||
|
||||
extern char coreb_trampoline_start, coreb_trampoline_end;
|
||||
extern void bfin_relocate_coreb_l1_mem(void);
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
|
||||
asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
|
||||
extern unsigned long blackfin_iflush_l1_entry[NR_CPUS];
|
||||
#endif
|
||||
|
||||
struct corelock_slot {
|
||||
int lock;
|
||||
|
@ -215,11 +215,48 @@ void __init bfin_relocate_l1_mem(void)
|
||||
|
||||
early_dma_memcpy_done();
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
|
||||
blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1;
|
||||
#endif
|
||||
|
||||
/* if necessary, copy L2 text/data to L2 SRAM */
|
||||
if (L2_LENGTH && l2_len)
|
||||
memcpy(_stext_l2, _l2_lma, l2_len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void __init bfin_relocate_coreb_l1_mem(void)
|
||||
{
|
||||
unsigned long text_l1_len = (unsigned long)_text_l1_len;
|
||||
unsigned long data_l1_len = (unsigned long)_data_l1_len;
|
||||
unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len;
|
||||
|
||||
blackfin_dma_early_init();
|
||||
|
||||
/* if necessary, copy L1 text to L1 instruction SRAM */
|
||||
if (L1_CODE_LENGTH && text_l1_len)
|
||||
early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma,
|
||||
text_l1_len);
|
||||
|
||||
/* if necessary, copy L1 data to L1 data bank A SRAM */
|
||||
if (L1_DATA_A_LENGTH && data_l1_len)
|
||||
early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma,
|
||||
data_l1_len);
|
||||
|
||||
/* if necessary, copy L1 data B to L1 data bank B SRAM */
|
||||
if (L1_DATA_B_LENGTH && data_b_l1_len)
|
||||
early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma,
|
||||
data_b_l1_len);
|
||||
|
||||
early_dma_memcpy_done();
|
||||
|
||||
#ifdef CONFIG_ICACHE_FLUSH_L1
|
||||
blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 -
|
||||
(unsigned long)_stext_l1 + COREB_L1_CODE_START;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROMKERNEL
|
||||
void __init bfin_relocate_xip_data(void)
|
||||
{
|
||||
|
@ -176,6 +176,7 @@ SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__stext_l1 = .;
|
||||
*(.l1.text.head)
|
||||
*(.l1.text)
|
||||
#ifdef CONFIG_SCHEDULE_L1
|
||||
SCHED_TEXT
|
||||
|
@ -13,7 +13,11 @@
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/trace.h>
|
||||
|
||||
__INIT
|
||||
/*
|
||||
* This code must come first as CoreB is hardcoded (in hardware)
|
||||
* to start at the beginning of its L1 instruction memory.
|
||||
*/
|
||||
.section .l1.text.head
|
||||
|
||||
/* Lay the initial stack into the L1 scratch area of Core B */
|
||||
#define INITIAL_STACK (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
|
||||
@ -160,7 +164,6 @@ ENTRY(_coreb_trampoline_start)
|
||||
.LWAIT_HERE:
|
||||
jump .LWAIT_HERE;
|
||||
ENDPROC(_coreb_trampoline_start)
|
||||
ENTRY(_coreb_trampoline_end)
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.section ".text"
|
||||
|
@ -30,18 +30,11 @@ void __init platform_init_cpus(void)
|
||||
|
||||
void __init platform_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = &coreb_trampoline_end - &coreb_trampoline_start + 1;
|
||||
BUG_ON(len > L1_CODE_LENGTH);
|
||||
|
||||
dma_memcpy((void *)COREB_L1_CODE_START, &coreb_trampoline_start, len);
|
||||
bfin_relocate_coreb_l1_mem();
|
||||
|
||||
/* Both cores ought to be present on a bf561! */
|
||||
cpu_set(0, cpu_present_map); /* CoreA */
|
||||
cpu_set(1, cpu_present_map); /* CoreB */
|
||||
|
||||
printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_L1_CODE_START);
|
||||
}
|
||||
|
||||
int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
|
||||
|
@ -69,10 +69,30 @@
|
||||
#endif
|
||||
|
||||
/* Invalidate all instruction cache lines assocoiated with this memory area */
|
||||
#ifdef CONFIG_SMP
|
||||
# define _blackfin_icache_flush_range _blackfin_icache_flush_range_l1
|
||||
#endif
|
||||
ENTRY(_blackfin_icache_flush_range)
|
||||
do_flush IFLUSH
|
||||
ENDPROC(_blackfin_icache_flush_range)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.text
|
||||
# undef _blackfin_icache_flush_range
|
||||
ENTRY(_blackfin_icache_flush_range)
|
||||
p0.L = LO(DSPID);
|
||||
p0.H = HI(DSPID);
|
||||
r3 = [p0];
|
||||
r3 = r3.b (z);
|
||||
p2 = r3;
|
||||
p0.L = _blackfin_iflush_l1_entry;
|
||||
p0.H = _blackfin_iflush_l1_entry;
|
||||
p0 = p0 + (p2 << 2);
|
||||
p1 = [p0];
|
||||
jump (p1);
|
||||
ENDPROC(_blackfin_icache_flush_range)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DCACHE_FLUSH_L1
|
||||
.section .l1.text
|
||||
#else
|
||||
|
@ -40,6 +40,10 @@
|
||||
*/
|
||||
struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
|
||||
|
||||
#ifdef CONFIG_ICACHE_FLUSH_L1
|
||||
unsigned long blackfin_iflush_l1_entry[NR_CPUS];
|
||||
#endif
|
||||
|
||||
void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
|
||||
*init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
|
||||
*init_saved_dcplb_fault_addr_coreb;
|
||||
|
Loading…
Reference in New Issue
Block a user