os-workshop

same materials and sample source for RV32 OS projects
git clone http://frotz.net/git/os-workshop.git
Log | Files | Refs

trap-entry-dual-stack.S (3255B)


      1 // Copyright 2022, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0
      3 
      4 // This file provides assembly glue for handling traps
      5 // (interrupts or exceptions) and safely saving and
      6 // restoring the processor state of the code running
      7 // when the trap happened.
      8 
      9 // It assume a dual stack setup -- when an interrupt
     10 // or exception occurs, a kernel stack will be used to
     11 // save the state -- whether or not the active user
     12 // stack is valid will not matter.
     13 
     14 // It will call into interrupt_handler() or exception_handler()
     15 // to process the interrupt or exception.
     16 
     17 // For interrupts, only the registers that must be saved
     18 // are saved (the others are callee-save so the C code
     19 // called into will save them if necessary).
     20 
     21 // For exceptions, ALL registers are saved so that the
     22 // exception handler my inspect, display, or modify them
     23 // as necesary.
     24 
     25 // hw/context.h defines structures tframe_t and eframe_t 
     26 // that correspond to how the registers are saved on the
     27 // stack
     28 
     29 .global trap_entry
     30 trap_entry:
     31 	// swap the user sp with the kernel sp
     32 	// stored in SSCRATCH 
     33 	csrrw sp, sscratch, sp
     34 
     35 	// reserve stack space for a full eframe_t
     36 	addi sp, sp, - (32 * 4)
     37 
     38 	// save caller-save registers (tframe_t)
     39 	sw ra, 0x00(sp)
     40 	sw t0, 0x04(sp)
     41 	sw t1, 0x08(sp)
     42 	sw t2, 0x0C(sp)
     43 	sw t3, 0x10(sp)
     44 	sw t4, 0x14(sp)
     45 	sw t5, 0x18(sp)
     46 	sw t6, 0x1C(sp)
     47 	sw a0, 0x20(sp)
     48 	sw a1, 0x24(sp)
     49 	sw a2, 0x28(sp)
     50 	sw a3, 0x2C(sp)
     51 	sw a4, 0x30(sp)
     52 	sw a5, 0x34(sp)
     53 	sw a6, 0x38(sp)
     54 	sw a7, 0x3C(sp)
     55 
     56 	// save user pc which hw stashed in SEPC
     57 	// and user sp which we stashed in SSCRATCH
     58 	csrr t0, sepc
     59 	csrr t1, sscratch
     60 	sw t0, 0x40(sp)
     61 	sw t1, 0x44(sp)
     62 
     63 	// if the scause high bit is clear, it is an exception
     64 	csrr t0, scause
     65 	bge t0, zero, exception_entry
     66 
     67 	// otherwise it is an interrupt, call interrupt_handler()
     68 	jal interrupt_handler
     69 
     70 .globl trap_exit
     71 trap_exit:
     72 	// restore kernel sp to sscratch
     73 	addi t0, sp, (32 * 4)
     74 	csrw sscratch, t0
     75 
     76 	// user pc goes into sepc for sret
     77 	lw t0, 0x40(sp)
     78 	csrw sepc, t0
     79 
     80 	// restore the caller-save registers
     81 	lw ra, 0x00(sp)
     82 	lw t0, 0x04(sp)
     83 	lw t1, 0x08(sp)
     84 	lw t2, 0x0C(sp)
     85 	lw t3, 0x10(sp)
     86 	lw t4, 0x14(sp)
     87 	lw t5, 0x18(sp)
     88 	lw t6, 0x1C(sp)
     89 	lw a0, 0x20(sp)
     90 	lw a1, 0x24(sp)
     91 	lw a2, 0x28(sp)
     92 	lw a3, 0x2C(sp)
     93 	lw a4, 0x30(sp)
     94 	lw a5, 0x34(sp)
     95 	lw a6, 0x38(sp)
     96 	lw a7, 0x3C(sp)
     97 
     98 	// finally restore the user sp
     99 	lw sp, 0x44(sp)
    100 
    101 	// and return from trap
    102 	sret
    103 
    104 exception_entry:
    105 	// save the callee-save registers (cframe_t)
    106 	// user pc and sp already stored at 0x40(sp), 0x44(sp)
    107 	sw gp, 0x48(sp)
    108 	sw tp, 0x4C(sp)
    109 	sw s0, 0x50(sp)
    110 	sw s1, 0x54(sp)
    111 	sw s2, 0x58(sp)
    112 	sw s3, 0x5C(sp)
    113 	sw s4, 0x60(sp)
    114 	sw s5, 0x64(sp)
    115 	sw s6, 0x68(sp)
    116 	sw s7, 0x6C(sp)
    117 	sw s8, 0x70(sp)
    118 	sw s9, 0x74(sp)
    119 	sw s10, 0x78(sp)
    120 	sw s11, 0x7C(sp)
    121 
    122 	// call exception_handler() passing eframe_t*
    123 	// as the first argument
    124 	mv a0, sp
    125 	jal exception_handler
    126 
    127 .globl exception_exit
    128 exception_exit:
    129 	lw gp, 0x48(sp)
    130 	lw tp, 0x4C(sp)
    131 	lw s0, 0x50(sp)
    132 	lw s1, 0x54(sp)
    133 	lw s2, 0x58(sp)
    134 	lw s3, 0x5C(sp)
    135 	lw s4, 0x60(sp)
    136 	lw s5, 0x64(sp)
    137 	lw s6, 0x68(sp)
    138 	lw s7, 0x6C(sp)
    139 	lw s8, 0x70(sp)
    140 	lw s9, 0x74(sp)
    141 	lw s10, 0x78(sp)
    142 	lw s11, 0x7C(sp)
    143 
    144 	j trap_exit
    145 
    146 .globl user_mode_entry
    147 user_mode_entry:
    148 	mv sp, a0
    149 	j exception_exit