Skip to content

Instantly share code, notes, and snippets.

@knknkn1162 knknkn1162/fw_base.S
Last active Oct 17, 2019

Embed
What would you like to do?
hart with hart_id==0
.align 3
.section .entry, "ax", %progbits
.globl _start
.globl _start_warm
_start:
csrr a6, CSR_MHARTID // assume that hart_id=0
// The condition `zero < a6=0` is false
blt zero, a6, _wait_relocate_copy_done
/* Save load address */
la t0, _load_start
la t1, _start
REG_S t1, 0(t0) // _load_start <- _start
_relocate:
la t0, _link_start // RISCV_PTR _fw_start
REG_L t0, 0(t0)
la t1, _link_end
REG_L t1, 0(t1)
la t2, _load_start // this is _start
REG_L t2, 0(t2)
sub t3, t1, t0
add t3, t3, t2
// _fw_start == _start, so jump
beq t0, t2, _relocate_done // yes and jump
// skip _relocate
_relocate_done:
/*
* Mark relocate copy done
* Use _boot_status copy relative to the load address
*/
la t0, _boot_status
la t1, _link_start
REG_L t1, 0(t1)
la t2, _load_start
REG_L t2, 0(t2)
sub t0, t0, t1
add t0, t0, t2
li t1, BOOT_STATUS_RELOCATE_DONE // #define BOOT_STATUS_RELOCATE_DONE 1
REG_S t1, 0(t0)
fence rw, rw
/* Reset all registers for boot HART */
li ra, 0
call _reset_regs
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4 // save
call fw_save_info
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4 // restore
/* Preload HART details
// .hart_count = VIRT_HART_COUNT=8,
// .hart_stack_size = VIRT_HART_STACK_SIZE=8192,
* s7 -> HART Count
* s8 -> HART Stack Size
*/
la a4, platform
#if __riscv_xlen == 64 // yes
lwu s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4) // VIRT_HART_COUNT=8
lwu s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4) // VIRT_HART_STACK_SIZE = 8192
#else
lw s7, SBI_PLATFORM_HART_COUNT_OFFSET(a4)
lw s8, SBI_PLATFORM_HART_STACK_SIZE_OFFSET(a4)
#endif
/* Setup scratch space for all the HARTs*/
la tp, _fw_end
mul a5, s7, s8
add tp, tp, a5
/* Keep a copy of tp */
add t3, tp, zero
/* Counter */
li t2, 1
/* hartid 0 is mandated by RISC-V ISA */
li t1, 0
_scratch_init: // initialize scratch space which is `struct sbi_scratch`
add tp, t3, zero
mul a5, s8, t1
sub tp, tp, a5
li a5, SBI_SCRATCH_SIZE
sub tp, tp, a5
/* Initialize scratch space */
/* Store fw_start and fw_size in scratch space */
la a4, _fw_start
la a5, _fw_end
mul t0, s7, s8
add a5, a5, t0
sub a5, a5, a4
REG_S a4, SBI_SCRATCH_FW_START_OFFSET(tp)
REG_S a5, SBI_SCRATCH_FW_SIZE_OFFSET(tp)
/* Store next arg1 in scratch space */
MOV_3R s0, a0, s1, a1, s2, a2 // save s*
call fw_next_arg1
REG_S a0, SBI_SCRATCH_NEXT_ARG1_OFFSET(tp)
MOV_3R a0, s0, a1, s1, a2, s2 // restore a*
/* Store next address in scratch space */
MOV_3R s0, a0, s1, a1, s2, a2
call fw_next_addr // la a0, payload_bin
REG_S a0, SBI_SCRATCH_NEXT_ADDR_OFFSET(tp)
MOV_3R a0, s0, a1, s1, a2, s2
/* Store next mode in scratch space */
MOV_3R s0, a0, s1, a1, s2, a2
call fw_next_mode // li a0, PRV_S
REG_S a0, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
MOV_3R a0, s0, a1, s1, a2, s2
/* Store warm_boot address in scratch space */
la a4, _start_warm
REG_S a4, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET(tp)
/* Store platform address in scratch space */
la a4, platform
REG_S a4, SBI_SCRATCH_PLATFORM_ADDR_OFFSET(tp)
/* Store hartid-to-scratch function address in scratch space */
la a4, _hartid_to_scratch
REG_S a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
/* Clear tmp0 in scratch space */
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
/* Store firmware options in scratch space */
MOV_3R s0, a0, s1, a1, s2, a2
#ifdef FW_OPTIONS // no
li a4, FW_OPTIONS
#else
add a4, zero, zero
#endif
call fw_options // don't care
or a4, a4, a0
REG_S a4, SBI_SCRATCH_OPTIONS_OFFSET(tp) // unsigned long options;
MOV_3R a0, s0, a1, s1, a2, s2
/* Move to next scratch space */
add t1, t1, t2 // t2: counter
// s7 -> HART Count
blt t1, s7, _scratch_init
/* Zero-out BSS */
la a4, _bss_start
la a5, _bss_end
_bss_zero:
REG_S zero, (a4)
add a4, a4, __SIZEOF_POINTER__
blt a4, a5, _bss_zero
/* Override pervious arg1 */
MOV_3R s0, a0, s1, a1, s2, a2
call fw_prev_arg1 // if not FW_PAYLOAD_FDT_PATH, set a0=0
add t1, a0, zero
MOV_3R a0, s0, a1, s1, a2, s2
beqz t1, _prev_arg1_override_done
add a1, t1, zero
_prev_arg1_override_done:
// if configure Flatened Device Tree (FDT). In `QEMU RISC-V Virt Machine Platform`, a1=0
beqz a1, _fdt_reloc_done // yes and jump
// skip FDT configuration
_fdt_reloc_done:
/* mark boot hart done */
li t0, BOOT_STATUS_BOOT_HART_DONE
la t1, _boot_status
REG_S t0, 0(t1) // now synced with hart with hart_id>=1
fence rw, rw
j _start_warm
_start_warm:
// skip
call sbi_init
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.