mirror of
https://github.com/plctlab/riscv-operating-system-mooc.git
synced 2025-12-05 15:15:49 +00:00
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>
82 lines
2.6 KiB
ArmAsm
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
|