firmware: Handle overlapping load and link addresses in relocation

The old code may corrupt the code of the waiting hart hence this patch
keeps waiting HART within relocation code range at time of relocation.

Signed-off-by: Xiang W <wxjstz@126.com>
Acked-by: Anup Patel <anup.patel@wdc.com>
This commit is contained in:
Xiang W 2019-06-20 15:01:10 +08:00 committed by Anup Patel
parent cd2dfdc870
commit 65aa5873c3
1 changed files with 39 additions and 21 deletions

View File

@ -48,7 +48,7 @@ _start:
* that is, for mhartid != 0 * that is, for mhartid != 0
*/ */
csrr a6, CSR_MHARTID csrr a6, CSR_MHARTID
blt zero, a6, _wait_for_boot_hart blt zero, a6, _wait_relocate_copy_done
/* Save load address */ /* Save load address */
la t0, _load_start la t0, _load_start
@ -72,7 +72,7 @@ _relocate:
blt t2, t0, _relocate_copy_to_upper blt t2, t0, _relocate_copy_to_upper
_relocate_copy_to_lower: _relocate_copy_to_lower:
ble t1, t2, _relocate_copy_to_lower_loop ble t1, t2, _relocate_copy_to_lower_loop
la t3, _boot_hart_done la t3, _boot_status
BRANGE t2, t1, t3, _start_hang BRANGE t2, t1, t3, _start_hang
la t3, _relocate la t3, _relocate
la t5, _relocate_done la t5, _relocate_done
@ -88,7 +88,7 @@ _relocate_copy_to_lower_loop:
jr t4 jr t4
_relocate_copy_to_upper: _relocate_copy_to_upper:
ble t3, t0, _relocate_copy_to_upper_loop ble t3, t0, _relocate_copy_to_upper_loop
la t2, _boot_hart_done la t2, _boot_status
BRANGE t0, t3, t2, _start_hang BRANGE t0, t3, t2, _start_hang
la t2, _relocate la t2, _relocate
la t5, _relocate_done la t5, _relocate_done
@ -102,8 +102,34 @@ _relocate_copy_to_upper_loop:
REG_S t2, 0(t1) REG_S t2, 0(t1)
blt t0, t1, _relocate_copy_to_upper_loop blt t0, t1, _relocate_copy_to_upper_loop
jr t4 jr t4
_wait_relocate_copy_done:
la t0, _start
la t1, _link_start
REG_L t1, 0(t1)
la t2, _boot_status
sub t2, t2, t0
add t2, t2, t1
la t3, _wait_for_boot_hart
sub t3, t3, t0
add t3, t3, t1
1:
/* waitting for relocate copy done (_boot_status == 1) */
li t4, 1
REG_L t5, 0(t2)
/* Reduce the bus traffic so that boot hart may proceed faster */
nop
nop
nop
bne t4, t5, 1b
jr t3
_relocate_done: _relocate_done:
/* mark relocate copy done */
la t0, _boot_status
li t1, 1
REG_S t1, 0(t0)
fence rw, rw
/* At this point we are running from link address */ /* At this point we are running from link address */
/* Reset all registers for boot HART */ /* Reset all registers for boot HART */
@ -274,31 +300,23 @@ _fdt_reloc_again:
blt t1, t2, _fdt_reloc_again blt t1, t2, _fdt_reloc_again
_fdt_reloc_done: _fdt_reloc_done:
/* Update boot hart flag */ /* mark boot hart done */
la a4, _boot_hart_done li t0, 2
la a5, _start_warm la t1, _boot_status
REG_S a5, (a4) REG_S t0, 0(t1)
fence rw, rw
la t0, _link_start
REG_L t0, 0(t0)
sub a4, a4, t0
la t0, _load_start
REG_L t0, 0(t0)
add a4, a4, t0
REG_S a5, (a4)
fence rw, rw fence rw, rw
j _start_warm j _start_warm
/* Wait for boot hart */ /* waitting for boot hart done (_boot_status == 2) */
_wait_for_boot_hart: _wait_for_boot_hart:
la a4, _boot_hart_done li t0, 2
REG_L a5, 0(a4) la t1, _boot_status
REG_L t1, 0(t1)
/* Reduce the bus traffic so that boot hart may proceed faster */ /* Reduce the bus traffic so that boot hart may proceed faster */
nop nop
nop nop
nop nop
beqz a5, _wait_for_boot_hart bne t0, t1, _wait_for_boot_hart
jr a5
_start_warm: _start_warm:
/* Reset all registers for non-boot HARTs */ /* Reset all registers for non-boot HARTs */
@ -352,7 +370,7 @@ _start_warm:
j _start_hang j _start_hang
.align 3 .align 3
_boot_hart_done: _boot_status:
RISCV_PTR 0 RISCV_PTR 0
_load_start: _load_start:
RISCV_PTR _fw_start RISCV_PTR _fw_start