Files
Wang Chen 992b0ba91c fixed bug for syscall example
The original logic of setting mstatus has problem.
The or directive cannot set .MPP to 0.

Optimize the original code and use csrs and csrc instead.

Note we cannot assume the default value of mstatus is zero.
rvos may not be the first one to run on the system/virt.
It just so lucky that the initial value of mstatus is zero
on QEMU/virt.

Signed-off-by: Wang Chen <wangchen20@iscas.ac.cn>
2024-03-25 21:10:40 +08:00

82 lines
2.6 KiB
ArmAsm

#include "platform.h"
# size of each hart's stack is 1024 bytes
.equ STACK_SIZE, 1024
.global _start
.text
_start:
# park harts with id != 0
csrr t0, mhartid # read current hart id
mv tp, t0 # keep CPU's hartid in its tp for later usage.
bnez t0, park # if we're not on the hart 0
# we park the hart
# Set all bytes in the BSS section to zero.
la a0, _bss_start
la a1, _bss_end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
# Setup stacks, the stack grows from bottom to top, so we put the
# stack pointer to the very end of the stack range.
slli t0, t0, 10 # shift left the hart id by 1024
la sp, stacks + STACK_SIZE # set the initial stack pointer
# to the end of the first stack space
add sp, sp, t0 # move the current hart stack pointer
# to its place in the stack space
#ifdef CONFIG_SYSCALL
# https://lore.kernel.org/qemu-devel/20201223192553.332508-1-atish.patra@wdc.com/
# For qemu version >= 6.0, exception would be raised if no PMP enty is
# configured. So just configure one entny, which allows all the whole
# 32-bits physical address range is R/W/X.
# FIXME: I say it is a temporary workaroud due to I think the patch
# above contains bug, and I have raised new issue to qemu but it has not
# been rootcaused till now. Details please refer to
# https://gitlab.com/qemu-project/qemu/-/issues/585 or
# https://gitee.com/unicornx/riscv-operating-system-mooc/issues/I441IC (in chinese)
# So it's just a temporary workaround till now to not block people who
# want to try newer qemu (>= 6.0).
li t0, 0xffffffff
csrw pmpaddr0, t0
li t0, 0xf
csrw pmpcfg0, t0
#endif
# At the end of start_kernel, schedule() will call MRET to switch
# to the first task, so we parepare the mstatus here.
# Notice: It is best not to assume that the initial value of mstatus is
# zero.
#ifdef CONFIG_SYSCALL
# Set mstatus.MPP as 0, so we will run in User mode after MRET.
# No need to set mstatus.MPIE to 1 explicitly, because according to ISA
# specification: interrupts for M-mode, which is higher than U-mode, are
# always globally enabled regardless of the setting of the global MIE bit.
li t0, 3 << 11
csrc mstatus, t0
#else
# Set mstatus.MPP to 3, so we still run in Machine mode after MRET.
# Set mstatus.MPIE to 1, so MRET will enable the interrupt.
li t0, 3 << 11 | 1 << 7
csrs mstatus, t0
#endif
j start_kernel # hart 0 jump to c
park:
wfi
j park
# In the standard RISC-V calling convention, the stack pointer sp
# is always 16-byte aligned.
.balign 16
stacks:
.skip STACK_SIZE * MAXNUM_CPU # allocate space for all the harts stacks
.end # End of file