2020-03-10 04:04:17 +00:00
|
|
|
#if __riscv_xlen == 64
|
|
|
|
|
# define STORE sd
|
|
|
|
|
# define LOAD ld
|
|
|
|
|
# define LOG_REGBYTES 3
|
|
|
|
|
#else
|
|
|
|
|
# define STORE sw
|
|
|
|
|
# define LOAD lw
|
|
|
|
|
# define LOG_REGBYTES 2
|
|
|
|
|
#endif
|
|
|
|
|
#define REGBYTES (1 << LOG_REGBYTES)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Entry point of all programs (_start).
|
|
|
|
|
|
|
|
|
|
It initializes DWARF call frame information, the stack pointer, the
|
|
|
|
|
frame pointer (needed for closures to work in start_rust) and the global
|
|
|
|
|
pointer. Then it calls _start_rust.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.section .text.init, "ax"
|
|
|
|
|
|
|
|
|
|
.global _start
|
|
|
|
|
|
|
|
|
|
_start:
|
|
|
|
|
// Set trap handler, which will be called
|
|
|
|
|
// on interrupts and cpu faults
|
|
|
|
|
la t0, _start_trap
|
|
|
|
|
csrw stvec, t0
|
|
|
|
|
|
|
|
|
|
// Jump to a program to initialize global variables.
|
|
|
|
|
// Note that at this point, the .data section should
|
|
|
|
|
// have already been set up by the loader.
|
|
|
|
|
jal x1, init
|
|
|
|
|
|
2020-06-03 10:28:22 +00:00
|
|
|
// Call the kmain function. This function diverges, so
|
2020-03-10 04:04:17 +00:00
|
|
|
// shouldn't ever return.
|
2020-06-03 10:28:22 +00:00
|
|
|
j kmain
|
2020-03-10 04:04:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Trap entry point (_start_trap)
|
|
|
|
|
|
|
|
|
|
Saves all process context into a structure that is
|
|
|
|
|
mapped to each thread at 0xff801000. Return happens
|
|
|
|
|
elsewhere.
|
|
|
|
|
*/
|
|
|
|
|
.section .trap, "ax"
|
|
|
|
|
.global _start_trap
|
|
|
|
|
|
|
|
|
|
_start_trap:
|
|
|
|
|
csrw sscratch, sp
|
|
|
|
|
li sp, 0xff801000
|
2020-03-24 07:24:19 +00:00
|
|
|
STORE x1, 0*REGBYTES(sp) // Store x1 in the scratch field
|
2020-03-27 04:30:29 +00:00
|
|
|
LOAD x1, 1*REGBYTES(sp) // Load current context number
|
2020-03-24 07:24:19 +00:00
|
|
|
slli x1, x1, 7 // Multiply current context number by 32
|
|
|
|
|
add sp, sp, x1 // Set $sp to 0xff801000 + (current_context * 32)
|
2020-03-10 04:04:17 +00:00
|
|
|
|
|
|
|
|
STORE x1, 0*REGBYTES(sp)
|
|
|
|
|
// Skip SP for now
|
|
|
|
|
STORE x3, 2*REGBYTES(sp)
|
|
|
|
|
STORE x4, 3*REGBYTES(sp)
|
|
|
|
|
STORE x5, 4*REGBYTES(sp)
|
|
|
|
|
STORE x6, 5*REGBYTES(sp)
|
|
|
|
|
STORE x7, 6*REGBYTES(sp)
|
|
|
|
|
STORE x8, 7*REGBYTES(sp)
|
|
|
|
|
STORE x9, 8*REGBYTES(sp)
|
|
|
|
|
STORE x10, 9*REGBYTES(sp)
|
|
|
|
|
STORE x11, 10*REGBYTES(sp)
|
|
|
|
|
STORE x12, 11*REGBYTES(sp)
|
|
|
|
|
STORE x13, 12*REGBYTES(sp)
|
|
|
|
|
STORE x14, 13*REGBYTES(sp)
|
|
|
|
|
STORE x15, 14*REGBYTES(sp)
|
|
|
|
|
STORE x16, 15*REGBYTES(sp)
|
|
|
|
|
STORE x17, 16*REGBYTES(sp)
|
|
|
|
|
STORE x18, 17*REGBYTES(sp)
|
|
|
|
|
STORE x19, 18*REGBYTES(sp)
|
|
|
|
|
STORE x20, 19*REGBYTES(sp)
|
|
|
|
|
STORE x21, 20*REGBYTES(sp)
|
|
|
|
|
STORE x22, 21*REGBYTES(sp)
|
|
|
|
|
STORE x23, 22*REGBYTES(sp)
|
|
|
|
|
STORE x24, 23*REGBYTES(sp)
|
|
|
|
|
STORE x25, 24*REGBYTES(sp)
|
|
|
|
|
STORE x26, 25*REGBYTES(sp)
|
|
|
|
|
STORE x27, 26*REGBYTES(sp)
|
|
|
|
|
STORE x28, 27*REGBYTES(sp)
|
|
|
|
|
STORE x29, 28*REGBYTES(sp)
|
|
|
|
|
STORE x30, 29*REGBYTES(sp)
|
|
|
|
|
STORE x31, 30*REGBYTES(sp)
|
|
|
|
|
|
|
|
|
|
// Save SEPC
|
|
|
|
|
csrr t0, sepc
|
|
|
|
|
STORE t0, 31*REGBYTES(sp)
|
|
|
|
|
|
2020-03-16 10:22:59 +00:00
|
|
|
// Save x1, which was used to calculate the offset. Prior to
|
|
|
|
|
// calculating, it was stashed at 0xff801000.
|
|
|
|
|
li t0, 0xff801000
|
|
|
|
|
LOAD t1, 0*REGBYTES(t0)
|
|
|
|
|
STORE t1, 0*REGBYTES(sp)
|
|
|
|
|
|
2020-03-10 04:04:17 +00:00
|
|
|
// Finally, save SP
|
|
|
|
|
csrr t0, sscratch
|
|
|
|
|
STORE t0, 1*REGBYTES(sp)
|
|
|
|
|
|
|
|
|
|
// Restore a default stack pointer
|
|
|
|
|
li sp, 0xfffefffc
|
|
|
|
|
|
|
|
|
|
// Note that registers $a0-$a7 still contain the arguments
|
|
|
|
|
j _start_trap_rust
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Resume a context (_xous_resume_context)
|
|
|
|
|
|
2020-06-16 08:34:49 +00:00
|
|
|
Restores all registers from a Context passed in $a0.
|
2020-03-10 04:04:17 +00:00
|
|
|
Note that the SEPC and SSTATUS should be set already.
|
|
|
|
|
*/
|
|
|
|
|
.global _xous_resume_context
|
|
|
|
|
_xous_resume_context:
|
|
|
|
|
move sp, a0
|
|
|
|
|
|
|
|
|
|
LOAD x1, 0*REGBYTES(sp)
|
|
|
|
|
// Skip SP for now
|
|
|
|
|
LOAD x3, 2*REGBYTES(sp)
|
|
|
|
|
LOAD x4, 3*REGBYTES(sp)
|
|
|
|
|
LOAD x5, 4*REGBYTES(sp)
|
|
|
|
|
LOAD x6, 5*REGBYTES(sp)
|
|
|
|
|
LOAD x7, 6*REGBYTES(sp)
|
|
|
|
|
LOAD x8, 7*REGBYTES(sp)
|
|
|
|
|
LOAD x9, 8*REGBYTES(sp)
|
|
|
|
|
LOAD x10, 9*REGBYTES(sp)
|
|
|
|
|
LOAD x11, 10*REGBYTES(sp)
|
|
|
|
|
LOAD x12, 11*REGBYTES(sp)
|
|
|
|
|
LOAD x13, 12*REGBYTES(sp)
|
|
|
|
|
LOAD x14, 13*REGBYTES(sp)
|
|
|
|
|
LOAD x15, 14*REGBYTES(sp)
|
|
|
|
|
LOAD x16, 15*REGBYTES(sp)
|
|
|
|
|
LOAD x17, 16*REGBYTES(sp)
|
|
|
|
|
LOAD x18, 17*REGBYTES(sp)
|
|
|
|
|
LOAD x19, 18*REGBYTES(sp)
|
|
|
|
|
LOAD x20, 19*REGBYTES(sp)
|
|
|
|
|
LOAD x21, 20*REGBYTES(sp)
|
|
|
|
|
LOAD x22, 21*REGBYTES(sp)
|
|
|
|
|
LOAD x23, 22*REGBYTES(sp)
|
|
|
|
|
LOAD x24, 23*REGBYTES(sp)
|
|
|
|
|
LOAD x25, 24*REGBYTES(sp)
|
|
|
|
|
LOAD x26, 25*REGBYTES(sp)
|
|
|
|
|
LOAD x27, 26*REGBYTES(sp)
|
|
|
|
|
LOAD x28, 27*REGBYTES(sp)
|
|
|
|
|
LOAD x29, 28*REGBYTES(sp)
|
|
|
|
|
LOAD x30, 29*REGBYTES(sp)
|
|
|
|
|
LOAD x31, 30*REGBYTES(sp)
|
|
|
|
|
|
|
|
|
|
// Restore SP
|
|
|
|
|
LOAD x2, 1*REGBYTES(sp)
|
|
|
|
|
sret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Return from a syscall with arguments (_xous_syscall_return_result)
|
|
|
|
|
|
|
|
|
|
Xous passes arguments in $a0-$a7, however the RISC-V calling convention
|
|
|
|
|
states that only $a0 and $a1 are used. To work around this, we pass
|
|
|
|
|
a pointer to a 32-byte structure in $a0, and this function moves that
|
|
|
|
|
into the registers. It then restores the context from other registers.
|
|
|
|
|
*/
|
|
|
|
|
.global _xous_syscall_return_result
|
|
|
|
|
_xous_syscall_return_result:
|
|
|
|
|
|
2020-03-16 10:22:59 +00:00
|
|
|
move sp, a1
|
|
|
|
|
LOAD t0, 31*REGBYTES(sp)
|
|
|
|
|
csrw sepc, t0
|
2020-03-10 04:04:17 +00:00
|
|
|
|
|
|
|
|
LOAD x1, 0*REGBYTES(sp)
|
|
|
|
|
// Skip SP for now
|
|
|
|
|
LOAD x3, 2*REGBYTES(sp)
|
|
|
|
|
LOAD x4, 3*REGBYTES(sp)
|
|
|
|
|
LOAD x5, 4*REGBYTES(sp)
|
|
|
|
|
LOAD x6, 5*REGBYTES(sp)
|
|
|
|
|
LOAD x7, 6*REGBYTES(sp)
|
|
|
|
|
LOAD x8, 7*REGBYTES(sp)
|
|
|
|
|
LOAD x9, 8*REGBYTES(sp)
|
2020-03-16 10:22:59 +00:00
|
|
|
|
|
|
|
|
// Load argument registers from the value pointed
|
|
|
|
|
// to by $a0
|
|
|
|
|
LOAD a7, 7*REGBYTES(a0)
|
|
|
|
|
LOAD a6, 6*REGBYTES(a0)
|
|
|
|
|
LOAD a5, 5*REGBYTES(a0)
|
|
|
|
|
LOAD a4, 4*REGBYTES(a0)
|
|
|
|
|
LOAD a3, 3*REGBYTES(a0)
|
|
|
|
|
LOAD a2, 2*REGBYTES(a0)
|
|
|
|
|
LOAD a1, 1*REGBYTES(a0)
|
|
|
|
|
LOAD a0, 0*REGBYTES(a0)
|
|
|
|
|
|
2020-03-10 04:04:17 +00:00
|
|
|
LOAD x18, 17*REGBYTES(sp)
|
|
|
|
|
LOAD x19, 18*REGBYTES(sp)
|
|
|
|
|
LOAD x20, 19*REGBYTES(sp)
|
|
|
|
|
LOAD x21, 20*REGBYTES(sp)
|
|
|
|
|
LOAD x22, 21*REGBYTES(sp)
|
|
|
|
|
LOAD x23, 22*REGBYTES(sp)
|
|
|
|
|
LOAD x24, 23*REGBYTES(sp)
|
|
|
|
|
LOAD x25, 24*REGBYTES(sp)
|
|
|
|
|
LOAD x26, 25*REGBYTES(sp)
|
|
|
|
|
LOAD x27, 26*REGBYTES(sp)
|
|
|
|
|
LOAD x28, 27*REGBYTES(sp)
|
|
|
|
|
LOAD x29, 28*REGBYTES(sp)
|
|
|
|
|
LOAD x30, 29*REGBYTES(sp)
|
|
|
|
|
LOAD x31, 30*REGBYTES(sp)
|
|
|
|
|
|
2020-03-16 10:22:59 +00:00
|
|
|
// Restore SP
|
|
|
|
|
//csrr t0, sscratch
|
2020-03-10 04:04:17 +00:00
|
|
|
LOAD x2, 1*REGBYTES(sp)
|
|
|
|
|
sret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.global flush_mmu
|
|
|
|
|
flush_mmu:
|
|
|
|
|
sfence.vma
|
|
|
|
|
ret
|