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
*/
csrr a6, CSR_MHARTID
blt zero, a6, _wait_for_boot_hart
blt zero, a6, _wait_relocate_copy_done
/* Save load address */
la t0, _load_start
@ -72,7 +72,7 @@ _relocate:
blt t2, t0, _relocate_copy_to_upper
_relocate_copy_to_lower:
ble t1, t2, _relocate_copy_to_lower_loop
la t3, _boot_hart_done
la t3, _boot_status
BRANGE t2, t1, t3, _start_hang
la t3, _relocate
la t5, _relocate_done
@ -88,7 +88,7 @@ _relocate_copy_to_lower_loop:
jr t4
_relocate_copy_to_upper:
ble t3, t0, _relocate_copy_to_upper_loop
la t2, _boot_hart_done
la t2, _boot_status
BRANGE t0, t3, t2, _start_hang
la t2, _relocate
la t5, _relocate_done
@ -102,8 +102,34 @@ _relocate_copy_to_upper_loop:
REG_S t2, 0(t1)
blt t0, t1, _relocate_copy_to_upper_loop
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:
/* 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 */
/* Reset all registers for boot HART */
@ -274,31 +300,23 @@ _fdt_reloc_again:
blt t1, t2, _fdt_reloc_again
_fdt_reloc_done:
/* Update boot hart flag */
la a4, _boot_hart_done
la a5, _start_warm
REG_S a5, (a4)
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)
/* mark boot hart done */
li t0, 2
la t1, _boot_status
REG_S t0, 0(t1)
fence rw, rw
j _start_warm
/* Wait for boot hart */
/* waitting for boot hart done (_boot_status == 2) */
_wait_for_boot_hart:
la a4, _boot_hart_done
REG_L a5, 0(a4)
li t0, 2
la t1, _boot_status
REG_L t1, 0(t1)
/* Reduce the bus traffic so that boot hart may proceed faster */
nop
nop
nop
beqz a5, _wait_for_boot_hart
jr a5
bne t0, t1, _wait_for_boot_hart
_start_warm:
/* Reset all registers for non-boot HARTs */
@ -352,7 +370,7 @@ _start_warm:
j _start_hang
.align 3
_boot_hart_done:
_boot_status:
RISCV_PTR 0
_load_start:
RISCV_PTR _fw_start