aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pk/mentry.S83
-rw-r--r--pk/minit.c10
-rw-r--r--pk/mtrap.c35
-rw-r--r--pk/pk.ld2
4 files changed, 78 insertions, 52 deletions
diff --git a/pk/mentry.S b/pk/mentry.S
index cfbb6a6..1ddd856 100644
--- a/pk/mentry.S
+++ b/pk/mentry.S
@@ -2,6 +2,28 @@
#include "mtrap.h"
+ .data
+ .align 6
+trap_table:
+ .word bad_trap
+ .word bad_trap
+ .word illegal_insn_trap
+ .word bad_trap
+ .word misaligned_load_trap
+ .word bad_trap
+ .word misaligned_store_trap
+ .word bad_trap
+ .word mcall_trap
+ .word bad_trap
+#define HTIF_INTERRUPT_VECTOR 10
+ .word htif_interrupt
+#define TRAP_FROM_MACHINE_MODE_VECTOR 11
+ .word trap_from_machine_mode
+ .word bad_trap
+ .word bad_trap
+ .word bad_trap
+ .word bad_trap
+
#define HANDLE_USER_TRAP_IN_MACHINE_MODE 0 \
| (0 << (31- 0)) /* IF misaligned */ \
| (0 << (31- 1)) /* IF fault */ \
@@ -26,18 +48,6 @@
| (1 << (31- 8)) /* environment call */ \
| (0 << (31- 9)) /* breakpoint */ \
-#define HANDLE_MACHINE_TRAP_IN_MACHINE_MODE 0 \
- | (0 << (31- 0)) /* IF misaligned */ \
- | (0 << (31- 1)) /* IF fault */ \
- | (0 << (31- 2)) /* illegal instruction */ \
- | (0 << (31- 3)) /* reserved */ \
- | (0 << (31- 4)) /* load misaligned */ \
- | (1 << (31- 5)) /* load fault */ \
- | (0 << (31- 6)) /* store misaligned */ \
- | (1 << (31- 7)) /* store fault */ \
- | (1 << (31- 8)) /* environment call */ \
- | (0 << (31- 9)) /* breakpoint */ \
-
.section .text.init,"ax",@progbits
.globl mentry
mentry:
@@ -92,19 +102,13 @@ mentry:
j bad_trap
.align 6
+ # Entry point from machine mode. These are rare, so punt to C code.
csrw mscratch, sp
addi sp, sp, -INTEGER_CONTEXT_SIZE
STORE a0,10*REGBYTES(sp)
STORE a1,11*REGBYTES(sp)
-
- csrr a0, mcause
- li a1, HANDLE_MACHINE_TRAP_IN_MACHINE_MODE
- SLL32 a1, a1, a0
- bltz a1, .Lhandle_trap_in_machine_mode
-
- # Uh oh...
-.Lbad_trap:
- j bad_trap
+ li a0, TRAP_FROM_MACHINE_MODE_VECTOR
+ j .Lhandle_trap_in_machine_mode
.Lsupervisor_double_fault:
# Return to supervisor trap entry with interrupts disabled.
@@ -119,6 +123,8 @@ mentry:
la sp, _end + 2*RISCV_PGSIZE - 1
li t0, -RISCV_PGSIZE
and sp, sp, t0
+ addi sp, sp, -MENTRY_FRAME_SIZE
+ csrw mscratch, sp
j machine_init
# XXX depend on sbi_base to force its linkage
@@ -155,12 +161,12 @@ mentry:
# See if this is an HTIF interrupt; if so, handle it in machine mode.
li a1, IRQ_HOST * 2
bne a0, a1, .Lbad_trap
- li a0, 10
+ li a0, HTIF_INTERRUPT_VECTOR
.Lhandle_trap_in_machine_mode:
# Preserve the registers. Compute the address of the trap handler.
STORE ra, 1*REGBYTES(sp)
- csrr ra, mscratch # ra <- user sp
+ csrrw ra, mscratch, sp # ra <- user sp
STORE gp, 3*REGBYTES(sp)
STORE tp, 4*REGBYTES(sp)
STORE t0, 5*REGBYTES(sp)
@@ -170,7 +176,7 @@ mentry:
STORE t2, 7*REGBYTES(sp)
add t0, t0, t1 # t0 <- %hi(trap_table)[mcause]
STORE s0, 8*REGBYTES(sp)
- lw t0, %pcrel_lo(1b)(t0) # t0 <- handlers[mcause]
+ lw t0, %pcrel_lo(1b)(t0) # t0 <- trap_table[mcause]
STORE s1, 9*REGBYTES(sp)
mv a1, sp # a1 <- regs
STORE a2,12*REGBYTES(sp)
@@ -242,32 +248,19 @@ mentry:
# Go back whence we came.
LOAD a0, 10*REGBYTES(sp)
- csrw mscratch, sp
LOAD sp, 2*REGBYTES(sp)
eret
1:# Redirect the trap to the supervisor.
LOAD a0, 10*REGBYTES(sp)
- csrw mscratch, sp
LOAD sp, 2*REGBYTES(sp)
mrts
- .data
- .align 6
-trap_table:
- .word bad_trap
- .word bad_trap
- .word illegal_insn_trap
- .word bad_trap
- .word misaligned_load_trap
- .word machine_page_fault
- .word misaligned_store_trap
- .word machine_page_fault
- .word mcall_trap
- .word bad_trap
- .word htif_interrupt
- .word bad_trap
- .word bad_trap
- .word bad_trap
- .word bad_trap
- .word bad_trap
+ .globl test_fpu_presence
+test_fpu_presence:
+ # return nonzero FPU present; else, trap handler will cause 0 to be returned.
+ fclass.d a0, f0
+ ret
+
+.Lbad_trap:
+ j bad_trap
diff --git a/pk/minit.c b/pk/minit.c
index abaa5e1..01625bd 100644
--- a/pk/minit.c
+++ b/pk/minit.c
@@ -49,13 +49,17 @@ static void hart_init()
static void fp_init()
{
-#ifdef __riscv_hard_float
kassert(read_csr(mstatus) & MSTATUS_FS);
- SET_FCSR(0);
+ extern int test_fpu_presence();
+
+#ifdef __riscv_hard_float
+ if (!test_fpu_presence())
+ panic("FPU not found; recompile pk with -msoft-float");
for (int i = 0; i < 32; i++)
init_fp_reg(i);
#else
- kassert(!(read_csr(mstatus) & MSTATUS_FS));
+ if (test_fpu_presence())
+ panic("FPU unexpectedly found; recompile pk without -msoft-float");
#endif
}
diff --git a/pk/mtrap.c b/pk/mtrap.c
index 1d461cf..1cb432f 100644
--- a/pk/mtrap.c
+++ b/pk/mtrap.c
@@ -197,13 +197,12 @@ uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs)
return 0;
}
-uintptr_t machine_page_fault(uintptr_t mcause, uintptr_t* regs)
+static uintptr_t machine_page_fault(uintptr_t mcause, uintptr_t* regs, uintptr_t mepc)
{
// See if this trap occurred when emulating an instruction on behalf of
// a lower privilege level.
extern int32_t unprivileged_access_ranges[];
extern int32_t unprivileged_access_ranges_end[];
- uintptr_t mepc = read_csr(mepc);
int32_t* p = unprivileged_access_ranges;
do {
@@ -220,3 +219,35 @@ uintptr_t machine_page_fault(uintptr_t mcause, uintptr_t* regs)
// No. We're boned.
bad_trap();
}
+
+static uintptr_t machine_illegal_instruction(uintptr_t mcause, uintptr_t* regs, uintptr_t mepc)
+{
+ extern void test_fpu_presence();
+ if (mepc == (uintptr_t)&test_fpu_presence) {
+ regs[10] = 0;
+ write_csr(mepc, mepc + 4);
+ return 0;
+ }
+ bad_trap();
+}
+
+uintptr_t trap_from_machine_mode(uintptr_t dummy, uintptr_t* regs)
+{
+ uintptr_t mcause = read_csr(mcause);
+ uintptr_t mepc = read_csr(mepc);
+ // restore mscratch, since we clobbered it.
+ write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE);
+
+ switch (mcause)
+ {
+ case CAUSE_FAULT_LOAD:
+ case CAUSE_FAULT_STORE:
+ return machine_page_fault(mcause, regs, mepc);
+ case CAUSE_ILLEGAL_INSTRUCTION:
+ return machine_illegal_instruction(mcause, regs, mepc);
+ case CAUSE_ECALL:
+ return mcall_trap(mcause, regs);
+ default:
+ bad_trap();
+ }
+}
diff --git a/pk/pk.ld b/pk/pk.ld
index 6f20a56..396716e 100644
--- a/pk/pk.ld
+++ b/pk/pk.ld
@@ -95,7 +95,5 @@ SECTIONS
*(.sbi)
}
- /* End of uninitialized data segment (used by syscalls.c for heap) */
- PROVIDE( end = . );
_end = .;
}