Browse Source

Don't rely on mstatus.fs to determine FPU presence

pull/9/head
Andrew Waterman 11 years ago
parent
commit
e554f30be8
  1. 83
      pk/mentry.S
  2. 10
      pk/minit.c
  3. 35
      pk/mtrap.c
  4. 2
      pk/pk.ld

83
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

10
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
}

35
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();
}
}

2
pk/pk.ld

@ -95,7 +95,5 @@ SECTIONS
*(.sbi)
}
/* End of uninitialized data segment (used by syscalls.c for heap) */
PROVIDE( end = . );
_end = .;
}

Loading…
Cancel
Save