Forked from 404小队 / OSKernel2021-404
Source project has a limited visibility.
entry.S 6.26 KiB
#include <asm.h>
#include <csr.h>
.macro SAVE_CONTEXT
  .local _restore_kernel_tpsp
  .local _save_context
  .local _from_kernel
# csrrw tp, CSR_SSCRATCH, tp
# bnez tp, _save_context
# _restore_kernel_tpsp:
#   csrr tp, CSR_SSCRATCH
#   sd sp, PCB_KERNEL_SP(tp)
_save_context:
  /* HappyEric uses tp as current_running */
   * If coming from userspace, tp is greater or equal to 0
   * If coming from kernel, tp is less than 0xffffffff00000000
  bltz tp, _from_kernel
  csrw CSR_SSCRATCH, tp
  ld tp, current_running
  sd sp, PCB_USER_SP(tp) /* user sp is real */
  ld sp, PCB_KERNEL_SP(tp)
  csrr tp, CSR_SSCRATCH
_from_kernel:
  addi sp, sp, -(OFFSET_SIZE)
  /* TODO: save all general purpose registers here! */
  sd zero, OFFSET_REG_ZERO(sp)
  sd ra, OFFSET_REG_RA(sp)
  sd gp, OFFSET_REG_GP(sp)
  /* push tp */
  sd tp, OFFSET_REG_TP(sp)
  ld tp, current_running
  sd sp, PCB_KERNEL_SP(tp) /* very important */
  sd t0, OFFSET_REG_T0(sp)
  sd t1, OFFSET_REG_T1(sp)
  sd t2, OFFSET_REG_T2(sp)
  sd s0, OFFSET_REG_S0(sp)
  sd s1, OFFSET_REG_S1(sp)
  sd a0, OFFSET_REG_A0(sp)
  sd a1, OFFSET_REG_A1(sp)
  sd a2, OFFSET_REG_A2(sp)
  sd a3, OFFSET_REG_A3(sp)
  sd a4, OFFSET_REG_A4(sp)
  sd a5, OFFSET_REG_A5(sp)
  sd a6, OFFSET_REG_A6(sp)
  sd a7, OFFSET_REG_A7(sp)
  sd s2, OFFSET_REG_S2(sp)
  sd s3, OFFSET_REG_S3(sp)
  sd s4, OFFSET_REG_S4(sp)
  sd s5, OFFSET_REG_S5(sp)
  sd s6, OFFSET_REG_S6(sp)
  sd s7, OFFSET_REG_S7(sp)
  sd s8, OFFSET_REG_S8(sp)
  sd s9, OFFSET_REG_S9(sp)
  sd s10, OFFSET_REG_S10(sp)
  sd s11, OFFSET_REG_S11(sp)
  sd t3, OFFSET_REG_T3(sp)
  sd t4, OFFSET_REG_T4(sp)
  sd t5, OFFSET_REG_T5(sp)
  sd t6, OFFSET_REG_T6(sp)
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/* * Disable user-mode memory access as it should only be set in the * actual user copy routines. * * Disable the FPU to detect illegal usage of floating point in kernel * space. */ li t0, SR_SUM | SR_FS /* TODO: save sstatus, sepc, stval, scause and sscratch on kernel stack */ csrr s0, CSR_SSTATUS sd s0, OFFSET_REG_SSTATUS(sp) csrr s0, CSR_SEPC sd s0, OFFSET_REG_SEPC(sp) csrr s0, CSR_STVAL sd s0, OFFSET_REG_SBADADDR(sp) csrr s0, CSR_SCAUSE sd s0, OFFSET_REG_SCAUSE(sp) csrr s0, CSR_SATP sd s0, OFFSET_REG_SATP(sp) .endm .macro RESTORE_CONTEXT .local _back_to_kernel /* TODO: Restore all registers and sepc,sstatus */ ld zero, OFFSET_REG_ZERO(sp) ld ra, OFFSET_REG_RA(sp) ld gp, OFFSET_REG_GP(sp) ld tp, OFFSET_REG_TP(sp) ld t0, OFFSET_REG_T0(sp) ld t1, OFFSET_REG_T1(sp) ld t2, OFFSET_REG_T2(sp) ld s1, OFFSET_REG_S1(sp) ld a0, OFFSET_REG_A0(sp) ld a1, OFFSET_REG_A1(sp) ld a2, OFFSET_REG_A2(sp) ld a3, OFFSET_REG_A3(sp) ld a4, OFFSET_REG_A4(sp) ld a5, OFFSET_REG_A5(sp) ld a6, OFFSET_REG_A6(sp) ld a7, OFFSET_REG_A7(sp) ld s2, OFFSET_REG_S2(sp) ld s3, OFFSET_REG_S3(sp) ld s4, OFFSET_REG_S4(sp) ld s5, OFFSET_REG_S5(sp) ld s6, OFFSET_REG_S6(sp) ld s7, OFFSET_REG_S7(sp) ld s8, OFFSET_REG_S8(sp) ld s9, OFFSET_REG_S9(sp) ld s10, OFFSET_REG_S10(sp) ld s11, OFFSET_REG_S11(sp) ld t3, OFFSET_REG_T3(sp) ld t4, OFFSET_REG_T4(sp) ld t5, OFFSET_REG_T5(sp) ld t6, OFFSET_REG_T6(sp) ld s0, OFFSET_REG_SSTATUS(sp) csrw CSR_SSTATUS, s0 ld s0, OFFSET_REG_SEPC(sp) csrw CSR_SEPC, s0 ld s0, OFFSET_REG_SATP(sp) fence
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
fence.i sfence.vma fence fence.i csrw CSR_SATP, s0 fence fence.i sfence.vma fence fence.i ld s0, OFFSET_REG_S0(sp) addi sp, sp, OFFSET_SIZE bltz tp, _back_to_kernel csrw CSR_SSCRATCH, tp ld tp, current_running sd sp, PCB_KERNEL_SP(tp) ld sp, PCB_USER_SP(tp) csrr tp, CSR_SSCRATCH _back_to_kernel: .endm ENTRY(enable_preempt) ld t1, current_running ld t0, PCB_PREEMPT_COUNT(t1) beq t0, zero, do_enable addi t0, t0, -1 sd t0, PCB_PREEMPT_COUNT(t1) beq t0, zero, do_enable jr ra do_enable: not t0, x0 csrs CSR_SIE, t0 jr ra ENDPROC(enable_preempt) ENTRY(disable_preempt) csrw CSR_SIE, zero ld t1, current_running ld t0, PCB_PREEMPT_COUNT(t1) addi t0, t0, 1 sd t0, PCB_PREEMPT_COUNT(t1) jr ra ENDPROC(disable_preempt) ENTRY(enable_interrupt) li t0, SR_SIE csrs CSR_SSTATUS, t0 jr ra ENDPROC(enable_interrupt) ENTRY(disable_interrupt) li t0, SR_SIE csrc CSR_SSTATUS, t0 jr ra ENDPROC(disable_interrupt) // the address of previous pcb in a0 // the address of next pcb in a1 ENTRY(switch_to) beqz a0, switch_to_restore addi tp, a0, 0 // save all callee save registers on kernel stack addi sp, sp, -(SWITCH_TO_SIZE) sd ra, SWITCH_TO_RA(sp) sd s0, SWITCH_TO_S0(sp) sd s1, SWITCH_TO_S1(sp)
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
sd s2, SWITCH_TO_S2(sp) sd s3, SWITCH_TO_S3(sp) sd s4, SWITCH_TO_S4(sp) sd s5, SWITCH_TO_S5(sp) sd s6, SWITCH_TO_S6(sp) sd s7, SWITCH_TO_S7(sp) sd s8, SWITCH_TO_S8(sp) sd s9, SWITCH_TO_S9(sp) sd s10, SWITCH_TO_S10(sp) sd s11, SWITCH_TO_S11(sp) csrr s11, CSR_SATP sd s11, SWITCH_TO_SATP(sp) sd sp, PCB_KERNEL_SP(tp) switch_to_restore: // restore next addi tp, a1, 0 ld sp, PCB_KERNEL_SP(tp) ld s0, SWITCH_TO_SATP(sp) fence fence.i sfence.vma fence fence.i csrw CSR_SATP, s0 fence fence.i sfence.vma fence fence.i ld s0, SWITCH_TO_S0(sp) ld s1, SWITCH_TO_S1(sp) ld s2, SWITCH_TO_S2(sp) ld s3, SWITCH_TO_S3(sp) ld s4, SWITCH_TO_S4(sp) ld s5, SWITCH_TO_S5(sp) ld s6, SWITCH_TO_S6(sp) ld s7, SWITCH_TO_S7(sp) ld s8, SWITCH_TO_S8(sp) ld s9, SWITCH_TO_S9(sp) ld s10, SWITCH_TO_S10(sp) ld s11, SWITCH_TO_S11(sp) ld ra, SWITCH_TO_RA(sp) addi sp, sp, SWITCH_TO_SIZE jr ra ENDPROC(switch_to) ENTRY(ret_from_exception) sd sp, PCB_KERNEL_SP(tp) call handle_signal ld sp, PCB_KERNEL_SP(tp) RESTORE_CONTEXT sret ENDPROC(ret_from_exception) ENTRY(exception_handler_entry) .align 4 SAVE_CONTEXT /* Load the global pointer */ .option push .option norelax la gp, __global_pointer$ .option pop
281282283284285286287288289290291292293294295296297298299300301302303304305306307
csrw CSR_SSCRATCH, x0 /* TODO: load ret_from_exception into $ra * so that we can return to ret_from_exception * when interrupt_help complete. */ la ra, ret_from_exception /* TODO: call interrupt_helper * note: dont forget to pass parameters for it. */ ld a0, PCB_KERNEL_SP(tp) csrr a1, CSR_STVAL csrr a2, CSR_SCAUSE mv a3, tp la t0, interrupt_helper jr t0 ENDPROC(exception_handler_entry) ENTRY(do_sret) csrw CSR_SEPC, ra sret ENDPROC(do_sret)