summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiang W <wxjstz@126.com>2019-06-20 10:01:10 +0300
committerAnup Patel <anup.patel@wdc.com>2019-06-24 07:09:18 +0300
commit65aa5873c377cfd01f4923e02871e401be644162 (patch)
treea30e05d7c46c1300a32d6451637e82b4653c73b8
parentcd2dfdc870ed3a03c3afc28e25f770fada0a396e (diff)
downloadopensbi-65aa5873c377cfd01f4923e02871e401be644162.tar.xz
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>
-rw-r--r--firmware/fw_base.S60
1 files changed, 39 insertions, 21 deletions
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 6270bbc..213396a 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -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