From 4678e84c040531a48eff2108fd9212660bf527ae Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 15 Feb 2017 15:20:06 -0800 Subject: Incorporate sptbr/sfence.vma changes --- bbl/bbl.c | 2 +- machine/encoding.h | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++--- machine/minit.c | 13 ++---- machine/mtrap.c | 4 +- machine/vm.h | 6 +-- 5 files changed, 130 insertions(+), 20 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 487a416..eacb6c3 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -51,7 +51,7 @@ static void supervisor_vm_init() mb(); root_page_table = root_pt; - write_csr(sptbr, (uintptr_t)root_pt >> RISCV_PGSHIFT); + write_csr(sptbr, ((uintptr_t)root_pt >> RISCV_PGSHIFT) | SPTBR_MODE); } void boot_loader() diff --git a/machine/encoding.h b/machine/encoding.h index 8aeac4c..9a87807 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -19,7 +19,6 @@ #define MSTATUS_MPRV 0x00020000 #define MSTATUS_PUM 0x00040000 #define MSTATUS_MXR 0x00080000 -#define MSTATUS_VM 0x1F000000 #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000 @@ -114,6 +113,20 @@ #define VM_SV39 9 #define VM_SV48 10 +#define SPTBR32_MODE 0x80000000 +#define SPTBR32_ASID 0x7FC00000 +#define SPTBR32_PPN 0x003FFFFF +#define SPTBR64_MODE 0xE000000000000000 +#define SPTBR64_ASID 0x1FFFE00000000000 +#define SPTBR64_PPN 0x0000003FFFFFFFFF + +#define SPTBR_MODE_OFF 0 +#define SPTBR_MODE_SV32 1 +#define SPTBR_MODE_SV39 4 +#define SPTBR_MODE_SV48 5 +#define SPTBR_MODE_SV57 6 +#define SPTBR_MODE_SV64 7 + #define IRQ_S_SOFT 1 #define IRQ_H_SOFT 2 #define IRQ_M_SOFT 3 @@ -208,7 +221,7 @@ #endif #endif -/* Automatically generated by parse-opcodes */ +/* Automatically generated by parse-opcodes. */ #ifndef RISCV_ENCODING_H #define RISCV_ENCODING_H #define MATCH_BEQ 0x63 @@ -397,8 +410,8 @@ #define MASK_MRET 0xffffffff #define MATCH_DRET 0x7b200073 #define MASK_DRET 0xffffffff -#define MATCH_SFENCE_VM 0x10400073 -#define MASK_SFENCE_VM 0xfff07fff +#define MATCH_SFENCE_VMA 0x12000073 +#define MASK_SFENCE_VMA 0xfe007fff #define MATCH_WFI 0x10500073 #define MASK_WFI 0xffffffff #define MATCH_CSRRW 0x1073 @@ -457,6 +470,34 @@ #define MASK_FCVT_D_S 0xfff0007f #define MATCH_FSQRT_D 0x5a000053 #define MASK_FSQRT_D 0xfff0007f +#define MATCH_FADD_Q 0x6000053 +#define MASK_FADD_Q 0xfe00007f +#define MATCH_FSUB_Q 0xe000053 +#define MASK_FSUB_Q 0xfe00007f +#define MATCH_FMUL_Q 0x16000053 +#define MASK_FMUL_Q 0xfe00007f +#define MATCH_FDIV_Q 0x1e000053 +#define MASK_FDIV_Q 0xfe00007f +#define MATCH_FSGNJ_Q 0x26000053 +#define MASK_FSGNJ_Q 0xfe00707f +#define MATCH_FSGNJN_Q 0x26001053 +#define MASK_FSGNJN_Q 0xfe00707f +#define MATCH_FSGNJX_Q 0x26002053 +#define MASK_FSGNJX_Q 0xfe00707f +#define MATCH_FMIN_Q 0x2e000053 +#define MASK_FMIN_Q 0xfe00707f +#define MATCH_FMAX_Q 0x2e001053 +#define MASK_FMAX_Q 0xfe00707f +#define MATCH_FCVT_S_Q 0x40300053 +#define MASK_FCVT_S_Q 0xfff0007f +#define MATCH_FCVT_Q_S 0x46000053 +#define MASK_FCVT_Q_S 0xfff0007f +#define MATCH_FCVT_D_Q 0x42300053 +#define MASK_FCVT_D_Q 0xfff0007f +#define MATCH_FCVT_Q_D 0x46100053 +#define MASK_FCVT_Q_D 0xfff0007f +#define MATCH_FSQRT_Q 0x5e000053 +#define MASK_FSQRT_Q 0xfff0007f #define MATCH_FLE_S 0xa0000053 #define MASK_FLE_S 0xfe00707f #define MATCH_FLT_S 0xa0001053 @@ -469,6 +510,12 @@ #define MASK_FLT_D 0xfe00707f #define MATCH_FEQ_D 0xa2002053 #define MASK_FEQ_D 0xfe00707f +#define MATCH_FLE_Q 0xa6000053 +#define MASK_FLE_Q 0xfe00707f +#define MATCH_FLT_Q 0xa6001053 +#define MASK_FLT_Q 0xfe00707f +#define MATCH_FEQ_Q 0xa6002053 +#define MASK_FEQ_Q 0xfe00707f #define MATCH_FCVT_W_S 0xc0000053 #define MASK_FCVT_W_S 0xfff0007f #define MATCH_FCVT_WU_S 0xc0100053 @@ -493,6 +540,18 @@ #define MASK_FMV_X_D 0xfff0707f #define MATCH_FCLASS_D 0xe2001053 #define MASK_FCLASS_D 0xfff0707f +#define MATCH_FCVT_W_Q 0xc6000053 +#define MASK_FCVT_W_Q 0xfff0007f +#define MATCH_FCVT_WU_Q 0xc6100053 +#define MASK_FCVT_WU_Q 0xfff0007f +#define MATCH_FCVT_L_Q 0xc6200053 +#define MASK_FCVT_L_Q 0xfff0007f +#define MATCH_FCVT_LU_Q 0xc6300053 +#define MASK_FCVT_LU_Q 0xfff0007f +#define MATCH_FMV_X_Q 0xe6000053 +#define MASK_FMV_X_Q 0xfff0707f +#define MATCH_FCLASS_Q 0xe6001053 +#define MASK_FCLASS_Q 0xfff0707f #define MATCH_FCVT_S_W 0xd0000053 #define MASK_FCVT_S_W 0xfff0007f #define MATCH_FCVT_S_WU 0xd0100053 @@ -513,14 +572,28 @@ #define MASK_FCVT_D_LU 0xfff0007f #define MATCH_FMV_D_X 0xf2000053 #define MASK_FMV_D_X 0xfff0707f +#define MATCH_FCVT_Q_W 0xd6000053 +#define MASK_FCVT_Q_W 0xfff0007f +#define MATCH_FCVT_Q_WU 0xd6100053 +#define MASK_FCVT_Q_WU 0xfff0007f +#define MATCH_FCVT_Q_L 0xd6200053 +#define MASK_FCVT_Q_L 0xfff0007f +#define MATCH_FCVT_Q_LU 0xd6300053 +#define MASK_FCVT_Q_LU 0xfff0007f +#define MATCH_FMV_Q_X 0xf6000053 +#define MASK_FMV_Q_X 0xfff0707f #define MATCH_FLW 0x2007 #define MASK_FLW 0x707f #define MATCH_FLD 0x3007 #define MASK_FLD 0x707f +#define MATCH_FLQ 0x4007 +#define MASK_FLQ 0x707f #define MATCH_FSW 0x2027 #define MASK_FSW 0x707f #define MATCH_FSD 0x3027 #define MASK_FSD 0x707f +#define MATCH_FSQ 0x4027 +#define MASK_FSQ 0x707f #define MATCH_FMADD_S 0x43 #define MASK_FMADD_S 0x600007f #define MATCH_FMSUB_S 0x47 @@ -537,6 +610,14 @@ #define MASK_FNMSUB_D 0x600007f #define MATCH_FNMADD_D 0x200004f #define MASK_FNMADD_D 0x600007f +#define MATCH_FMADD_Q 0x6000043 +#define MASK_FMADD_Q 0x600007f +#define MATCH_FMSUB_Q 0x6000047 +#define MASK_FMSUB_Q 0x600007f +#define MATCH_FNMSUB_Q 0x600004b +#define MASK_FNMSUB_Q 0x600007f +#define MATCH_FNMADD_Q 0x600004f +#define MASK_FNMADD_Q 0x600007f #define MATCH_C_NOP 0x1 #define MASK_C_NOP 0xffff #define MATCH_C_ADDI16SP 0x6101 @@ -967,7 +1048,7 @@ DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) -DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) +DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA) DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) @@ -997,12 +1078,29 @@ DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) +DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q) +DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q) +DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q) +DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q) +DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q) +DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q) +DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q) +DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q) +DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q) +DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q) +DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S) +DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q) +DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D) +DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q) DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) +DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q) +DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q) +DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q) DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) @@ -1015,6 +1113,12 @@ DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) +DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q) +DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q) +DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q) +DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q) +DECLARE_INSN(fmv_x_q, MATCH_FMV_X_Q, MASK_FMV_X_Q) +DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q) DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) @@ -1025,10 +1129,17 @@ DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) +DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W) +DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU) +DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L) +DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU) +DECLARE_INSN(fmv_q_x, MATCH_FMV_Q_X, MASK_FMV_Q_X) DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) +DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ) DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) +DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ) DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) @@ -1037,6 +1148,10 @@ DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) +DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q) +DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q) +DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q) +DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q) DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) diff --git a/machine/minit.c b/machine/minit.c index b3f2c86..06e8d25 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -15,15 +15,8 @@ size_t plic_ndevs; static void mstatus_init() { - // Enable FPU and set VM mode - uintptr_t ms = 0; - ms = INSERT_FIELD(ms, MSTATUS_VM, VM_CHOICE); - ms = INSERT_FIELD(ms, MSTATUS_FS, 1); - write_csr(mstatus, ms); - - // Make sure the hart actually supports the VM mode we want - ms = read_csr(mstatus); - assert(EXTRACT_FIELD(ms, MSTATUS_VM) == VM_CHOICE); + // Enable FPU + write_csr(mstatus, MSTATUS_FS); // Enable user/supervisor use of perf counters write_csr(mucounteren, -1); @@ -156,7 +149,7 @@ void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack) write_csr(mstatus, mstatus); write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE); write_csr(mepc, fn); - write_csr(sptbr, (uintptr_t)root_page_table >> RISCV_PGSHIFT); + write_csr(sptbr, ((uintptr_t)root_page_table >> RISCV_PGSHIFT) | SPTBR_MODE); asm volatile ("mv a0, %0; mv sp, %0; mret" : : "r" (stack)); __builtin_unreachable(); } diff --git a/machine/mtrap.c b/machine/mtrap.c index 07f7d10..34772b7 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -3,6 +3,7 @@ #include "htif.h" #include "atomic.h" #include "bits.h" +#include "vm.h" #include #include #include @@ -176,6 +177,7 @@ void software_interrupt() *HLS()->ipi = 0; mb(); int ipi_pending = atomic_swap(&HLS()->mipi_pending, 0); + mb(); if (ipi_pending & IPI_SOFT) { HLS()->sipi_pending = 1; @@ -186,7 +188,7 @@ void software_interrupt() asm volatile ("fence.i"); if (ipi_pending & IPI_SFENCE_VM) - asm volatile ("sfence.vm"); + flush_tlb(); } static void send_ipi_many(uintptr_t* pmask, int event) diff --git a/machine/vm.h b/machine/vm.h index 4e6bcc1..6d3da4e 100644 --- a/machine/vm.h +++ b/machine/vm.h @@ -6,11 +6,11 @@ #define MEGAPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS)) #if __riscv_xlen == 64 -# define VM_CHOICE VM_SV39 +# define SPTBR_MODE INSERT_FIELD(0, SPTBR64_MODE, SPTBR_MODE_SV39) # define VA_BITS 39 # define GIGAPAGE_SIZE (MEGAPAGE_SIZE << RISCV_PGLEVEL_BITS) #else -# define VM_CHOICE VM_SV32 +# define SPTBR_MODE INSERT_FIELD(0, SPTBR32_MODE, SPTBR_MODE_SV32) # define VA_BITS 32 #endif @@ -19,7 +19,7 @@ extern pte_t* root_page_table; static inline void flush_tlb() { - asm volatile("sfence.vm"); + asm volatile ("sfence.vma"); } static inline pte_t pte_create(uintptr_t ppn, int type) -- cgit v1.1 From 15a111444d6819021328e990eb5308155a9def6a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 15 Feb 2017 15:26:09 -0800 Subject: Emulate RVFC instructions --- machine/emulation.c | 70 ++++++++++++++++++++++++++++++++++++++++--- machine/emulation.h | 37 ++++++++++++++++++----- machine/fp_emulation.c | 2 ++ machine/fp_emulation.h | 17 +++++++---- machine/fp_ldst.c | 46 +++++++++++----------------- machine/misaligned_ldst.c | 49 ++++++++++++++++++++++++++++++ machine/unprivileged_memory.h | 16 ++++++++-- 7 files changed, 190 insertions(+), 47 deletions(-) diff --git a/machine/emulation.c b/machine/emulation.c index 882daa1..696467d 100644 --- a/machine/emulation.c +++ b/machine/emulation.c @@ -5,6 +5,67 @@ #include "mtrap.h" #include +static DECLARE_EMULATION_FUNC(emulate_rvc) +{ +#ifdef __riscv_compressed + // the only emulable RVC instructions are FP loads and stores. +# if !defined(__riscv_flen) && defined(PK_ENABLE_FP_EMULATION) + write_csr(mepc, mepc + 2); + + // if FPU is disabled, punt back to the OS + if (unlikely((mstatus & MSTATUS_FS) == 0)) + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + + if ((insn & MASK_C_FLD) == MATCH_C_FLD) { + uintptr_t addr = GET_RS1S(insn, regs) + RVC_LD_IMM(insn); + if (unlikely(addr % sizeof(uintptr_t))) + return misaligned_load_trap(regs, mcause, mepc); + SET_F64_RD(RVC_RS2S(insn) << SH_RD, regs, load_uint64_t((void *)addr, mepc)); + } else if ((insn & MASK_C_FLDSP) == MATCH_C_FLDSP) { + uintptr_t addr = GET_SP(regs) + RVC_LDSP_IMM(insn); + if (unlikely(addr % sizeof(uintptr_t))) + return misaligned_load_trap(regs, mcause, mepc); + SET_F64_RD(insn, regs, load_uint64_t((void *)addr, mepc)); + } else if ((insn & MASK_C_FSD) == MATCH_C_FSD) { + uintptr_t addr = GET_RS1S(insn, regs) + RVC_LD_IMM(insn); + if (unlikely(addr % sizeof(uintptr_t))) + return misaligned_store_trap(regs, mcause, mepc); + store_uint64_t((void *)addr, GET_F64_RS2(RVC_RS2S(insn) << SH_RS2, regs), mepc); + } else if ((insn & MASK_C_FSDSP) == MATCH_C_FSDSP) { + uintptr_t addr = GET_SP(regs) + RVC_SDSP_IMM(insn); + if (unlikely(addr % sizeof(uintptr_t))) + return misaligned_store_trap(regs, mcause, mepc); + store_uint64_t((void *)addr, GET_F64_RS2(RVC_RS2(insn) << SH_RS2, regs), mepc); + } else +# if __riscv_xlen == 32 + if ((insn & MASK_C_FLW) == MATCH_C_FLW) { + uintptr_t addr = GET_RS1S(insn, regs) + RVC_LW_IMM(insn); + if (unlikely(addr % 4)) + return misaligned_load_trap(regs, mcause, mepc); + SET_F32_RD(RVC_RS2S(insn) << SH_RD, regs, load_int32_t((void *)addr, mepc)); + } else if ((insn & MASK_C_FLWSP) == MATCH_C_FLWSP) { + uintptr_t addr = GET_SP(regs) + RVC_LWSP_IMM(insn); + if (unlikely(addr % 4)) + return misaligned_load_trap(regs, mcause, mepc); + SET_F32_RD(insn, regs, load_int32_t((void *)addr, mepc)); + } else if ((insn & MASK_C_FSW) == MATCH_C_FSW) { + uintptr_t addr = GET_RS1S(insn, regs) + RVC_LW_IMM(insn); + if (unlikely(addr % 4)) + return misaligned_store_trap(regs, mcause, mepc); + store_uint32_t((void *)addr, GET_F32_RS2(RVC_RS2S(insn) << SH_RS2, regs), mepc); + } else if ((insn & MASK_C_FSWSP) == MATCH_C_FSWSP) { + uintptr_t addr = GET_SP(regs) + RVC_SWSP_IMM(insn); + if (unlikely(addr % 4)) + return misaligned_store_trap(regs, mcause, mepc); + store_uint32_t((void *)addr, GET_F32_RS2(RVC_RS2(insn) << SH_RS2, regs), mepc); + } else +# endif +# endif +#endif + + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); +} + void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) { asm (".pushsection .rodata\n" @@ -70,8 +131,8 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) uintptr_t mstatus; insn_t insn = get_insn(mepc, &mstatus); - if (unlikely((insn & 3) != 3)) - return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); + if ((insn & 3) != 3) + return emulate_rvc(regs, mcause, mepc, mstatus, insn); write_csr(mepc, mepc + 4); @@ -81,9 +142,10 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) f(regs, mcause, mepc, mstatus, insn); } -void __attribute__((noinline)) truly_illegal_insn(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc, uintptr_t mstatus, insn_t insn) +__attribute__((noinline)) +DECLARE_EMULATION_FUNC(truly_illegal_insn) { - redirect_trap(mepc, mstatus); + return redirect_trap(mepc, mstatus); } static inline int emulate_read_csr(int num, uintptr_t mstatus, uintptr_t* result) diff --git a/machine/emulation.h b/machine/emulation.h index b8712b5..156d847 100644 --- a/machine/emulation.h +++ b/machine/emulation.h @@ -5,22 +5,45 @@ #include "bits.h" #include -typedef uint32_t insn_t; +typedef uintptr_t insn_t; typedef void (*emulation_func)(uintptr_t*, uintptr_t, uintptr_t, uintptr_t, insn_t); #define DECLARE_EMULATION_FUNC(name) void name(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc, uintptr_t mstatus, insn_t insn) void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc); void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc); -void redirect_trap(uintptr_t epc, uintptr_t mstatus) __attribute__((noreturn)); -DECLARE_EMULATION_FUNC(truly_illegal_insn) __attribute__((noreturn)); +void redirect_trap(uintptr_t epc, uintptr_t mstatus); +DECLARE_EMULATION_FUNC(truly_illegal_insn); +DECLARE_EMULATION_FUNC(emulate_rvc_0); +DECLARE_EMULATION_FUNC(emulate_rvc_2); +#define SH_RD 7 +#define SH_RS1 15 +#define SH_RS2 20 +#define SH_RS2C 2 + +#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1)) +#define RVC_LW_IMM(x) ((RV_X(x, 6, 1) << 2) | (RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 1) << 6)) +#define RVC_LD_IMM(x) ((RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 2) << 6)) +#define RVC_LWSP_IMM(x) ((RV_X(x, 4, 3) << 2) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 2) << 6)) +#define RVC_LDSP_IMM(x) ((RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 3) << 6)) +#define RVC_SWSP_IMM(x) ((RV_X(x, 9, 4) << 2) | (RV_X(x, 7, 2) << 6)) +#define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | (RV_X(x, 7, 3) << 6)) +#define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3)) +#define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3)) +#define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5) + +#define SHIFT_RIGHT(x, y) ((y) < 0 ? ((x) << -(y)) : ((x) >> (y))) #define GET_REG(insn, pos, regs) ({ \ int mask = (1 << (5+LOG_REGBYTES)) - (1 << LOG_REGBYTES); \ - (uintptr_t*)((uintptr_t)regs + (((insn) >> ((pos) - LOG_REGBYTES)) & mask)); \ + (uintptr_t*)((uintptr_t)regs + (SHIFT_RIGHT(insn, (pos) - LOG_REGBYTES) & (mask))); \ }) -#define GET_RS1(insn, regs) (*GET_REG(insn, 15, regs)) -#define GET_RS2(insn, regs) (*GET_REG(insn, 20, regs)) -#define SET_RD(insn, regs, val) (*GET_REG(insn, 7, regs) = (val)) +#define GET_RS1(insn, regs) (*GET_REG(insn, SH_RS1, regs)) +#define GET_RS2(insn, regs) (*GET_REG(insn, SH_RS2, regs)) +#define GET_RS1S(insn, regs) (*GET_REG(RVC_RS1S(insn), 0, regs)) +#define GET_RS2S(insn, regs) (*GET_REG(RVC_RS2S(insn), 0, regs)) +#define GET_RS2C(insn, regs) (*GET_REG(insn, SH_RS2C, regs)) +#define GET_SP(regs) (*GET_REG(2, 0, regs)) +#define SET_RD(insn, regs, val) (*GET_REG(insn, SH_RD, regs) = (val)) #define IMM_I(insn) ((int32_t)(insn) >> 20) #define IMM_S(insn) (((int32_t)(insn) >> 25 << 5) | (int32_t)(((insn) >> 7) & 0x1f)) #define MASK_FUNCT3 0x7000 diff --git a/machine/fp_emulation.c b/machine/fp_emulation.c index 182567a..0bbe83c 100644 --- a/machine/fp_emulation.c +++ b/machine/fp_emulation.c @@ -331,6 +331,7 @@ DECLARE_EMULATION_FUNC(emulate_fcmp) } return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); success: + SET_FS_DIRTY(); SET_RD(insn, regs, result); } @@ -358,6 +359,7 @@ DECLARE_EMULATION_FUNC(emulate_fmv_if) return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); } + SET_FS_DIRTY(); SET_RD(insn, regs, result); } diff --git a/machine/fp_emulation.h b/machine/fp_emulation.h index c2177a2..97950df 100644 --- a/machine/fp_emulation.h +++ b/machine/fp_emulation.h @@ -10,25 +10,25 @@ #ifdef __riscv_flen # define GET_F32_REG(insn, pos, regs) ({ \ - register int32_t value asm("a0") = ((insn) >> ((pos)-3)) & 0xf8; \ + register int32_t value asm("a0") = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ uintptr_t tmp; \ asm ("1: auipc %0, %%pcrel_hi(get_f32_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp), "+&r"(value) :: "t0"); \ value; }) # define SET_F32_REG(insn, pos, regs, val) ({ \ register uint32_t value asm("a0") = (val); \ - uintptr_t offset = ((insn) >> ((pos)-3)) & 0xf8; \ + uintptr_t offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ uintptr_t tmp; \ asm volatile ("1: auipc %0, %%pcrel_hi(put_f32_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp) : "r"(value), "r"(offset) : "t0"); }) # define init_fp_reg(i) SET_F32_REG((i) << 3, 3, 0, 0) # define GET_F64_REG(insn, pos, regs) ({ \ - register uintptr_t value asm("a0") = ((insn) >> ((pos)-3)) & 0xf8; \ + register uintptr_t value asm("a0") = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ uintptr_t tmp; \ asm ("1: auipc %0, %%pcrel_hi(get_f64_reg); add %0, %0, %1; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp), "+&r"(value) :: "t0"); \ sizeof(uintptr_t) == 4 ? *(int64_t*)value : (int64_t)value; }) # define SET_F64_REG(insn, pos, regs, val) ({ \ uint64_t __val = (val); \ register uintptr_t value asm("a0") = sizeof(uintptr_t) == 4 ? (uintptr_t)&__val : (uintptr_t)__val; \ - uintptr_t offset = ((insn) >> ((pos)-3)) & 0xf8; \ + uintptr_t offset = SHIFT_RIGHT(insn, (pos)-3) & 0xf8; \ uintptr_t tmp; \ asm volatile ("1: auipc %0, %%pcrel_hi(put_f64_reg); add %0, %0, %2; jalr t0, %0, %%pcrel_lo(1b)" : "=&r"(tmp) : "r"(value), "r"(offset) : "t0"); }) # define GET_FCSR() read_csr(fcsr) @@ -48,12 +48,12 @@ # define softfloat_roundingMode ({ register int tp asm("tp"); tp; }) # define SET_FS_DIRTY() ((void) 0) #else -# define GET_F64_REG(insn, pos, regs) (*(int64_t*)((void*)((regs) + 32) + (((insn) >> ((pos)-3)) & 0xf8))) +# define GET_F64_REG(insn, pos, regs) (*(int64_t*)((void*)((regs) + 32) + (SHIFT_RIGHT(insn, (pos)-3) & 0xf8))) # define SET_F64_REG(insn, pos, regs, val) (GET_F64_REG(insn, pos, regs) = (val)) # define GET_F32_REG(insn, pos, regs) (*(int32_t*)&GET_F64_REG(insn, pos, regs)) # define SET_F32_REG(insn, pos, regs, val) (GET_F32_REG(insn, pos, regs) = (val)) # define GET_FCSR() ({ register int tp asm("tp"); tp & 0xFF; }) -# define SET_FCSR(value) ({ asm volatile("add tp, x0, %0" :: "rI"((value) & 0xFF)); }) +# define SET_FCSR(value) ({ asm volatile("add tp, x0, %0" :: "rI"((value) & 0xFF)); SET_FS_DIRTY(); }) # define GET_FRM() (GET_FCSR() >> 5) # define SET_FRM(value) SET_FCSR(GET_FFLAGS() | ((value) << 5)) # define GET_FFLAGS() (GET_FCSR() & 0x1F) @@ -79,4 +79,9 @@ #define SET_F32_RD(insn, regs, val) (SET_F32_REG(insn, 7, regs, val), SET_FS_DIRTY()) #define SET_F64_RD(insn, regs, val) (SET_F64_REG(insn, 7, regs, val), SET_FS_DIRTY()) +#define GET_F32_RS2C(insn, regs) (GET_F32_REG(insn, 2, regs)) +#define GET_F32_RS2S(insn, regs) (GET_F32_REG(RVC_RS2S(insn), 0, regs)) +#define GET_F64_RS2C(insn, regs) (GET_F64_REG(insn, 2, regs)) +#define GET_F64_RS2S(insn, regs) (GET_F64_REG(RVC_RS2S(insn), 0, regs)) + #endif diff --git a/machine/fp_ldst.c b/machine/fp_ldst.c index 93a4844..e11900c 100644 --- a/machine/fp_ldst.c +++ b/machine/fp_ldst.c @@ -1,31 +1,28 @@ #include "fp_emulation.h" #include "unprivileged_memory.h" +#define punt_to_misaligned_handler(align, handler) \ + if (addr % (align) != 0) \ + return write_csr(mbadaddr, addr), (handler)(regs, mcause, mepc) + DECLARE_EMULATION_FUNC(emulate_float_load) { - uint64_t val; uintptr_t addr = GET_RS1(insn, regs) + IMM_I(insn); + + // if FPU is disabled, punt back to the OS + if (unlikely((mstatus & MSTATUS_FS) == 0)) + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); switch (insn & MASK_FUNCT3) { case MATCH_FLW & MASK_FUNCT3: - if (addr % 4 != 0) - return misaligned_load_trap(regs, mcause, mepc); - + punt_to_misaligned_handler(4, misaligned_load_trap); SET_F32_RD(insn, regs, load_int32_t((void *)addr, mepc)); break; case MATCH_FLD & MASK_FUNCT3: - if (addr % sizeof(uintptr_t) != 0) - return misaligned_load_trap(regs, mcause, mepc); - -#if __riscv_xlen == 64 - val = load_uint64_t((void *)addr, mepc); -#else - val = load_uint32_t((void *)addr, mepc); - val += (uint64_t)load_uint32_t((void *)(addr + 4), mepc) << 32; -#endif - SET_F64_RD(insn, regs, val); + punt_to_misaligned_handler(sizeof(uintptr_t), misaligned_load_trap); + SET_F64_RD(insn, regs, load_uint64_t((void *)addr, mepc)); break; default: @@ -35,29 +32,22 @@ DECLARE_EMULATION_FUNC(emulate_float_load) DECLARE_EMULATION_FUNC(emulate_float_store) { - uint64_t val; uintptr_t addr = GET_RS1(insn, regs) + IMM_S(insn); + + // if FPU is disabled, punt back to the OS + if (unlikely((mstatus & MSTATUS_FS) == 0)) + return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); switch (insn & MASK_FUNCT3) { case MATCH_FSW & MASK_FUNCT3: - if (addr % 4 != 0) - return misaligned_store_trap(regs, mcause, mepc); - + punt_to_misaligned_handler(4, misaligned_store_trap); store_uint32_t((void *)addr, GET_F32_RS2(insn, regs), mepc); break; case MATCH_FSD & MASK_FUNCT3: - if (addr % sizeof(uintptr_t) != 0) - return misaligned_store_trap(regs, mcause, mepc); - - val = GET_F64_RS2(insn, regs); -#if __riscv_xlen == 64 - store_uint64_t((void *)addr, val, mepc); -#else - store_uint32_t((void *)addr, val, mepc); - store_uint32_t((void *)(addr + 4), val >> 32, mepc); -#endif + punt_to_misaligned_handler(sizeof(uintptr_t), misaligned_store_trap); + store_uint64_t((void *)addr, GET_F64_RS2(insn, regs), mepc); break; default: diff --git a/machine/misaligned_ldst.c b/machine/misaligned_ldst.c index 980aeba..8c96c18 100644 --- a/machine/misaligned_ldst.c +++ b/machine/misaligned_ldst.c @@ -2,6 +2,7 @@ #include "fp_emulation.h" #include "unprivileged_memory.h" #include "mtrap.h" +#include "config.h" union byte_array { uint8_t bytes[8]; @@ -35,6 +36,30 @@ void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) len = 2, shift = 8*(sizeof(uintptr_t) - len); else if ((insn & MASK_LHU) == MATCH_LHU) len = 2; +#ifdef __riscv_compressed +# if __riscv_xlen >= 64 + else if ((insn & MASK_C_LD) == MATCH_C_LD) + len = 8, shift = 8*(sizeof(uintptr_t) - len), insn = RVC_RS2S(insn) << SH_RD; + else if ((insn & MASK_C_LDSP) == MATCH_C_LDSP && ((insn >> SH_RD) & 0x1f)) + len = 8, shift = 8*(sizeof(uintptr_t) - len); +# endif + else if ((insn & MASK_C_LW) == MATCH_C_LW) + len = 4, shift = 8*(sizeof(uintptr_t) - len), insn = RVC_RS2S(insn) << SH_RD; + else if ((insn & MASK_C_LWSP) == MATCH_C_LWSP && ((insn >> SH_RD) & 0x1f)) + len = 4, shift = 8*(sizeof(uintptr_t) - len); +# ifdef PK_ENABLE_FP_EMULATION + else if ((insn & MASK_C_FLD) == MATCH_C_FLD) + fp = 1, len = 8, insn = RVC_RS2S(insn) << SH_RD; + else if ((insn & MASK_C_FLDSP) == MATCH_C_FLDSP) + fp = 1, len = 8; +# if __riscv_xlen == 32 + else if ((insn & MASK_C_FLW) == MATCH_C_FLW) + fp = 1, len = 4, insn = RVC_RS2S(insn) << SH_RD; + else if ((insn & MASK_C_FLWSP) == MATCH_C_FLWSP) + fp = 1, len = 4; +# endif +# endif +#endif else return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); @@ -74,6 +99,30 @@ void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) #endif else if ((insn & MASK_SH) == MATCH_SH) len = 2; +#ifdef __riscv_compressed +# if __riscv_xlen >= 64 + else if ((insn & MASK_C_SD) == MATCH_C_SD) + len = 8, val.intx = GET_RS2S(insn, regs); + else if ((insn & MASK_C_SDSP) == MATCH_C_SDSP && ((insn >> SH_RD) & 0x1f)) + len = 8, val.intx = GET_RS2C(insn, regs); +# endif + else if ((insn & MASK_C_SW) == MATCH_C_SW) + len = 4, val.intx = GET_RS2S(insn, regs); + else if ((insn & MASK_C_SWSP) == MATCH_C_SWSP && ((insn >> SH_RD) & 0x1f)) + len = 4, val.intx = GET_RS2C(insn, regs); +# ifdef PK_ENABLE_FP_EMULATION + else if ((insn & MASK_C_FSD) == MATCH_C_FSD) + len = 8, val.int64 = GET_F64_RS2S(insn, regs); + else if ((insn & MASK_C_FSDSP) == MATCH_C_FSDSP) + len = 8, val.int64 = GET_F64_RS2C(insn, regs); +# if __riscv_xlen == 32 + else if ((insn & MASK_C_FSW) == MATCH_C_FSW) + len = 4, val.intx = GET_F32_RS2S(insn, regs); + else if ((insn & MASK_C_FSWSP) == MATCH_C_FSWSP) + len = 4, val.intx = GET_F32_RS2C(insn, regs); +# endif +# endif +#endif else return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h index 03f1e27..39a7722 100644 --- a/machine/unprivileged_memory.h +++ b/machine/unprivileged_memory.h @@ -45,13 +45,25 @@ DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint64_t, ld) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint64_t, sd) #else DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lw) + +static inline uint64_t load_uint64_t(const uint64_t* addr, uintptr_t mepc) +{ + return load_uint32_t((uint32_t*)addr, mepc) + + ((uint64_t)load_uint32_t((uint32_t*)addr + 1, mepc) << 32); +} + +static inline void store_uint64_t(uint64_t* addr, uint64_t val, uintptr_t mepc) +{ + store_uint32_t((uint32_t*)addr, val, mepc); + store_uint32_t((uint32_t*)addr + 1, val >> 32, mepc); +} #endif -static uint32_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr_t* mstatus) +static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr_t* mstatus) { register uintptr_t __mepc asm ("a2") = mepc; register uintptr_t __mstatus asm ("a3"); - uint32_t val; + uintptr_t val; #ifndef __riscv_compressed asm ("csrrs %[mstatus], mstatus, %[mprv]\n" "lw %[insn], (%[addr])\n" -- cgit v1.1 From 611290ccde8d76c1973a37d82a5d4b3e4b7b90c4 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 15 Feb 2017 18:59:21 -0800 Subject: Cleanly separate HTIF code; don't poll keyboard on timer interrupt --- machine/htif.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ machine/htif.h | 5 +++ machine/machine.mk.in | 1 + machine/mcall.h | 1 - machine/mtrap.c | 89 ++++----------------------------------------------- machine/mtrap.h | 1 - pk/frontend.c | 4 +-- 7 files changed, 92 insertions(+), 87 deletions(-) create mode 100644 machine/htif.c diff --git a/machine/htif.c b/machine/htif.c new file mode 100644 index 0000000..a513305 --- /dev/null +++ b/machine/htif.c @@ -0,0 +1,78 @@ +#include "htif.h" +#include "atomic.h" +#include "mtrap.h" + +volatile uint64_t tohost __attribute__((aligned(64))) __attribute__((section("htif"))); +volatile uint64_t fromhost __attribute__((aligned(64))) __attribute__((section("htif"))); +volatile int htif_console_buf; +static spinlock_t htif_lock = SPINLOCK_INIT; + +static void request_htif_keyboard_interrupt() +{ + assert(tohost == 0); + tohost = TOHOST_CMD(1, 0, 0); +} + +static void __check_fromhost() +{ + // we should only be interrupted by keypresses + uint64_t fh = fromhost; + if (!fh) + return; + if (!(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0)) + die("unexpected htif interrupt"); + htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh); + fromhost = 0; +} + +int htif_console_getchar() +{ + if (spinlock_trylock(&htif_lock) == 0) { + __check_fromhost(); + spinlock_unlock(&htif_lock); + } + + int ch = atomic_swap(&htif_console_buf, -1); + if (ch >= 0) + request_htif_keyboard_interrupt(); + return ch - 1; +} + +static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) +{ + spinlock_lock(&htif_lock); + while (tohost) + __check_fromhost(); + tohost = TOHOST_CMD(dev, cmd, data); + + while (1) { + uint64_t fh = fromhost; + if (fh) { + if (FROMHOST_DEV(fh) == dev && FROMHOST_CMD(fh) == cmd) { + fromhost = 0; + break; + } + __check_fromhost(); + } + } + spinlock_unlock(&htif_lock); +} + +uintptr_t htif_syscall(uintptr_t arg) +{ + do_tohost_fromhost(0, 0, arg); + return 0; +} + +void htif_console_putchar(uint8_t ch) +{ + do_tohost_fromhost(1, 1, ch); +} + +void htif_poweroff() +{ + while (1) { + fromhost = 0; + tohost = 1; + } +} diff --git a/machine/htif.h b/machine/htif.h index 7107ddb..f47e965 100644 --- a/machine/htif.h +++ b/machine/htif.h @@ -15,4 +15,9 @@ #define FROMHOST_CMD(fromhost_value) ((uint64_t)(fromhost_value) << 8 >> 56) #define FROMHOST_DATA(fromhost_value) ((uint64_t)(fromhost_value) << 16 >> 16) +void htif_console_putchar(uint8_t); +int htif_console_getchar(); +void htif_poweroff() __attribute__((noreturn)); +uintptr_t htif_syscall(uintptr_t); + #endif diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 6568dc5..e224982 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -18,6 +18,7 @@ machine_hdrs = \ machine_c_srcs = \ mtrap.c \ minit.c \ + htif.c \ emulation.c \ muldiv_emulation.c \ fp_emulation.c \ diff --git a/machine/mcall.h b/machine/mcall.h index 2096d16..ed5a28c 100644 --- a/machine/mcall.h +++ b/machine/mcall.h @@ -4,7 +4,6 @@ #define MCALL_HART_ID 0 #define MCALL_CONSOLE_PUTCHAR 1 #define MCALL_CONSOLE_GETCHAR 2 -#define MCALL_HTIF_SYSCALL 3 #define MCALL_SEND_IPI 4 #define MCALL_CLEAR_IPI 5 #define MCALL_SHUTDOWN 6 diff --git a/machine/mtrap.c b/machine/mtrap.c index 34772b7..0ed27e9 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -8,10 +8,6 @@ #include #include -volatile uint64_t tohost __attribute__((aligned(64))) __attribute__((section("htif"))); -volatile uint64_t fromhost __attribute__((aligned(64))) __attribute__((section("htif"))); -static spinlock_t htif_lock = SPINLOCK_INIT; - void __attribute__((noreturn)) bad_trap() { die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc)); @@ -22,81 +18,24 @@ static uintptr_t mcall_hart_id() return read_const_csr(mhartid); } -static void request_htif_keyboard_interrupt() -{ - assert(tohost == 0); - tohost = TOHOST_CMD(1, 0, 0); -} - -static void __htif_interrupt() -{ - // we should only be interrupted by keypresses - uint64_t fh = fromhost; - if (!fh) - return; - if (!(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0)) - die("unexpected htif interrupt"); - HLS()->console_ibuf = 1 + (uint8_t)FROMHOST_DATA(fh); - fromhost = 0; - set_csr(mip, MIP_SSIP); -} - -static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) -{ - spinlock_lock(&htif_lock); - while (tohost) - __htif_interrupt(); - tohost = TOHOST_CMD(dev, cmd, data); - - while (1) { - uint64_t fh = fromhost; - if (fh) { - if (FROMHOST_DEV(fh) == dev && FROMHOST_CMD(fh) == cmd) { - fromhost = 0; - break; - } - __htif_interrupt(); - } - } - spinlock_unlock(&htif_lock); -} - -static void htif_interrupt() -{ - if (spinlock_trylock(&htif_lock) == 0) { - __htif_interrupt(); - spinlock_unlock(&htif_lock); - } -} - uintptr_t timer_interrupt() { // just send the timer interrupt to the supervisor clear_csr(mie, MIP_MTIP); set_csr(mip, MIP_STIP); - // and poll the HTIF console - htif_interrupt(); - return 0; } static uintptr_t mcall_console_putchar(uint8_t ch) { - do_tohost_fromhost(1, 1, ch); - return 0; -} - -static uintptr_t mcall_htif_syscall(uintptr_t magic_mem) -{ - do_tohost_fromhost(0, 0, magic_mem); + htif_console_putchar(ch); return 0; } void poweroff() { - while (1) - tohost = 1; + htif_poweroff(); } void putstring(const char* s) @@ -134,29 +73,16 @@ static uintptr_t mcall_send_ipi(uintptr_t recipient) return 0; } -static void reset_ssip() -{ - clear_csr(mip, MIP_SSIP); - mb(); - - if (HLS()->sipi_pending || HLS()->console_ibuf > 0) - set_csr(mip, MIP_SSIP); -} - static uintptr_t mcall_console_getchar() { - int ch = atomic_swap(&HLS()->console_ibuf, -1); - if (ch >= 0) - request_htif_keyboard_interrupt(); - reset_ssip(); - return ch - 1; + return htif_console_getchar(); } static uintptr_t mcall_clear_ipi() { - int ipi = atomic_swap(&HLS()->sipi_pending, 0); - reset_ssip(); - return ipi; + clear_csr(mip, MIP_SSIP); + mb(); + return atomic_swap(&HLS()->sipi_pending, 0); } static uintptr_t mcall_shutdown() @@ -239,9 +165,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) case MCALL_CONSOLE_GETCHAR: retval = mcall_console_getchar(); break; - case MCALL_HTIF_SYSCALL: - retval = mcall_htif_syscall(arg0); - break; case MCALL_SEND_IPI: retval = mcall_send_ipi(arg0); break; diff --git a/machine/mtrap.h b/machine/mtrap.h index 9995203..68c93f2 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -41,7 +41,6 @@ typedef struct { uint32_t* ipi; volatile int mipi_pending; volatile int sipi_pending; - int console_ibuf; volatile uint32_t* plic_m_thresh; volatile uintptr_t* plic_m_ie; diff --git a/pk/frontend.c b/pk/frontend.c index 13fdfcf..716f050 100644 --- a/pk/frontend.c +++ b/pk/frontend.c @@ -4,8 +4,8 @@ #include "atomic.h" #include "frontend.h" #include "sbi.h" -#include "mcall.h" #include "syscall.h" +#include "htif.h" #include long frontend_syscall(long n, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) @@ -24,7 +24,7 @@ long frontend_syscall(long n, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3 magic_mem[6] = a5; magic_mem[7] = a6; - do_mcall(MCALL_HTIF_SYSCALL, magic_mem); + htif_syscall((uintptr_t)magic_mem); long ret = magic_mem[0]; -- cgit v1.1 From 926b360655fd7a22413c7732faceeea21a224aa1 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 17 Feb 2017 01:54:41 -0800 Subject: WIP towards ECALL interface for SBI --- bbl/bbl.c | 56 ++----------------- dummy_payload/dummy_entry.S | 22 ++++++++ dummy_payload/dummy_payload.c | 21 -------- dummy_payload/dummy_payload.lds | 4 ++ dummy_payload/dummy_payload.mk.in | 2 +- dummy_payload/dummy_sbi.S | 1 - machine/machine.mk.in | 4 -- machine/mcall.h | 7 --- machine/minit.c | 9 ++-- machine/mtrap.c | 8 --- machine/mtrap.h | 3 +- machine/sbi.S | 15 ------ machine/sbi.h | 30 ----------- machine/sbi_entry.S | 111 -------------------------------------- machine/sbi_impl.c | 33 ------------ pk/frontend.c | 1 - pk/pk.c | 2 +- 17 files changed, 40 insertions(+), 289 deletions(-) create mode 100644 dummy_payload/dummy_entry.S delete mode 120000 dummy_payload/dummy_sbi.S delete mode 100644 machine/sbi.S delete mode 100644 machine/sbi.h delete mode 100644 machine/sbi_entry.S delete mode 100644 machine/sbi_impl.c diff --git a/bbl/bbl.c b/bbl/bbl.c index eacb6c3..96605fd 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -9,68 +9,22 @@ static kernel_elf_info info; static volatile int elf_loaded; -static void supervisor_vm_init() +void boot_other_hart() { - uintptr_t highest_va = DRAM_BASE - first_free_paddr; - mem_size = MIN(mem_size, highest_va - info.first_user_vaddr) & -MEGAPAGE_SIZE; - - pte_t* sbi_pt = (pte_t*)(info.first_vaddr_after_user + info.load_offset); - memset(sbi_pt, 0, RISCV_PGSIZE); - pte_t* middle_pt = (void*)sbi_pt + RISCV_PGSIZE; -#if __riscv_xlen == 32 - size_t num_middle_pts = 1; - pte_t* root_pt = middle_pt; - memset(root_pt, 0, RISCV_PGSIZE); -#else - size_t num_middle_pts = (-info.first_user_vaddr - 1) / GIGAPAGE_SIZE + 1; - pte_t* root_pt = (void*)middle_pt + num_middle_pts * RISCV_PGSIZE; - memset(middle_pt, 0, (num_middle_pts + 1) * RISCV_PGSIZE); - for (size_t i = 0; i < num_middle_pts; i++) - root_pt[(1<> RISCV_PGSHIFT) + i); -#endif - - for (uintptr_t vaddr = info.first_user_vaddr, paddr = vaddr + info.load_offset, end = info.first_vaddr_after_user; - paddr < DRAM_BASE + mem_size; vaddr += MEGAPAGE_SIZE, paddr += MEGAPAGE_SIZE) { - int l2_shift = RISCV_PGLEVEL_BITS + RISCV_PGSHIFT; - size_t l2_idx = (info.first_user_vaddr >> l2_shift) & ((1 << RISCV_PGLEVEL_BITS)-1); - l2_idx += ((vaddr - info.first_user_vaddr) >> l2_shift); - middle_pt[l2_idx] = pte_create(paddr >> RISCV_PGSHIFT, PTE_G | PTE_R | PTE_W | PTE_X); - } - - // map SBI at top of vaddr space - extern char _sbi_end; - uintptr_t num_sbi_pages = ((uintptr_t)&_sbi_end - DRAM_BASE - 1) / RISCV_PGSIZE + 1; - assert(num_sbi_pages <= (1 << RISCV_PGLEVEL_BITS)); - for (uintptr_t i = 0; i < num_sbi_pages; i++) { - uintptr_t idx = (1 << RISCV_PGLEVEL_BITS) - num_sbi_pages + i; - sbi_pt[idx] = pte_create((DRAM_BASE / RISCV_PGSIZE) + i, PTE_G | PTE_R | PTE_X); - } - pte_t* sbi_pte = middle_pt + ((num_middle_pts << RISCV_PGLEVEL_BITS)-1); - assert(!*sbi_pte); - *sbi_pte = ptd_create((uintptr_t)sbi_pt >> RISCV_PGSHIFT); - + while (!elf_loaded) + ; mb(); - root_page_table = root_pt; - write_csr(sptbr, ((uintptr_t)root_pt >> RISCV_PGSHIFT) | SPTBR_MODE); + enter_supervisor_mode((void *)info.entry + info.load_offset, read_csr(mhartid), 0); } void boot_loader() { extern char _payload_start, _payload_end; load_kernel_elf(&_payload_start, &_payload_end - &_payload_start, &info); - supervisor_vm_init(); #ifdef PK_ENABLE_LOGO print_logo(); #endif mb(); elf_loaded = 1; - enter_supervisor_mode((void *)info.entry, 0); -} - -void boot_other_hart() -{ - while (!elf_loaded) - ; - mb(); - enter_supervisor_mode((void *)info.entry, 0); + boot_other_hart(); } diff --git a/dummy_payload/dummy_entry.S b/dummy_payload/dummy_entry.S new file mode 100644 index 0000000..46c0b7f --- /dev/null +++ b/dummy_payload/dummy_entry.S @@ -0,0 +1,22 @@ +#include "mcall.h" + + .section ".text.init" + .globl _start +_start: + la s0, str +1: + lbu a0, (s0) + beqz a0, 1f + li a7, MCALL_CONSOLE_PUTCHAR + ecall + add s0, s0, 1 + j 1b + +1: + li a7, MCALL_SHUTDOWN + ecall + + .data +str: + .asciz "This is bbl's dummy_payload. To boot a real kernel, reconfigure\n\ +bbl with the flag --with-payload=PATH, then rebuild bbl.\n" diff --git a/dummy_payload/dummy_payload.c b/dummy_payload/dummy_payload.c index 61ed59a..e69de29 100644 --- a/dummy_payload/dummy_payload.c +++ b/dummy_payload/dummy_payload.c @@ -1,21 +0,0 @@ -#include -#include "sbi.h" - -asm (".globl _start\n\ - _start: la sp, stack\n\ - j entry\n\ - .pushsection .rodata\n\ - .align 4\n\ - .skip 4096\n\ - stack:\n\ - .popsection"); - -void entry() -{ - const char* message = -"This is bbl's dummy_payload. To boot a real kernel, reconfigure\n\ -bbl with the flag --with-payload=PATH, then rebuild bbl.\n"; - while (*message) - sbi_console_putchar(*message++); - sbi_shutdown(); -} diff --git a/dummy_payload/dummy_payload.lds b/dummy_payload/dummy_payload.lds index ee9410b..0506a8d 100644 --- a/dummy_payload/dummy_payload.lds +++ b/dummy_payload/dummy_payload.lds @@ -1,3 +1,7 @@ +ENTRY(_start) + SECTIONS { . = -0x80000000; + + .text.init : { *(.text.init) } } diff --git a/dummy_payload/dummy_payload.mk.in b/dummy_payload/dummy_payload.mk.in index b1d4ac7..4a133be 100644 --- a/dummy_payload/dummy_payload.mk.in +++ b/dummy_payload/dummy_payload.mk.in @@ -5,7 +5,7 @@ dummy_payload_hdrs = \ dummy_payload_c_srcs = \ dummy_payload_asm_srcs = \ - dummy_sbi.S \ + dummy_entry.S \ dummy_payload_test_srcs = diff --git a/dummy_payload/dummy_sbi.S b/dummy_payload/dummy_sbi.S deleted file mode 120000 index 2978a97..0000000 --- a/dummy_payload/dummy_sbi.S +++ /dev/null @@ -1 +0,0 @@ -../machine/sbi.S \ No newline at end of file diff --git a/machine/machine.mk.in b/machine/machine.mk.in index e224982..d083fdf 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -11,7 +11,6 @@ machine_hdrs = \ htif.h \ mcall.h \ mtrap.h \ - sbi.h \ unprivileged_memory.h \ vm.h \ @@ -24,11 +23,8 @@ machine_c_srcs = \ fp_emulation.c \ fp_ldst.c \ misaligned_ldst.c \ - sbi_impl.c \ configstring.c \ machine_asm_srcs = \ mentry.S \ fp_asm.S \ - sbi_entry.S \ - sbi.S \ diff --git a/machine/mcall.h b/machine/mcall.h index ed5a28c..a704480 100644 --- a/machine/mcall.h +++ b/machine/mcall.h @@ -1,7 +1,6 @@ #ifndef _RISCV_MCALL_H #define _RISCV_MCALL_H -#define MCALL_HART_ID 0 #define MCALL_CONSOLE_PUTCHAR 1 #define MCALL_CONSOLE_GETCHAR 2 #define MCALL_SEND_IPI 4 @@ -11,10 +10,4 @@ #define MCALL_REMOTE_SFENCE_VM 8 #define MCALL_REMOTE_FENCE_I 9 -#ifndef __ASSEMBLER__ - -extern uintptr_t do_mcall(uintptr_t which, ...); - -#endif - #endif diff --git a/machine/minit.c b/machine/minit.c index 06e8d25..0c95ea4 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -141,7 +141,7 @@ void init_other_hart() boot_other_hart(); } -void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack) +void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1) { uintptr_t mstatus = read_csr(mstatus); mstatus = INSERT_FIELD(mstatus, MSTATUS_MPP, PRV_S); @@ -149,7 +149,10 @@ void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack) write_csr(mstatus, mstatus); write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE); write_csr(mepc, fn); - write_csr(sptbr, ((uintptr_t)root_page_table >> RISCV_PGSHIFT) | SPTBR_MODE); - asm volatile ("mv a0, %0; mv sp, %0; mret" : : "r" (stack)); + write_csr(sptbr, 0); + + register uintptr_t a0 asm ("a0") = arg0; + register uintptr_t a1 asm ("a1") = arg1; + asm volatile ("mret" : : "r" (a0), "r" (a1)); __builtin_unreachable(); } diff --git a/machine/mtrap.c b/machine/mtrap.c index 0ed27e9..3cbc064 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -13,11 +13,6 @@ void __attribute__((noreturn)) bad_trap() die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc)); } -static uintptr_t mcall_hart_id() -{ - return read_const_csr(mhartid); -} - uintptr_t timer_interrupt() { // just send the timer interrupt to the supervisor @@ -156,9 +151,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval; switch (n) { - case MCALL_HART_ID: - retval = mcall_hart_id(); - break; case MCALL_CONSOLE_PUTCHAR: retval = mcall_console_putchar(arg0); break; diff --git a/machine/mtrap.h b/machine/mtrap.h index 68c93f2..1f692b3 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -11,7 +11,6 @@ #ifndef __ASSEMBLER__ -#include "sbi.h" #include #include @@ -68,7 +67,7 @@ void putstring(const char* s); #define assert(x) ({ if (!(x)) die("assertion failed: %s", #x); }) #define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(); }) -void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack) +void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1) __attribute__((noreturn)); void boot_loader(); void boot_other_hart(); diff --git a/machine/sbi.S b/machine/sbi.S deleted file mode 100644 index cbea78a..0000000 --- a/machine/sbi.S +++ /dev/null @@ -1,15 +0,0 @@ -.globl sbi_hart_id; sbi_hart_id = -2048 -.globl sbi_num_harts; sbi_num_harts = -2032 -.globl sbi_query_memory; sbi_query_memory = -2016 -.globl sbi_console_putchar; sbi_console_putchar = -2000 -.globl sbi_console_getchar; sbi_console_getchar = -1984 -.globl sbi_send_ipi; sbi_send_ipi = -1952 -.globl sbi_clear_ipi; sbi_clear_ipi = -1936 -.globl sbi_timebase; sbi_timebase = -1920 -.globl sbi_shutdown; sbi_shutdown = -1904 -.globl sbi_set_timer; sbi_set_timer = -1888 -.globl sbi_mask_interrupt; sbi_mask_interrupt = -1872 -.globl sbi_unmask_interrupt; sbi_unmask_interrupt = -1856 -.globl sbi_remote_sfence_vm; sbi_remote_sfence_vm = -1840 -.globl sbi_remote_sfence_vm_range; sbi_remote_sfence_vm_range = -1824 -.globl sbi_remote_fence_i; sbi_remote_fence_i = -1808 diff --git a/machine/sbi.h b/machine/sbi.h deleted file mode 100644 index 4e2fbd8..0000000 --- a/machine/sbi.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _ASM_RISCV_SBI_H -#define _ASM_RISCV_SBI_H - -typedef struct { - unsigned long base; - unsigned long size; - unsigned long node_id; -} memory_block_info; - -unsigned long sbi_query_memory(unsigned long id, memory_block_info *p); - -unsigned long sbi_hart_id(void); -unsigned long sbi_num_harts(void); -unsigned long sbi_timebase(void); -void sbi_set_timer(unsigned long long stime_value); -void sbi_send_ipi(unsigned long hart_id); -unsigned long sbi_clear_ipi(void); -void sbi_shutdown(void); - -void sbi_console_putchar(unsigned char ch); -int sbi_console_getchar(void); - -void sbi_remote_sfence_vm(unsigned long hart_mask_ptr, unsigned long asid); -void sbi_remote_sfence_vm_range(unsigned long hart_mask_ptr, unsigned long asid, unsigned long start, unsigned long size); -void sbi_remote_fence_i(unsigned long hart_mask_ptr); - -unsigned long sbi_mask_interrupt(unsigned long which); -unsigned long sbi_unmask_interrupt(unsigned long which); - -#endif diff --git a/machine/sbi_entry.S b/machine/sbi_entry.S deleted file mode 100644 index a37dd25..0000000 --- a/machine/sbi_entry.S +++ /dev/null @@ -1,111 +0,0 @@ -#include "encoding.h" -#include "mcall.h" - - .section .sbi,"ax",@progbits - .option norvc - .align RISCV_PGSHIFT - .globl sbi_base -sbi_base: - - # TODO: figure out something better to do with this space. It's not - # protected from the OS, so beware. - .skip RISCV_PGSIZE - 2048 - - # hart_id - .align 4 - li a7, MCALL_HART_ID - ecall - ret - - # num_harts - .align 4 - lw a0, num_harts - ret - - # query_memory - .align 4 - tail __sbi_query_memory - - # console_putchar - .align 4 - li a7, MCALL_CONSOLE_PUTCHAR - ecall - ret - - # console_getchar - .align 4 - li a7, MCALL_CONSOLE_GETCHAR - ecall - ret - - # empty - .align 4 - unimp - - # send ipi - .align 4 - li a7, MCALL_SEND_IPI - ecall - ret - - # clear ipi - .align 4 - li a7, MCALL_CLEAR_IPI - ecall - ret - - # timebase - .align 4 - li a0, 10000000 # or, you know, we could provide the correct answer - ret - - # shutdown - .align 4 - li a7, MCALL_SHUTDOWN - ecall - - # set_timer - .align 4 - li a7, MCALL_SET_TIMER - ecall - ret - - # mask_interrupt - .align 4 - tail __sbi_mask_interrupt - - # unmask_interrupt - .align 4 - tail __sbi_unmask_interrupt - - # remote_sfence_vm - .align 4 - li a7, MCALL_REMOTE_SFENCE_VM - ecall - ret - - # remote_sfence_vm_range - .align 4 - li a7, MCALL_REMOTE_SFENCE_VM - ecall - ret - - # remote_fence_i - .align 4 - li a7, MCALL_REMOTE_FENCE_I - ecall - ret - - # end of SBI trampolines - - .globl do_mcall -do_mcall: - mv a7, a0 - mv a0, a1 - mv a1, a2 - ecall - ret - - .align RISCV_PGSHIFT - .globl _sbi_end -_sbi_end: diff --git a/machine/sbi_impl.c b/machine/sbi_impl.c deleted file mode 100644 index f5ed8c9..0000000 --- a/machine/sbi_impl.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "mtrap.h" -#include "sbi.h" - -uintptr_t __sbi_query_memory(uintptr_t id, memory_block_info *p) -{ - if (id == 0) { - p->base = first_free_paddr; - p->size = mem_size + DRAM_BASE - p->base; - return 0; - } - - return -1; -} - -#define LOW_IRQ_OK(n) ((n) == IRQ_S_SOFT || (n) == IRQ_S_TIMER) - -uintptr_t __sbi_mask_interrupt(uintptr_t which) -{ - if (!LOW_IRQ_OK(which)) - return -1; - - clear_csr(sie, 1UL << which); - return 0; -} - -uintptr_t __sbi_unmask_interrupt(uintptr_t which) -{ - if (!LOW_IRQ_OK(which)) - return -1; - - set_csr(sie, 1UL << which); - return 0; -} diff --git a/pk/frontend.c b/pk/frontend.c index 716f050..e58df26 100644 --- a/pk/frontend.c +++ b/pk/frontend.c @@ -3,7 +3,6 @@ #include "pk.h" #include "atomic.h" #include "frontend.h" -#include "sbi.h" #include "syscall.h" #include "htif.h" #include diff --git a/pk/pk.c b/pk/pk.c index 25cd5a5..8132f8d 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -162,7 +162,7 @@ void boot_loader() write_csr(sie, 0); file_init(); - enter_supervisor_mode(rest_of_boot_loader, pk_vm_init()); + enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), 0); } void boot_other_hart() -- cgit v1.1 From b14d4187fe1a328b9e87f61a984fd70e17211954 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 17 Feb 2017 01:54:52 -0800 Subject: Clean up boot loader for physical address loading --- bbl/bbl.c | 11 +++++------ bbl/bbl.h | 9 +-------- bbl/kernel_elf.c | 8 ++------ 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 96605fd..bdd56ad 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -6,25 +6,24 @@ #include "config.h" #include -static kernel_elf_info info; -static volatile int elf_loaded; +static volatile uintptr_t entry_point; void boot_other_hart() { - while (!elf_loaded) + while (!entry_point) ; mb(); - enter_supervisor_mode((void *)info.entry + info.load_offset, read_csr(mhartid), 0); + enter_supervisor_mode((void *)entry_point, read_csr(mhartid), 0); } void boot_loader() { extern char _payload_start, _payload_end; - load_kernel_elf(&_payload_start, &_payload_end - &_payload_start, &info); + uintptr_t entry = load_kernel_elf(&_payload_start, &_payload_end - &_payload_start); #ifdef PK_ENABLE_LOGO print_logo(); #endif mb(); - elf_loaded = 1; + entry_point = entry; boot_other_hart(); } diff --git a/bbl/bbl.h b/bbl/bbl.h index e9e1dab..67997b9 100644 --- a/bbl/bbl.h +++ b/bbl/bbl.h @@ -8,14 +8,7 @@ #include #include -typedef struct { - uintptr_t entry; - uintptr_t first_user_vaddr; - uintptr_t first_vaddr_after_user; - uintptr_t load_offset; -} kernel_elf_info; - -void load_kernel_elf(void* blob, size_t size, kernel_elf_info* info); +uintptr_t load_kernel_elf(void* blob, size_t size); void print_logo(); #endif // !__ASSEMBLER__ diff --git a/bbl/kernel_elf.c b/bbl/kernel_elf.c index e22c35c..096a690 100644 --- a/bbl/kernel_elf.c +++ b/bbl/kernel_elf.c @@ -7,7 +7,7 @@ #include #include -void load_kernel_elf(void* blob, size_t size, kernel_elf_info* info) +uintptr_t load_kernel_elf(void* blob, size_t size) { Elf_Ehdr* eh = blob; if (sizeof(*eh) > size || @@ -43,11 +43,7 @@ void load_kernel_elf(void* blob, size_t size, kernel_elf_info* info) } } - info->entry = eh->e_entry; - info->load_offset = bias; - info->first_user_vaddr = min_vaddr; - info->first_vaddr_after_user = ROUNDUP(max_vaddr - bias, RISCV_PGSIZE); - return; + return eh->e_entry + bias; fail: die("failed to load payload"); -- cgit v1.1 From 7c4765029820580c0c01b3321fe4310c8416dcb6 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 19 Feb 2017 15:55:02 -0800 Subject: Handle IPIs and timer interrupts more quickly --- machine/mentry.S | 50 +++++++++++++++++++++-------- machine/mtrap.c | 75 +++++++++++++------------------------------ machine/mtrap.h | 18 ++++++----- machine/unprivileged_memory.h | 2 ++ 4 files changed, 71 insertions(+), 74 deletions(-) diff --git a/machine/mentry.S b/machine/mentry.S index 95653c1..6e77d5e 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -18,11 +18,7 @@ trap_table: .word mcall_trap .word bad_trap .word bad_trap -#define SOFTWARE_INTERRUPT_VECTOR 12 - .word software_interrupt -#define TIMER_INTERRUPT_VECTOR 13 - .word timer_interrupt -#define TRAP_FROM_MACHINE_MODE_VECTOR 14 +#define TRAP_FROM_MACHINE_MODE_VECTOR 12 .word __trap_from_machine_mode .option norvc @@ -31,10 +27,6 @@ trap_table: reset_vector: j do_reset -nmi_vector: -.Lunhandleable_trap: - j bad_trap - trap_vector: csrrw sp, mscratch, sp beqz sp, .Ltrap_from_machine_mode @@ -51,8 +43,12 @@ trap_vector: # Is it a machine timer interrupt? li a0, IRQ_M_TIMER * 2 bne a0, a1, 1f - li a1, TIMER_INTERRUPT_VECTOR - j .Lhandle_trap_in_machine_mode + + # Yes. Simply clear MSIE and raise SSIP. + li a0, MIP_MTIP + csrc mie, a0 + li a0, MIP_STIP + csrs mip, a0 .Lmret: # Go back whence we came. @@ -64,9 +60,35 @@ trap_vector: 1: # Is it an IPI? li a0, IRQ_M_SOFT * 2 - bne a0, a1, .Lunhandleable_trap - li a1, SOFTWARE_INTERRUPT_VECTOR - j .Lhandle_trap_in_machine_mode + bne a0, a1, bad_trap + + # Yes. First, clear the MIPI bit. + LOAD a0, MENTRY_IPI_OFFSET(sp) + STORE x0, (a0) + fence + + # Now, decode the cause(s). +#ifdef __riscv_atomic + addi a0, sp, MENTRY_IPI_PENDING_OFFSET + amoswap.w a0, x0, (a0) +#else + lw a0, MENTRY_IPI_PENDING_OFFSET(a0) + sw x0, MENTRY_IPI_PENDING_OFFSET(a0) +#endif + and a1, a0, IPI_SOFT + beqz a1, 1f + csrs mip, MIP_SSIP +1: + andi a1, a0, IPI_FENCE_I + beqz a1, 1f + fence.i +1: + andi a1, a0, IPI_SFENCE_VM + beqz a1, 1f + sfence.vma +1: + j .Lmret + .Lhandle_trap_in_machine_mode: # Preserve the registers. Compute the address of the trap handler. diff --git a/machine/mtrap.c b/machine/mtrap.c index 3cbc064..fb6c3f9 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -4,6 +4,7 @@ #include "atomic.h" #include "bits.h" #include "vm.h" +#include "unprivileged_memory.h" #include #include #include @@ -13,15 +14,6 @@ void __attribute__((noreturn)) bad_trap() die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc)); } -uintptr_t timer_interrupt() -{ - // just send the timer interrupt to the supervisor - clear_csr(mie, MIP_MTIP); - set_csr(mip, MIP_STIP); - - return 0; -} - static uintptr_t mcall_console_putchar(uint8_t ch) { htif_console_putchar(ch); @@ -59,15 +51,6 @@ static void send_ipi(uintptr_t recipient, int event) } } -static uintptr_t mcall_send_ipi(uintptr_t recipient) -{ - if (recipient >= num_harts) - return -1; - - send_ipi(recipient, IPI_SOFT); - return 0; -} - static uintptr_t mcall_console_getchar() { return htif_console_getchar(); @@ -75,9 +58,7 @@ static uintptr_t mcall_console_getchar() static uintptr_t mcall_clear_ipi() { - clear_csr(mip, MIP_SSIP); - mb(); - return atomic_swap(&HLS()->sipi_pending, 0); + return clear_csr(mip, MIP_SSIP) & MIP_SSIP; } static uintptr_t mcall_shutdown() @@ -93,31 +74,12 @@ static uintptr_t mcall_set_timer(uint64_t when) return 0; } -void software_interrupt() -{ - *HLS()->ipi = 0; - mb(); - int ipi_pending = atomic_swap(&HLS()->mipi_pending, 0); - mb(); - - if (ipi_pending & IPI_SOFT) { - HLS()->sipi_pending = 1; - set_csr(mip, MIP_SSIP); - } - - if (ipi_pending & IPI_FENCE_I) - asm volatile ("fence.i"); - - if (ipi_pending & IPI_SFENCE_VM) - flush_tlb(); -} - static void send_ipi_many(uintptr_t* pmask, int event) { _Static_assert(MAX_HARTS <= 8 * sizeof(*pmask), "# harts > uintptr_t bits"); uintptr_t mask = -1; if (pmask) - mask = *pmask; + mask = load_uintptr_t(pmask, read_csr(mepc)); // send IPIs to everyone for (ssize_t i = num_harts-1; i >= 0; i--) @@ -125,14 +87,21 @@ static void send_ipi_many(uintptr_t* pmask, int event) send_ipi(i, event); // wait until all events have been handled. - // prevent deadlock while spinning by handling any IPIs from other harts. + // prevent deadlock by consuming incoming IPIs. + uint32_t incoming_ipi = 0; for (ssize_t i = num_harts-1; i >= 0; i--) if ((mask >> i) & 1) - while (OTHER_HLS(i)->mipi_pending & event) - software_interrupt(); + while (OTHER_HLS(i)->ipi) + incoming_ipi |= atomic_swap(HLS()->ipi, 0); + + // if we got an IPI, restore it; it will be taken after returning + if (incoming_ipi) { + *HLS()->ipi = incoming_ipi; + mb(); + } } -static uintptr_t mcall_remote_sfence_vm(uintptr_t* hart_mask, uintptr_t asid) +static uintptr_t mcall_remote_sfence_vm(uintptr_t* hart_mask) { // ignore the ASID and do a global flush. // this allows us to avoid queueing a message. @@ -149,6 +118,8 @@ static uintptr_t mcall_remote_fence_i(uintptr_t* hart_mask) void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) { uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval; + uintptr_t ipi_type = 0; + switch (n) { case MCALL_CONSOLE_PUTCHAR: @@ -158,7 +129,13 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) retval = mcall_console_getchar(); break; case MCALL_SEND_IPI: - retval = mcall_send_ipi(arg0); + ipi_type = IPI_SOFT; + case MCALL_REMOTE_SFENCE_VM: + ipi_type = IPI_SFENCE_VM; + case MCALL_REMOTE_FENCE_I: + ipi_type = IPI_FENCE_I; + send_ipi_many((uintptr_t*)arg0, ipi_type); + retval = 0; break; case MCALL_CLEAR_IPI: retval = mcall_clear_ipi(); @@ -173,12 +150,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) retval = mcall_set_timer(arg0); #endif break; - case MCALL_REMOTE_SFENCE_VM: - retval = mcall_remote_sfence_vm((uintptr_t*)arg0, arg1); - break; - case MCALL_REMOTE_FENCE_I: - retval = mcall_remote_fence_i((uintptr_t*)arg0); - break; default: retval = -ENOSYS; break; diff --git a/machine/mtrap.h b/machine/mtrap.h index 1f692b3..6f38cf6 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -36,10 +36,10 @@ extern volatile uint32_t* plic_priorities; extern size_t plic_ndevs; typedef struct { - uint64_t* timecmp; uint32_t* ipi; volatile int mipi_pending; - volatile int sipi_pending; + + uint64_t* timecmp; volatile uint32_t* plic_m_thresh; volatile uintptr_t* plic_m_ie; @@ -47,10 +47,6 @@ typedef struct { volatile uintptr_t* plic_s_ie; } hls_t; -#define IPI_SOFT 0x1 -#define IPI_FENCE_I 0x2 -#define IPI_SFENCE_VM 0x4 - #define MACHINE_STACK_TOP() ({ \ register uintptr_t sp asm ("sp"); \ (void*)((sp + RISCV_PGSIZE) & -RISCV_PGSIZE); }) @@ -79,9 +75,15 @@ static inline void wfi() #endif // !__ASSEMBLER__ +#define IPI_SOFT 0x1 +#define IPI_FENCE_I 0x2 +#define IPI_SFENCE_VM 0x4 + #define MACHINE_STACK_SIZE RISCV_PGSIZE -#define MENTRY_FRAME_SIZE (INTEGER_CONTEXT_SIZE + SOFT_FLOAT_CONTEXT_SIZE \ - + HLS_SIZE) +#define MENTRY_HLS_OFFSET (INTEGER_CONTEXT_SIZE + SOFT_FLOAT_CONTEXT_SIZE) +#define MENTRY_FRAME_SIZE (MENTRY_HLS_OFFSET + HLS_SIZE) +#define MENTRY_IPI_OFFSET (MENTRY_HLS_OFFSET) +#define MENTRY_IPI_PENDING_OFFSET (MENTRY_HLS_OFFSET + REGBYTES) #ifdef __riscv_flen # define SOFT_FLOAT_CONTEXT_SIZE 0 diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h index 39a7722..6b84861 100644 --- a/machine/unprivileged_memory.h +++ b/machine/unprivileged_memory.h @@ -43,8 +43,10 @@ DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint32_t, sw) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lwu) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint64_t, ld) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint64_t, sd) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, ld) #else DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lw) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, lw) static inline uint64_t load_uint64_t(const uint64_t* addr, uintptr_t mepc) { -- cgit v1.1 From 66fda264c796e7bcfe63282ae46c398d4a25c4d9 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 20 Feb 2017 18:49:19 -0800 Subject: minor HTIF cleanup + use WFI --- machine/htif.c | 11 +++++------ machine/htif.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/machine/htif.c b/machine/htif.c index a513305..8b8d69b 100644 --- a/machine/htif.c +++ b/machine/htif.c @@ -2,8 +2,8 @@ #include "atomic.h" #include "mtrap.h" -volatile uint64_t tohost __attribute__((aligned(64))) __attribute__((section("htif"))); -volatile uint64_t fromhost __attribute__((aligned(64))) __attribute__((section("htif"))); +volatile uint64_t tohost __attribute__((section("htif"))); +volatile uint64_t fromhost __attribute__((section("htif"))); volatile int htif_console_buf; static spinlock_t htif_lock = SPINLOCK_INIT; @@ -19,8 +19,7 @@ static void __check_fromhost() uint64_t fh = fromhost; if (!fh) return; - if (!(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0)) - die("unexpected htif interrupt"); + assert(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0); htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh); fromhost = 0; } @@ -54,14 +53,14 @@ static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) } __check_fromhost(); } + wfi(); } spinlock_unlock(&htif_lock); } -uintptr_t htif_syscall(uintptr_t arg) +void htif_syscall(uintptr_t arg) { do_tohost_fromhost(0, 0, arg); - return 0; } void htif_console_putchar(uint8_t ch) diff --git a/machine/htif.h b/machine/htif.h index f47e965..fa768d8 100644 --- a/machine/htif.h +++ b/machine/htif.h @@ -18,6 +18,6 @@ void htif_console_putchar(uint8_t); int htif_console_getchar(); void htif_poweroff() __attribute__((noreturn)); -uintptr_t htif_syscall(uintptr_t); +void htif_syscall(uintptr_t); #endif -- cgit v1.1 From 59484c94e161b0f1870096cfb183533b20569669 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 20 Feb 2017 19:05:55 -0800 Subject: WIP on SBI --- dummy_payload/dummy_entry.S | 4 +-- machine/mcall.h | 21 ++++++------ machine/mentry.S | 11 +++++-- machine/mtrap.c | 78 ++++++++++++++++++++------------------------- machine/mtrap.h | 10 +++--- 5 files changed, 61 insertions(+), 63 deletions(-) diff --git a/dummy_payload/dummy_entry.S b/dummy_payload/dummy_entry.S index 46c0b7f..92d4652 100644 --- a/dummy_payload/dummy_entry.S +++ b/dummy_payload/dummy_entry.S @@ -7,13 +7,13 @@ _start: 1: lbu a0, (s0) beqz a0, 1f - li a7, MCALL_CONSOLE_PUTCHAR + li a7, SBI_CONSOLE_PUTCHAR ecall add s0, s0, 1 j 1b 1: - li a7, MCALL_SHUTDOWN + li a7, SBI_SHUTDOWN ecall .data diff --git a/machine/mcall.h b/machine/mcall.h index a704480..6a2c037 100644 --- a/machine/mcall.h +++ b/machine/mcall.h @@ -1,13 +1,14 @@ -#ifndef _RISCV_MCALL_H -#define _RISCV_MCALL_H +#ifndef _RISCV_SBI_H +#define _RISCV_SBI_H -#define MCALL_CONSOLE_PUTCHAR 1 -#define MCALL_CONSOLE_GETCHAR 2 -#define MCALL_SEND_IPI 4 -#define MCALL_CLEAR_IPI 5 -#define MCALL_SHUTDOWN 6 -#define MCALL_SET_TIMER 7 -#define MCALL_REMOTE_SFENCE_VM 8 -#define MCALL_REMOTE_FENCE_I 9 +#define SBI_SET_TIMER 0 +#define SBI_CONSOLE_PUTCHAR 1 +#define SBI_CONSOLE_GETCHAR 2 +#define SBI_CLEAR_IPI 3 +#define SBI_SEND_IPI 4 +#define SBI_REMOTE_FENCE_I 5 +#define SBI_REMOTE_SFENCE_VMA 6 +#define SBI_REMOTE_SFENCE_VMA_ASID 7 +#define SBI_SHUTDOWN 8 #endif diff --git a/machine/mentry.S b/machine/mentry.S index 6e77d5e..5ff5c68 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -6,6 +6,7 @@ .data .align 6 trap_table: +#define BAD_TRAP_VECTOR 0 .word bad_trap .word bad_trap .word illegal_insn_trap @@ -60,11 +61,11 @@ trap_vector: 1: # Is it an IPI? li a0, IRQ_M_SOFT * 2 - bne a0, a1, bad_trap + bne a0, a1, .Lbad_trap # Yes. First, clear the MIPI bit. LOAD a0, MENTRY_IPI_OFFSET(sp) - STORE x0, (a0) + sw x0, (a0) fence # Now, decode the cause(s). @@ -83,7 +84,7 @@ trap_vector: beqz a1, 1f fence.i 1: - andi a1, a0, IPI_SFENCE_VM + andi a1, a0, IPI_SFENCE_VMA beqz a1, 1f sfence.vma 1: @@ -188,6 +189,10 @@ restore_regs: li a1, TRAP_FROM_MACHINE_MODE_VECTOR j .Lhandle_trap_in_machine_mode +.Lbad_trap: + li a1, BAD_TRAP_VECTOR + j .Lhandle_trap_in_machine_mode + .globl __redirect_trap __redirect_trap: # reset sp to top of M-mode stack diff --git a/machine/mtrap.c b/machine/mtrap.c index fb6c3f9..b9adebf 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -9,9 +9,9 @@ #include #include -void __attribute__((noreturn)) bad_trap() +void __attribute__((noreturn)) bad_trap(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) { - die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc)); + die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), mepc); } static uintptr_t mcall_console_putchar(uint8_t ch) @@ -45,10 +45,9 @@ void printm(const char* s, ...) static void send_ipi(uintptr_t recipient, int event) { - if ((atomic_or(&OTHER_HLS(recipient)->mipi_pending, event) & event) == 0) { - mb(); - *OTHER_HLS(recipient)->ipi = 1; - } + atomic_or(&OTHER_HLS(recipient)->mipi_pending, event); + mb(); + *OTHER_HLS(recipient)->ipi = 1; } static uintptr_t mcall_console_getchar() @@ -77,21 +76,24 @@ static uintptr_t mcall_set_timer(uint64_t when) static void send_ipi_many(uintptr_t* pmask, int event) { _Static_assert(MAX_HARTS <= 8 * sizeof(*pmask), "# harts > uintptr_t bits"); - uintptr_t mask = -1; + uintptr_t mask = ((uintptr_t)1 << num_harts) - 1; if (pmask) - mask = load_uintptr_t(pmask, read_csr(mepc)); + mask &= load_uintptr_t(pmask, read_csr(mepc)); // send IPIs to everyone - for (ssize_t i = num_harts-1; i >= 0; i--) - if ((mask >> i) & 1) + for (uintptr_t i = 0, m = mask; m; i++, m >>= 1) + if (m & 1) send_ipi(i, event); + if (event == IPI_SOFT) + return; + // wait until all events have been handled. // prevent deadlock by consuming incoming IPIs. uint32_t incoming_ipi = 0; - for (ssize_t i = num_harts-1; i >= 0; i--) - if ((mask >> i) & 1) - while (OTHER_HLS(i)->ipi) + for (uintptr_t i = 0, m = mask; m; i++, m >>= 1) + if (m & 1) + while (*OTHER_HLS(i)->ipi) incoming_ipi |= atomic_swap(HLS()->ipi, 0); // if we got an IPI, restore it; it will be taken after returning @@ -101,49 +103,40 @@ static void send_ipi_many(uintptr_t* pmask, int event) } } -static uintptr_t mcall_remote_sfence_vm(uintptr_t* hart_mask) -{ - // ignore the ASID and do a global flush. - // this allows us to avoid queueing a message. - send_ipi_many(hart_mask, IPI_SFENCE_VM); - return 0; -} - -static uintptr_t mcall_remote_fence_i(uintptr_t* hart_mask) -{ - send_ipi_many(hart_mask, IPI_FENCE_I); - return 0; -} - void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) { - uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval; - uintptr_t ipi_type = 0; + write_csr(mepc, mepc + 4); + + uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval, ipi_type; switch (n) { - case MCALL_CONSOLE_PUTCHAR: + case SBI_CONSOLE_PUTCHAR: retval = mcall_console_putchar(arg0); break; - case MCALL_CONSOLE_GETCHAR: + case SBI_CONSOLE_GETCHAR: retval = mcall_console_getchar(); break; - case MCALL_SEND_IPI: + case SBI_SEND_IPI: ipi_type = IPI_SOFT; - case MCALL_REMOTE_SFENCE_VM: - ipi_type = IPI_SFENCE_VM; - case MCALL_REMOTE_FENCE_I: + goto send_ipi; + case SBI_REMOTE_SFENCE_VMA: + case SBI_REMOTE_SFENCE_VMA_ASID: + ipi_type = IPI_SFENCE_VMA; + goto send_ipi; + case SBI_REMOTE_FENCE_I: ipi_type = IPI_FENCE_I; +send_ipi: send_ipi_many((uintptr_t*)arg0, ipi_type); retval = 0; break; - case MCALL_CLEAR_IPI: + case SBI_CLEAR_IPI: retval = mcall_clear_ipi(); break; - case MCALL_SHUTDOWN: + case SBI_SHUTDOWN: retval = mcall_shutdown(); break; - case MCALL_SET_TIMER: + case SBI_SET_TIMER: #if __riscv_xlen == 32 retval = mcall_set_timer(arg0 + ((uint64_t)arg1 << 32)); #else @@ -155,7 +148,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) break; } regs[10] = retval; - write_csr(mepc, mepc + 4); } void redirect_trap(uintptr_t epc, uintptr_t mstatus) @@ -175,7 +167,7 @@ void redirect_trap(uintptr_t epc, uintptr_t mstatus) return __redirect_trap(); } -static void machine_page_fault(uintptr_t* regs, uintptr_t mepc) +static void machine_page_fault(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) { // MPRV=1 iff this trap occurred while emulating an instruction on behalf // of a lower privilege level. In that case, a2=epc and a3=mstatus. @@ -183,7 +175,7 @@ static void machine_page_fault(uintptr_t* regs, uintptr_t mepc) write_csr(sbadaddr, read_csr(mbadaddr)); return redirect_trap(regs[12], regs[13]); } - bad_trap(); + bad_trap(regs, dummy, mepc); } void trap_from_machine_mode(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) @@ -194,8 +186,8 @@ void trap_from_machine_mode(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) { case CAUSE_FAULT_LOAD: case CAUSE_FAULT_STORE: - return machine_page_fault(regs, mepc); + return machine_page_fault(regs, dummy, mepc); default: - bad_trap(); + bad_trap(regs, dummy, mepc); } } diff --git a/machine/mtrap.h b/machine/mtrap.h index 6f38cf6..3700a6d 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -36,10 +36,10 @@ extern volatile uint32_t* plic_priorities; extern size_t plic_ndevs; typedef struct { - uint32_t* ipi; + volatile uint32_t* ipi; volatile int mipi_pending; - uint64_t* timecmp; + volatile uint64_t* timecmp; volatile uint32_t* plic_m_thresh; volatile uintptr_t* plic_m_ie; @@ -75,9 +75,9 @@ static inline void wfi() #endif // !__ASSEMBLER__ -#define IPI_SOFT 0x1 -#define IPI_FENCE_I 0x2 -#define IPI_SFENCE_VM 0x4 +#define IPI_SOFT 0x1 +#define IPI_FENCE_I 0x2 +#define IPI_SFENCE_VMA 0x4 #define MACHINE_STACK_SIZE RISCV_PGSIZE #define MENTRY_HLS_OFFSET (INTEGER_CONTEXT_SIZE + SOFT_FLOAT_CONTEXT_SIZE) -- cgit v1.1 From f6bca6e35b66632afad68f6b7fb2b3203c8502fb Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 20 Feb 2017 21:43:09 -0800 Subject: Don't block for acks on console writes --- Makefile.in | 6 +- bbl/bbl.ac | 4 +- bbl/bbl.c | 17 ++--- bbl/bbl.h | 1 - bbl/bbl.lds | 4 +- bbl/bbl.mk.in | 6 +- bbl/kernel_elf.c | 50 -------------- bbl/payload.S | 10 +-- configure | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- configure.ac | 2 + machine/htif.c | 54 +++++++++------ machine/mentry.S | 11 +-- machine/minit.c | 8 --- machine/mtrap.h | 1 - pk/mmap.c | 12 ++-- pk/mmap.h | 1 + pk/pk.lds | 4 +- 17 files changed, 277 insertions(+), 118 deletions(-) delete mode 100644 bbl/kernel_elf.c diff --git a/Makefile.in b/Makefile.in index b2aca28..7b9bb81 100644 --- a/Makefile.in +++ b/Makefile.in @@ -35,7 +35,6 @@ default : all project_name := @PACKAGE_TARNAME@ src_dir := @srcdir@ scripts_dir := $(src_dir)/scripts -bbl_payload := @BBL_PAYLOAD@ # If the version information is not in the configure script, then we # assume that we are in a working directory. We use the vcs-version.sh @@ -84,7 +83,10 @@ VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled)) # - CXXFLAGS : flags for C++ compiler (eg. -Wall,-g,-O3) CC := @CC@ -CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"$(bbl_payload)\" +READELF := @READELF@ +OBJCOPY := @OBJCOPY@ +CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"bbl_payload\" +BBL_PAYLOAD := @BBL_PAYLOAD@ COMPILE := $(CC) -MMD -MP $(CFLAGS) \ $(sprojs_include) # Linker diff --git a/bbl/bbl.ac b/bbl/bbl.ac index 51dcf01..4b6a9f3 100644 --- a/bbl/bbl.ac +++ b/bbl/bbl.ac @@ -1,5 +1,5 @@ -AC_ARG_ENABLE([logo], AS_HELP_STRING([--disable-logo], [Disable boot logo])) -AS_IF([test "x$enable_logo" != "xno"], [ +AC_ARG_ENABLE([logo], AS_HELP_STRING([--enable-logo], [Enable boot logo])) +AS_IF([test "x$enable_logo" == "xyes"], [ AC_DEFINE([PK_ENABLE_LOGO],,[Define if the RISC-V logo is to be displayed]) ]) diff --git a/bbl/bbl.c b/bbl/bbl.c index bdd56ad..9553ddb 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -6,24 +6,25 @@ #include "config.h" #include -static volatile uintptr_t entry_point; +static const void* entry_point; void boot_other_hart() { - while (!entry_point) - ; - mb(); - enter_supervisor_mode((void *)entry_point, read_csr(mhartid), 0); + const void* entry; + do { + entry = entry_point; + mb(); + } while (!entry); + enter_supervisor_mode(entry, read_csr(mhartid), 0); } void boot_loader() { - extern char _payload_start, _payload_end; - uintptr_t entry = load_kernel_elf(&_payload_start, &_payload_end - &_payload_start); + extern char _payload_start; #ifdef PK_ENABLE_LOGO print_logo(); #endif mb(); - entry_point = entry; + entry_point = &_payload_start; boot_other_hart(); } diff --git a/bbl/bbl.h b/bbl/bbl.h index 67997b9..c9a02e1 100644 --- a/bbl/bbl.h +++ b/bbl/bbl.h @@ -8,7 +8,6 @@ #include #include -uintptr_t load_kernel_elf(void* blob, size_t size); void print_logo(); #endif // !__ASSEMBLER__ diff --git a/bbl/bbl.lds b/bbl/bbl.lds index 6833e47..b90e99f 100644 --- a/bbl/bbl.lds +++ b/bbl/bbl.lds @@ -44,9 +44,9 @@ SECTIONS /* HTIF, isolated onto separate page */ /*--------------------------------------------------------------------*/ . = ALIGN(0x1000); - htif : + .htif : { - *(htif) + *(.htif) } . = ALIGN(0x1000); diff --git a/bbl/bbl.mk.in b/bbl/bbl.mk.in index 1bb4cd1..5abe2cd 100644 --- a/bbl/bbl.mk.in +++ b/bbl/bbl.mk.in @@ -8,13 +8,15 @@ bbl_hdrs = \ bbl.h \ bbl_c_srcs = \ - kernel_elf.c \ logo.c \ bbl_asm_srcs = \ payload.S \ -payload.o: $(bbl_payload) +payload.o: bbl_payload + +bbl_payload: $(BBL_PAYLOAD) + if $(READELF) -h $< 2> /dev/null > /dev/null; then $(OBJCOPY) -O binary $< $@; else cp $< $@; fi bbl_test_srcs = diff --git a/bbl/kernel_elf.c b/bbl/kernel_elf.c deleted file mode 100644 index 096a690..0000000 --- a/bbl/kernel_elf.c +++ /dev/null @@ -1,50 +0,0 @@ -// See LICENSE for license details. - -#include "mtrap.h" -#include "bbl.h" -#include "bits.h" -#include "vm.h" -#include -#include - -uintptr_t load_kernel_elf(void* blob, size_t size) -{ - Elf_Ehdr* eh = blob; - if (sizeof(*eh) > size || - !(eh->e_ident[0] == '\177' && eh->e_ident[1] == 'E' && - eh->e_ident[2] == 'L' && eh->e_ident[3] == 'F')) - goto fail; - - if (IS_ELF64(*eh) != (sizeof(uintptr_t) == 8)) - goto fail; - - uintptr_t min_vaddr = -1, max_vaddr = 0; - size_t phdr_size = eh->e_phnum * sizeof(Elf_Ehdr); - Elf_Phdr* ph = blob + eh->e_phoff; - if (eh->e_phoff + phdr_size > size) - goto fail; - first_free_paddr = ROUNDUP(first_free_paddr, MEGAPAGE_SIZE); - for (int i = 0; i < eh->e_phnum; i++) - if (ph[i].p_type == PT_LOAD && ph[i].p_memsz && ph[i].p_vaddr < min_vaddr) - min_vaddr = ph[i].p_vaddr; - min_vaddr = ROUNDDOWN(min_vaddr, MEGAPAGE_SIZE); - uintptr_t bias = first_free_paddr - min_vaddr; - for (int i = eh->e_phnum - 1; i >= 0; i--) { - if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { - uintptr_t prepad = ph[i].p_vaddr % RISCV_PGSIZE; - uintptr_t vaddr = ph[i].p_vaddr + bias; - if (vaddr + ph[i].p_memsz > max_vaddr) - max_vaddr = vaddr + ph[i].p_memsz; - if (ph[i].p_offset + ph[i].p_filesz > size) - goto fail; - memcpy((void*)vaddr, blob + ph[i].p_offset, ph[i].p_filesz); - memset((void*)vaddr - prepad, 0, prepad); - memset((void*)vaddr + ph[i].p_filesz, 0, ph[i].p_memsz - ph[i].p_filesz); - } - } - - return eh->e_entry + bias; - -fail: - die("failed to load payload"); -} diff --git a/bbl/payload.S b/bbl/payload.S index 7ff1e58..6a175aa 100644 --- a/bbl/payload.S +++ b/bbl/payload.S @@ -1,7 +1,9 @@ -.section ".payload","a",@progbits -.align 3 +#include "encoding.h" -.globl _payload_start, _payload_end + .section ".payload","a",@progbits + .align RISCV_PGSHIFT + RISCV_PGLEVEL_BITS + + .globl _payload_start, _payload_end _payload_start: -.incbin BBL_PAYLOAD + .incbin BBL_PAYLOAD _payload_end: diff --git a/configure b/configure index 2ca6316..c1b2b73 100755 --- a/configure +++ b/configure @@ -603,6 +603,8 @@ INSTALL_PROGRAM STOW_PREFIX STOW_ROOT enable_stow +OBJCOPY +READELF RANLIB AR ac_ct_CXX @@ -642,6 +644,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -725,6 +728,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -977,6 +981,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1114,7 +1127,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1267,6 +1280,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1305,7 +1319,7 @@ Optional Features: --enable-optional-subprojects Enable all optional subprojects --disable-vm Disable virtual memory - --disable-logo Disable boot logo + --enable-logo Enable boot logo --disable-fp-emulation Disable floating-point emulation Optional Packages: @@ -3250,6 +3264,190 @@ else RANLIB="$ac_cv_prog_RANLIB" fi +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}readelf", so it can be a program name with args. +set dummy ${ac_tool_prefix}readelf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_READELF+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$READELF"; then + ac_cv_prog_READELF="$READELF" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_READELF="${ac_tool_prefix}readelf" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +READELF=$ac_cv_prog_READELF +if test -n "$READELF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF" >&5 +$as_echo "$READELF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_READELF"; then + ac_ct_READELF=$READELF + # Extract the first word of "readelf", so it can be a program name with args. +set dummy readelf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_READELF+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_READELF"; then + ac_cv_prog_ac_ct_READELF="$ac_ct_READELF" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_READELF="readelf" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_READELF=$ac_cv_prog_ac_ct_READELF +if test -n "$ac_ct_READELF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_READELF" >&5 +$as_echo "$ac_ct_READELF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_READELF" = x; then + READELF="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + READELF=$ac_ct_READELF + fi +else + READELF="$ac_cv_prog_READELF" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args. +set dummy ${ac_tool_prefix}objcopy; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJCOPY+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJCOPY"; then + ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJCOPY=$ac_cv_prog_OBJCOPY +if test -n "$OBJCOPY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCOPY" >&5 +$as_echo "$OBJCOPY" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJCOPY"; then + ac_ct_OBJCOPY=$OBJCOPY + # Extract the first word of "objcopy", so it can be a program name with args. +set dummy objcopy; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJCOPY+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJCOPY"; then + ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJCOPY="objcopy" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY +if test -n "$ac_ct_OBJCOPY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJCOPY" >&5 +$as_echo "$ac_ct_OBJCOPY" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJCOPY" = x; then + OBJCOPY="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJCOPY=$ac_ct_OBJCOPY + fi +else + OBJCOPY="$ac_cv_prog_OBJCOPY" +fi + #------------------------------------------------------------------------- # MCPPBS specific program checks @@ -4020,7 +4218,7 @@ if test "${enable_logo+set}" = set; then : enableval=$enable_logo; fi -if test "x$enable_logo" != "xno"; then : +if test "x$enable_logo" == "xyes"; then : $as_echo "#define PK_ENABLE_LOGO /**/" >>confdefs.h diff --git a/configure.ac b/configure.ac index 1bf0326..b4a58fd 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,8 @@ AC_PROG_CC AC_PROG_CXX AC_CHECK_TOOL([AR],[ar]) AC_CHECK_TOOL([RANLIB],[ranlib]) +AC_CHECK_TOOL([READELF],[readelf]) +AC_CHECK_TOOL([OBJCOPY],[objcopy]) #------------------------------------------------------------------------- # MCPPBS specific program checks diff --git a/machine/htif.c b/machine/htif.c index 8b8d69b..fa3db53 100644 --- a/machine/htif.c +++ b/machine/htif.c @@ -2,47 +2,56 @@ #include "atomic.h" #include "mtrap.h" -volatile uint64_t tohost __attribute__((section("htif"))); -volatile uint64_t fromhost __attribute__((section("htif"))); +volatile uint64_t tohost __attribute__((section(".htif"))); +volatile uint64_t fromhost __attribute__((section(".htif"))); volatile int htif_console_buf; static spinlock_t htif_lock = SPINLOCK_INIT; -static void request_htif_keyboard_interrupt() -{ - assert(tohost == 0); - tohost = TOHOST_CMD(1, 0, 0); -} - static void __check_fromhost() { - // we should only be interrupted by keypresses uint64_t fh = fromhost; if (!fh) return; - assert(FROMHOST_DEV(fh) == 1 && FROMHOST_CMD(fh) == 0); - htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh); fromhost = 0; + + // this should be from the console + assert(FROMHOST_DEV(fh) == 1); + switch (FROMHOST_CMD(fh)) { + case 0: + htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh); + break; + case 1: + break; + default: + assert(0); + } +} + +static void __set_tohost(uintptr_t dev, uintptr_t cmd, uintptr_t data) +{ + while (tohost) + __check_fromhost(); + tohost = TOHOST_CMD(dev, cmd, data); } int htif_console_getchar() { - if (spinlock_trylock(&htif_lock) == 0) { + spinlock_lock(&htif_lock); __check_fromhost(); - spinlock_unlock(&htif_lock); - } + int ch = htif_console_buf; + if (ch >= 0) { + htif_console_buf = -1; + __set_tohost(1, 0, 0); + } + spinlock_unlock(&htif_lock); - int ch = atomic_swap(&htif_console_buf, -1); - if (ch >= 0) - request_htif_keyboard_interrupt(); return ch - 1; } static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) { spinlock_lock(&htif_lock); - while (tohost) - __check_fromhost(); - tohost = TOHOST_CMD(dev, cmd, data); + __set_tohost(dev, cmd, data); while (1) { uint64_t fh = fromhost; @@ -53,7 +62,6 @@ static void do_tohost_fromhost(uintptr_t dev, uintptr_t cmd, uintptr_t data) } __check_fromhost(); } - wfi(); } spinlock_unlock(&htif_lock); } @@ -65,7 +73,9 @@ void htif_syscall(uintptr_t arg) void htif_console_putchar(uint8_t ch) { - do_tohost_fromhost(1, 1, ch); + spinlock_lock(&htif_lock); + __set_tohost(1, 1, ch); + spinlock_unlock(&htif_lock); } void htif_poweroff() diff --git a/machine/mentry.S b/machine/mentry.S index 5ff5c68..01db536 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -247,11 +247,7 @@ do_reset: csrr t1, mtvec 1:bne t0, t1, 1b - # sp <- end of first full page after the end of the binary - la sp, _end + 2*RISCV_PGSIZE - 1 - li t0, -RISCV_PGSIZE - and sp, sp, t0 - addi sp, sp, -MENTRY_FRAME_SIZE + la sp, stacks + RISCV_PGSIZE - MENTRY_FRAME_SIZE csrr a0, mhartid slli a1, a0, RISCV_PGSHIFT @@ -278,3 +274,8 @@ do_reset: #endif wfi j .LmultiHart + + .bss + .align RISCV_PGSHIFT +stacks: + .skip RISCV_PGSIZE * MAX_HARTS diff --git a/machine/minit.c b/machine/minit.c index 0c95ea4..e84f6d9 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -6,7 +6,6 @@ #include pte_t* root_page_table; -uintptr_t first_free_paddr; uintptr_t mem_size; uintptr_t num_harts; volatile uint64_t* mtime; @@ -67,16 +66,9 @@ hls_t* hls_init(uintptr_t id) return hls; } -static uintptr_t sbi_top_paddr() -{ - extern char _end; - return ROUNDUP((uintptr_t)&_end, RISCV_PGSIZE); -} - static void memory_init() { mem_size = mem_size / MEGAPAGE_SIZE * MEGAPAGE_SIZE; - first_free_paddr = sbi_top_paddr() + num_harts * RISCV_PGSIZE; } static void hart_init() diff --git a/machine/mtrap.h b/machine/mtrap.h index 3700a6d..2f0fc69 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -28,7 +28,6 @@ static inline int xlen() return read_const_csr(misa) < 0 ? 64 : 32; } -extern uintptr_t first_free_paddr; extern uintptr_t mem_size; extern uintptr_t num_harts; extern volatile uint64_t* mtime; diff --git a/pk/mmap.c b/pk/mmap.c index 9e9be57..33c3da2 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -20,6 +20,7 @@ typedef struct { static spinlock_t vm_lock = SPINLOCK_INIT; static vmr_t* vmrs; +uintptr_t first_free_paddr; static uintptr_t first_free_page; static size_t next_free_page; static size_t free_pages; @@ -385,15 +386,14 @@ void populate_mapping(const void* start, size_t size, int prot) uintptr_t pk_vm_init() { -#if __riscv_xlen == 32 - // We can't support more than 2 GiB of memory in RV32 + // HTIF address signedness and va2pa macro both cap memory size to 2 GiB mem_size = MIN(mem_size, 1U << 31); -#endif - size_t mem_pages = mem_size >> RISCV_PGSHIFT; free_pages = MAX(8, mem_pages >> (RISCV_PGLEVEL_BITS-1)); - first_free_page = first_free_paddr; - first_free_paddr += free_pages * RISCV_PGSIZE; + + extern char _end; + first_free_page = ROUNDUP((uintptr_t)&_end, RISCV_PGSIZE); + first_free_paddr = first_free_page + free_pages * RISCV_PGSIZE; root_page_table = (void*)__page_alloc(); __map_kernel_range(DRAM_BASE, DRAM_BASE, first_free_paddr - DRAM_BASE, PROT_READ|PROT_WRITE|PROT_EXEC); diff --git a/pk/mmap.h b/pk/mmap.h index f4f39f5..efc7c1e 100644 --- a/pk/mmap.h +++ b/pk/mmap.h @@ -33,6 +33,7 @@ uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot); uintptr_t do_brk(uintptr_t addr); #define va2pa(va) ({ uintptr_t __va = (uintptr_t)(va); \ + extern uintptr_t first_free_paddr; \ __va >= DRAM_BASE ? __va : __va + first_free_paddr; }) #endif diff --git a/pk/pk.lds b/pk/pk.lds index 1bc9adf..5348635 100644 --- a/pk/pk.lds +++ b/pk/pk.lds @@ -44,9 +44,9 @@ SECTIONS /* HTIF, isolated onto separate page */ /*--------------------------------------------------------------------*/ . = ALIGN(0x1000); - htif : + .htif : { - *(htif) + *(.htif) } . = ALIGN(0x1000); -- cgit v1.1 From 34979b93458d685df65a49bca3084eb8283439da Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 22 Feb 2017 20:31:28 -0800 Subject: Fix PK boot --- machine/encoding.h | 22 ++++++---------------- machine/minit.c | 4 +++- machine/vm.h | 4 ++-- pk/mmap.c | 9 ++++++--- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index 9a87807..e46e3d8 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -167,10 +167,12 @@ # define MSTATUS_SD MSTATUS64_SD # define SSTATUS_SD SSTATUS64_SD # define RISCV_PGLEVEL_BITS 9 +# define SPTBR_MODE SPTBR64_MODE #else # define MSTATUS_SD MSTATUS32_SD # define SSTATUS_SD SSTATUS32_SD # define RISCV_PGLEVEL_BITS 10 +# define SPTBR_MODE SPTBR32_MODE #endif #define RISCV_PGSHIFT 12 #define RISCV_PGSIZE (1 << RISCV_PGSHIFT) @@ -184,30 +186,18 @@ __tmp; }) #define write_csr(reg, val) ({ \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ - else \ - asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + asm volatile ("csrw " #reg ", %0" :: "rK"(val)); }) #define swap_csr(reg, val) ({ unsigned long __tmp; \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ - else \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \ __tmp; }) #define set_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ __tmp; }) #define clear_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ __tmp; }) #define rdtime() read_csr(time) diff --git a/machine/minit.c b/machine/minit.c index e84f6d9..0a1e37e 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -21,6 +21,9 @@ static void mstatus_init() write_csr(mucounteren, -1); write_csr(mscounteren, -1); write_csr(mie, ~MIP_MTIP); // disable timer; enable other interrupts + + // Disable paging + write_csr(sptbr, 0); } // send S-mode interrupts and most exceptions straight to S-mode @@ -141,7 +144,6 @@ void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1 write_csr(mstatus, mstatus); write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE); write_csr(mepc, fn); - write_csr(sptbr, 0); register uintptr_t a0 asm ("a0") = arg0; register uintptr_t a1 asm ("a1") = arg1; diff --git a/machine/vm.h b/machine/vm.h index 6d3da4e..29f4535 100644 --- a/machine/vm.h +++ b/machine/vm.h @@ -6,11 +6,11 @@ #define MEGAPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS)) #if __riscv_xlen == 64 -# define SPTBR_MODE INSERT_FIELD(0, SPTBR64_MODE, SPTBR_MODE_SV39) +# define SPTBR_MODE_CHOICE INSERT_FIELD(0, SPTBR64_MODE, SPTBR_MODE_SV39) # define VA_BITS 39 # define GIGAPAGE_SIZE (MEGAPAGE_SIZE << RISCV_PGLEVEL_BITS) #else -# define SPTBR_MODE INSERT_FIELD(0, SPTBR32_MODE, SPTBR_MODE_SV32) +# define SPTBR_MODE_CHOICE INSERT_FIELD(0, SPTBR32_MODE, SPTBR_MODE_SV32) # define VA_BITS 32 #endif diff --git a/pk/mmap.c b/pk/mmap.c index 33c3da2..a063f42 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -142,9 +142,9 @@ static uintptr_t __vm_alloc(size_t npage) static inline pte_t prot_to_type(int prot, int user) { pte_t pte = 0; - if (prot & PROT_READ) pte |= PTE_R; - if (prot & PROT_WRITE) pte |= PTE_W; - if (prot & PROT_EXEC) pte |= PTE_X; + if (prot & PROT_READ) pte |= PTE_R | PTE_A; + if (prot & PROT_WRITE) pte |= PTE_W | PTE_D; + if (prot & PROT_EXEC) pte |= PTE_X | PTE_A; if (pte == 0) pte = PTE_R; if (user) pte |= PTE_U; return pte; @@ -406,6 +406,9 @@ uintptr_t pk_vm_init() kassert(stack_bottom != (uintptr_t)-1); current.stack_top = stack_bottom + stack_size; + flush_tlb(); + write_csr(sptbr, ((uintptr_t)root_page_table >> RISCV_PGSHIFT) | SPTBR_MODE_CHOICE); + uintptr_t kernel_stack_top = __page_alloc() + RISCV_PGSIZE; return kernel_stack_top; } -- cgit v1.1 From 410fb0384f0fac770ab89b675939790d9253bbf1 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sat, 25 Feb 2017 15:32:40 -0800 Subject: New counter-enable scheme https://github.com/riscv/riscv-isa-manual/issues/10 --- machine/emulation.c | 6 +++--- machine/encoding.h | 8 ++++---- machine/minit.c | 8 +++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/machine/emulation.c b/machine/emulation.c index 696467d..25b39af 100644 --- a/machine/emulation.c +++ b/machine/emulation.c @@ -150,9 +150,9 @@ DECLARE_EMULATION_FUNC(truly_illegal_insn) static inline int emulate_read_csr(int num, uintptr_t mstatus, uintptr_t* result) { - uintptr_t counteren = - EXTRACT_FIELD(mstatus, MSTATUS_MPP) == PRV_U ? read_csr(mucounteren) : - read_csr(mscounteren); + uintptr_t counteren = -1; + if (EXTRACT_FIELD(mstatus, MSTATUS_MPP) == PRV_U) + counteren = read_csr(scounteren); switch (num) { diff --git a/machine/encoding.h b/machine/encoding.h index e46e3d8..e8e9dd4 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -778,6 +778,7 @@ #define CSR_SSTATUS 0x100 #define CSR_SIE 0x104 #define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 #define CSR_SCAUSE 0x142 @@ -790,6 +791,7 @@ #define CSR_MIDELEG 0x303 #define CSR_MIE 0x304 #define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 #define CSR_MSCRATCH 0x340 #define CSR_MEPC 0x341 #define CSR_MCAUSE 0x342 @@ -833,8 +835,6 @@ #define CSR_MHPMCOUNTER29 0xb1d #define CSR_MHPMCOUNTER30 0xb1e #define CSR_MHPMCOUNTER31 0xb1f -#define CSR_MUCOUNTEREN 0x320 -#define CSR_MSCOUNTEREN 0x321 #define CSR_MHPMEVENT3 0x323 #define CSR_MHPMEVENT4 0x324 #define CSR_MHPMEVENT5 0x325 @@ -1248,6 +1248,7 @@ DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) DECLARE_CSR(sstatus, CSR_SSTATUS) DECLARE_CSR(sie, CSR_SIE) DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(scounteren, CSR_SCOUNTEREN) DECLARE_CSR(sscratch, CSR_SSCRATCH) DECLARE_CSR(sepc, CSR_SEPC) DECLARE_CSR(scause, CSR_SCAUSE) @@ -1260,6 +1261,7 @@ DECLARE_CSR(medeleg, CSR_MEDELEG) DECLARE_CSR(mideleg, CSR_MIDELEG) DECLARE_CSR(mie, CSR_MIE) DECLARE_CSR(mtvec, CSR_MTVEC) +DECLARE_CSR(mcounteren, CSR_MCOUNTEREN) DECLARE_CSR(mscratch, CSR_MSCRATCH) DECLARE_CSR(mepc, CSR_MEPC) DECLARE_CSR(mcause, CSR_MCAUSE) @@ -1303,8 +1305,6 @@ DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) -DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) -DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) diff --git a/machine/minit.c b/machine/minit.c index 0a1e37e..9a3b01c 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -18,9 +18,11 @@ static void mstatus_init() write_csr(mstatus, MSTATUS_FS); // Enable user/supervisor use of perf counters - write_csr(mucounteren, -1); - write_csr(mscounteren, -1); - write_csr(mie, ~MIP_MTIP); // disable timer; enable other interrupts + write_csr(scounteren, -1); + write_csr(mcounteren, -1); + + // Enable software interrupts + write_csr(mie, MIP_MSIP); // Disable paging write_csr(sptbr, 0); -- cgit v1.1 From d203037851b05ed665ec98d8f6bf40dcd3984bbd Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sat, 25 Feb 2017 15:32:51 -0800 Subject: PPNs are 44 bits in RV64 --- machine/encoding.h | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index e8e9dd4..13930e8 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -106,26 +106,19 @@ #define PRV_H 2 #define PRV_M 3 -#define VM_MBARE 0 -#define VM_MBB 1 -#define VM_MBBID 2 -#define VM_SV32 8 -#define VM_SV39 9 -#define VM_SV48 10 - #define SPTBR32_MODE 0x80000000 #define SPTBR32_ASID 0x7FC00000 #define SPTBR32_PPN 0x003FFFFF -#define SPTBR64_MODE 0xE000000000000000 -#define SPTBR64_ASID 0x1FFFE00000000000 -#define SPTBR64_PPN 0x0000003FFFFFFFFF +#define SPTBR64_MODE 0xF000000000000000 +#define SPTBR64_ASID 0x0FFFF00000000000 +#define SPTBR64_PPN 0x00000FFFFFFFFFFF #define SPTBR_MODE_OFF 0 #define SPTBR_MODE_SV32 1 -#define SPTBR_MODE_SV39 4 -#define SPTBR_MODE_SV48 5 -#define SPTBR_MODE_SV57 6 -#define SPTBR_MODE_SV64 7 +#define SPTBR_MODE_SV39 8 +#define SPTBR_MODE_SV48 9 +#define SPTBR_MODE_SV57 10 +#define SPTBR_MODE_SV64 11 #define IRQ_S_SOFT 1 #define IRQ_H_SOFT 2 -- cgit v1.1 From 36a5855d446efab2d122346c99e12b66183a2e9b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 8 Mar 2017 02:13:48 -0800 Subject: Don't rely on config string for basic functionality --- machine/minit.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/machine/minit.c b/machine/minit.c index 9a3b01c..76d9bae 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -73,6 +73,9 @@ hls_t* hls_init(uintptr_t id) static void memory_init() { + // TODO FDT: mem_size + mem_size = 16 << 20; + mem_size = mem_size / MEGAPAGE_SIZE * MEGAPAGE_SIZE; } @@ -104,6 +107,9 @@ static void prci_test() static void hart_plic_init() { + // TODO FDT: mtime, ipi, timecmp + return; + // clear pending interrupts *HLS()->ipi = 0; *HLS()->timecmp = -1ULL; @@ -123,7 +129,7 @@ void init_first_hart() { hart_init(); hls_init(0); // this might get called again from parse_config_string - parse_config_string(); + //parse_config_string(); plic_init(); hart_plic_init(); //prci_test(); -- cgit v1.1 From cfc4554bc641214261089e03edc2450e9af027ac Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 16 Mar 2017 14:36:55 -0700 Subject: Simplify interrupt-stack discipline https://github.com/riscv/riscv-isa-manual/commit/f2ed45b1791bb602657adc2ea9ab5fc409c62542 --- machine/encoding.h | 43 +++++++++++++++++++++++++++++++++++++++++++ machine/mtrap.c | 4 ++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index 13930e8..1b9883e 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -19,6 +19,9 @@ #define MSTATUS_MPRV 0x00020000 #define MSTATUS_PUM 0x00040000 #define MSTATUS_MXR 0x00080000 +#define MSTATUS_TVM 0x00100000 +#define MSTATUS_TW 0x00200000 +#define MSTATUS_TSR 0x00400000 #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000 @@ -790,6 +793,26 @@ #define CSR_MCAUSE 0x342 #define CSR_MBADADDR 0x343 #define CSR_MIP 0x344 +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPCFG1 0x3a1 +#define CSR_PMPCFG2 0x3a2 +#define CSR_PMPCFG3 0x3a3 +#define CSR_PMPADDR0 0x3b0 +#define CSR_PMPADDR1 0x3b1 +#define CSR_PMPADDR2 0x3b2 +#define CSR_PMPADDR3 0x3b3 +#define CSR_PMPADDR4 0x3b4 +#define CSR_PMPADDR5 0x3b5 +#define CSR_PMPADDR6 0x3b6 +#define CSR_PMPADDR7 0x3b7 +#define CSR_PMPADDR8 0x3b8 +#define CSR_PMPADDR9 0x3b9 +#define CSR_PMPADDR10 0x3ba +#define CSR_PMPADDR11 0x3bb +#define CSR_PMPADDR12 0x3bc +#define CSR_PMPADDR13 0x3bd +#define CSR_PMPADDR14 0x3be +#define CSR_PMPADDR15 0x3bf #define CSR_TSELECT 0x7a0 #define CSR_TDATA1 0x7a1 #define CSR_TDATA2 0x7a2 @@ -1260,6 +1283,26 @@ DECLARE_CSR(mepc, CSR_MEPC) DECLARE_CSR(mcause, CSR_MCAUSE) DECLARE_CSR(mbadaddr, CSR_MBADADDR) DECLARE_CSR(mip, CSR_MIP) +DECLARE_CSR(pmpcfg0, CSR_PMPCFG0) +DECLARE_CSR(pmpcfg1, CSR_PMPCFG1) +DECLARE_CSR(pmpcfg2, CSR_PMPCFG2) +DECLARE_CSR(pmpcfg3, CSR_PMPCFG3) +DECLARE_CSR(pmpaddr0, CSR_PMPADDR0) +DECLARE_CSR(pmpaddr1, CSR_PMPADDR1) +DECLARE_CSR(pmpaddr2, CSR_PMPADDR2) +DECLARE_CSR(pmpaddr3, CSR_PMPADDR3) +DECLARE_CSR(pmpaddr4, CSR_PMPADDR4) +DECLARE_CSR(pmpaddr5, CSR_PMPADDR5) +DECLARE_CSR(pmpaddr6, CSR_PMPADDR6) +DECLARE_CSR(pmpaddr7, CSR_PMPADDR7) +DECLARE_CSR(pmpaddr8, CSR_PMPADDR8) +DECLARE_CSR(pmpaddr9, CSR_PMPADDR9) +DECLARE_CSR(pmpaddr10, CSR_PMPADDR10) +DECLARE_CSR(pmpaddr11, CSR_PMPADDR11) +DECLARE_CSR(pmpaddr12, CSR_PMPADDR12) +DECLARE_CSR(pmpaddr13, CSR_PMPADDR13) +DECLARE_CSR(pmpaddr14, CSR_PMPADDR14) +DECLARE_CSR(pmpaddr15, CSR_PMPADDR15) DECLARE_CSR(tselect, CSR_TSELECT) DECLARE_CSR(tdata1, CSR_TDATA1) DECLARE_CSR(tdata2, CSR_TDATA2) diff --git a/machine/mtrap.c b/machine/mtrap.c index b9adebf..15859d1 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -156,9 +156,9 @@ void redirect_trap(uintptr_t epc, uintptr_t mstatus) write_csr(scause, read_csr(mcause)); write_csr(mepc, read_csr(stvec)); - uintptr_t new_mstatus = mstatus & ~(MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_MPIE); + uintptr_t new_mstatus = mstatus & ~(MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE); uintptr_t mpp_s = MSTATUS_MPP & (MSTATUS_MPP >> 1); - new_mstatus |= (mstatus / (MSTATUS_MPIE / MSTATUS_SPIE)) & MSTATUS_SPIE; + new_mstatus |= (mstatus * (MSTATUS_SPIE / MSTATUS_SIE)) & MSTATUS_SPIE; new_mstatus |= (mstatus / (mpp_s / MSTATUS_SPP)) & MSTATUS_SPP; new_mstatus |= mpp_s; write_csr(mstatus, new_mstatus); -- cgit v1.1 From 7d60c5904f45d979643c1b9f6cdde42f62ef3c32 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 21 Mar 2017 16:56:52 -0700 Subject: Allow PK access to user memory --- machine/encoding.h | 15 +++++++++++++-- pk/pk.c | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index 1b9883e..4f0d0a4 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -17,7 +17,7 @@ #define MSTATUS_FS 0x00006000 #define MSTATUS_XS 0x00018000 #define MSTATUS_MPRV 0x00020000 -#define MSTATUS_PUM 0x00040000 +#define MSTATUS_SUM 0x00040000 #define MSTATUS_MXR 0x00080000 #define MSTATUS_TVM 0x00100000 #define MSTATUS_TW 0x00200000 @@ -32,7 +32,8 @@ #define SSTATUS_SPP 0x00000100 #define SSTATUS_FS 0x00006000 #define SSTATUS_XS 0x00018000 -#define SSTATUS_PUM 0x00040000 +#define SSTATUS_SUM 0x00040000 +#define SSTATUS_MXR 0x00080000 #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 @@ -123,6 +124,16 @@ #define SPTBR_MODE_SV57 10 #define SPTBR_MODE_SV64 11 +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_M 0x08 +#define PMP_NAPOT 0x10 +#define PMP_TOR 0x20 +#define PMP_EN 0x40 +#define PMP_LOCK 0x80 +#define PMP_SHIFT 2 + #define IRQ_S_SOFT 1 #define IRQ_H_SOFT 2 #define IRQ_M_SOFT 3 diff --git a/pk/pk.c b/pk/pk.c index 8132f8d..c0b6407 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -160,6 +160,7 @@ void boot_loader() write_csr(stvec, &trap_entry); write_csr(sscratch, 0); write_csr(sie, 0); + set_csr(sstatus, SSTATUS_SUM); file_init(); enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), 0); -- cgit v1.1 From db19d0d2785c50de38e5b0b1879c6c5a3793a5a3 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 21 Mar 2017 19:19:46 -0700 Subject: machine: remove configstring --- machine/configstring.c | 102 ------------------------------ machine/configstring.h | 166 ------------------------------------------------- machine/machine.mk.in | 2 - 3 files changed, 270 deletions(-) delete mode 100644 machine/configstring.c delete mode 100644 machine/configstring.h diff --git a/machine/configstring.c b/machine/configstring.c deleted file mode 100644 index 4e72f04..0000000 --- a/machine/configstring.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "configstring.h" -#include "encoding.h" -#include "mtrap.h" -#include "atomic.h" -#include - -static void query_mem(const char* config_string) -{ - query_result res = query_config_string(config_string, "ram{0{addr"); - assert(res.start); - uintptr_t base = get_uint(res); - assert(base == DRAM_BASE); - res = query_config_string(config_string, "ram{0{size"); - mem_size = get_uint(res); -} - -static void query_rtc(const char* config_string) -{ - query_result res = query_config_string(config_string, "rtc{addr"); - assert(res.start); - mtime = (void*)(uintptr_t)get_uint(res); -} - -static void query_plic(const char* config_string) -{ - query_result res = query_config_string(config_string, "plic{priority"); - if (!res.start) - return; - plic_priorities = (uint32_t*)(uintptr_t)get_uint(res); - - res = query_config_string(config_string, "plic{ndevs"); - if (!res.start) - return; - plic_ndevs = get_uint(res); -} - -static void query_hart_plic(const char* config_string, hls_t* hls, int core, int hart) -{ - char buf[48]; - snprintf(buf, sizeof buf, "core{%d{%d{plic{m{ie", core, hart); - query_result res = query_config_string(config_string, buf); - if (res.start) - hls->plic_m_ie = (void*)(uintptr_t)get_uint(res); - - snprintf(buf, sizeof buf, "core{%d{%d{plic{m{thresh", core, hart); - res = query_config_string(config_string, buf); - if (res.start) - hls->plic_m_thresh = (void*)(uintptr_t)get_uint(res); - - snprintf(buf, sizeof buf, "core{%d{%d{plic{s{ie", core, hart); - res = query_config_string(config_string, buf); - if (res.start) - hls->plic_s_ie = (void*)(uintptr_t)get_uint(res); - - snprintf(buf, sizeof buf, "core{%d{%d{plic{s{thresh", core, hart); - res = query_config_string(config_string, buf); - if (res.start) - hls->plic_s_thresh = (void*)(uintptr_t)get_uint(res); -} - -static void query_harts(const char* config_string) -{ - for (int core = 0, hart; ; core++) { - for (hart = 0; ; hart++) { - char buf[40]; - snprintf(buf, sizeof buf, "core{%d{%d{ipi", core, hart); - query_result res = query_config_string(config_string, buf); - if (!res.start) - break; - hls_t* hls = hls_init(num_harts); - hls->ipi = (void*)(uintptr_t)get_uint(res); - - query_hart_plic(config_string, hls, core, hart); - - snprintf(buf, sizeof buf, "core{%d{%d{timecmp", core, hart); - res = query_config_string(config_string, buf); - assert(res.start); - hls->timecmp = (void*)(uintptr_t)get_uint(res); - - mb(); - - // wake up the hart - *hls->ipi = 1; - - num_harts++; - } - if (!hart) - break; - } - assert(num_harts); - assert(num_harts <= MAX_HARTS); -} - -void parse_config_string() -{ - uint32_t addr = *(uint32_t*)CONFIG_STRING_ADDR; - const char* s = (const char*)(uintptr_t)addr; - query_mem(s); - query_plic(s); - query_rtc(s); - query_harts(s); -} diff --git a/machine/configstring.h b/machine/configstring.h deleted file mode 100644 index 39538c9..0000000 --- a/machine/configstring.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef RISCV_CONFIG_STRING_H -#define RISCV_CONFIG_STRING_H - -#include -#include - -static const char* skip_whitespace(const char* str) -{ - while (*str && *str <= ' ') - str++; - return str; -} - -static const char* skip_string(const char* str) -{ - while (*str && *str++ != '"') - ; - return str; -} - -static int is_hex(char ch) -{ - return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); -} - -static int parse_hex(char ch) -{ - return (ch >= '0' && ch <= '9') ? ch - '0' : - (ch >= 'a' && ch <= 'f') ? ch - 'a' + 10 : - ch - 'A' + 10; -} - -static const char* skip_key(const char* str) -{ - while (*str >= 35 && *str <= 122 && *str != ';') - str++; - return str; -} - -typedef struct { - const char* start; - const char* end; -} query_result; - -static query_result query_config_string(const char* str, const char* k) -{ - size_t ksize = 0; - while (k[ksize] && k[ksize] != '{') - ksize++; - int last = !k[ksize]; - - query_result res = {0, 0}; - while (1) { - const char* key_start = str = skip_whitespace(str); - const char* key_end = str = skip_key(str); - int match = (size_t)(key_end - key_start) == ksize; - if (match) - for (size_t i = 0; i < ksize; i++) - if (key_start[i] != k[i]) - match = 0; - const char* value_start = str = skip_whitespace(str); - while (*str != ';') { - if (!*str) { - return res; - } else if (*str == '"') { - str = skip_string(str+1); - } else if (*str == '{') { - const char* search_key = match && !last ? k + ksize + 1 : ""; - query_result inner_res = query_config_string(str + 1, search_key); - if (inner_res.start) - return inner_res; - str = inner_res.end + 1; - } else { - str = skip_key(str); - } - str = skip_whitespace(str); - } - res.end = str; - if (match && last) { - res.start = value_start; - return res; - } - str = skip_whitespace(str+1); - if (*str == '}') { - res.end = str; - return res; - } - } -} - -static void parse_string(query_result r, char* buf) -{ - if (r.start < r.end) { - if (*r.start == '"') { - for (const char* p = r.start + 1; p < r.end && *p != '"'; p++) { - char ch = p[0]; - if (ch == '\\' && p[1] == 'x' && is_hex(p[2])) { - ch = parse_hex(p[2]); - if (is_hex(p[3])) { - ch = (ch << 4) + parse_hex(p[3]); - p++; - } - p += 2; - } - *buf++ = ch; - } - } else { - for (const char* p = r.start; p < r.end && *p > ' '; p++) - *buf++ = *p; - } - } - *buf = 0; -} - -#define get_string(name, search_res) \ - char name[(search_res).end - (search_res).start + 1]; \ - parse_string(search_res, name) - -static uint64_t __get_uint_hex(const char* s) -{ - uint64_t res = 0; - while (*s) { - if (is_hex(*s)) - res = (res << 4) + parse_hex(*s); - else if (*s != '_') - break; - s++; - } - return res; -} - -static uint64_t __get_uint_dec(const char* s) -{ - uint64_t res = 0; - while (*s) { - if (*s >= '0' && *s <= '9') - res = res * 10 + (*s - '0'); - else - break; - s++; - } - return res; -} - -static uint64_t __get_uint(const char* s) -{ - if (s[0] == '0' && s[1] == 'x') - return __get_uint_hex(s+2); - return __get_uint_dec(s); -} - -static inline uint64_t get_uint(query_result res) -{ - get_string(s, res); - return __get_uint(s); -} - -static inline int64_t get_sint(query_result res) -{ - get_string(s, res); - if (s[0] == '-') - return -__get_uint(s+1); - return __get_uint(s); -} - -#endif diff --git a/machine/machine.mk.in b/machine/machine.mk.in index d083fdf..6267f5f 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -4,7 +4,6 @@ machine_subproject_deps = \ machine_hdrs = \ atomic.h \ bits.h \ - configstring.h \ emulation.h \ encoding.h \ fp_emulation.h \ @@ -23,7 +22,6 @@ machine_c_srcs = \ fp_emulation.c \ fp_ldst.c \ misaligned_ldst.c \ - configstring.c \ machine_asm_srcs = \ mentry.S \ -- cgit v1.1 From 316f85e9ae2f5d9dd0b33d3649a8256db0dfd29b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 21 Mar 2017 21:44:49 -0700 Subject: machine: add FDT parser --- machine/fdt.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++ machine/fdt.h | 54 ++++++++++++ machine/machine.mk.in | 2 + machine/minit.c | 15 ++-- 4 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 machine/fdt.c create mode 100644 machine/fdt.h diff --git a/machine/fdt.c b/machine/fdt.c new file mode 100644 index 0000000..f297e52 --- /dev/null +++ b/machine/fdt.c @@ -0,0 +1,236 @@ +#include +#include +#include "fdt.h" +#include "mtrap.h" + +static inline uint32_t bswap(uint32_t x) +{ + uint32_t y = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8; + uint32_t z = (y & 0x0000FFFF) << 16 | (y & 0xFFFF0000) >> 16; + return z; +} + +static const uint32_t *fdt_scan_helper( + const uint32_t *lex, + const char *strings, + const char *name, + struct fdt_scan_node *parent, + fdt_cb cb, + void *extra) +{ + struct fdt_scan_node node; + struct fdt_scan_prop prop; + + node.parent = parent; + node.base = lex; + node.name = name; + node.address_cells = 2; + node.size_cells = 1; + prop.node = &node; + + while (1) { + switch (bswap(lex[0])) { + case FDT_BEGIN_NODE: { + const char *child_name = (const char *)(lex+1); + lex = fdt_scan_helper( + lex + 2 + strlen(child_name)/4, + strings, child_name, &node, cb, extra); + break; + } + case FDT_PROP: { + prop.name = strings + bswap(lex[2]); + prop.len = bswap(lex[1]); + prop.value = lex + 3; + if (!strcmp(prop.name, "#address-cells")) { node.address_cells = bswap(lex[3]); } + if (!strcmp(prop.name, "#size-cells")) { node.size_cells = bswap(lex[3]); } + lex += 3 + (prop.len+3)/4; + cb(&prop, extra); + break; + } + case FDT_END_NODE: return lex + 1; + case FDT_NOP: lex += 1; break; + default: return lex; // FDT_END + } + } +} + +void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra) +{ + struct fdt_header *header = (struct fdt_header *)fdt; + + // Only process FDT that we understand + if (bswap(header->magic) != FDT_MAGIC || + bswap(header->last_comp_version) > FDT_VERSION) return; + + const char *strings = (const char *)(fdt + bswap(header->off_dt_strings)); + const uint32_t *lex = (const uint32_t *)(fdt + bswap(header->off_dt_struct)); + + fdt_scan_helper(lex, strings, "/", 0, cb, extra); +} + +const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *value, uintptr_t *result) +{ + *result = 0; + for (int cells = node->address_cells; cells > 0; --cells) *result += bswap(*value++); + return value; +} + +const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *value, uintptr_t *result) +{ + *result = 0; + for (int cells = node->size_cells; cells > 0; --cells) *result += bswap(*value++); + return value; +} + +static void find_mem(const struct fdt_scan_prop *prop, void *extra) +{ + const uint32_t **base = (const uint32_t **)extra; + if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "memory")) { + *base = prop->node->base; + } else if (!strcmp(prop->name, "reg") && prop->node->base == *base) { + const uint32_t *value = prop->value; + const uint32_t *end = value + prop->len/4; + assert (prop->len % 4 == 0); + while (end - value > 0) { + uintptr_t base, size; + value = fdt_get_address(prop->node->parent, value, &base); + value = fdt_get_size (prop->node->parent, value, &size); + if (base == DRAM_BASE) { mem_size = size; } + } + assert (end == value); + } +} + +void query_mem(uintptr_t fdt) +{ + mem_size = 0; + const uint32_t *base = 0; + fdt_scan(fdt, &find_mem, &base); + assert (mem_size > 0); +} + +static uint32_t hart_phandles[MAX_HARTS]; + +struct hart_scan { + const uint32_t *base; + int cpu; + int controller; + int cells; + int hart; + uint32_t phandle; +}; + +static void init_hart(struct hart_scan *scan, const uint32_t *base) +{ + scan->base = base; + scan->cpu = 0; + scan->controller = 0; + scan->cells = -1; + scan->hart = -1; + scan->phandle = 0; +} + +static void done_hart(struct hart_scan *scan) +{ + if (scan->cpu) { + assert (scan->controller == 1); + assert (scan->cells == 1); + assert (scan->hart >= 0); + if (scan->hart < MAX_HARTS) { + hart_phandles[scan->hart] = scan->phandle; + if (scan->hart >= num_harts) num_harts = scan->hart + 1; + } + } +} + +static void count_harts(const struct fdt_scan_prop *prop, void *extra) +{ + struct hart_scan *scan = (struct hart_scan *)extra; + if (prop->node->base != scan->base) { + done_hart(scan); + init_hart(scan, prop->node->base); + } + if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "cpu")) { + scan->cpu = 1; + } else if (!strcmp(prop->name, "interrupt-controller")) { + scan->controller = 1; + } else if (!strcmp(prop->name, "#interrupt-cells")) { + scan->cells = bswap(prop->value[0]); + } else if (!strcmp(prop->name, "phandle")) { + scan->phandle = bswap(prop->value[0]); + } else if (!strcmp(prop->name, "reg")) { + uintptr_t reg; + fdt_get_address(prop->node->parent, prop->value, ®); + scan->hart = reg; + } +} + +void query_harts(uintptr_t fdt) +{ + struct hart_scan scan; + num_harts = 0; + init_hart(&scan, 0); + fdt_scan(fdt, &count_harts, &scan); + done_hart(&scan); + assert (num_harts > 0); +} + +struct clint_scan +{ + const uint32_t *base; + uintptr_t address; +}; + +static void find_clint_base(const struct fdt_scan_prop *prop, void *extra) +{ + struct clint_scan *scan = (struct clint_scan *)extra; + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,clint0")) + scan->base = prop->node->base; +} + +static void find_clint_reg(const struct fdt_scan_prop *prop, void *extra) +{ + struct clint_scan *scan = (struct clint_scan *)extra; + if (!strcmp(prop->name, "reg") && scan->base == prop->node->base) + fdt_get_address(prop->node->parent, prop->value, &scan->address); +} + +static void setup_clint(const struct fdt_scan_prop *prop, void *extra) +{ + struct clint_scan *scan = (struct clint_scan *)extra; + if (!strcmp(prop->name, "interrupts-extended") && scan->base == prop->node->base) { + const uint32_t *value = prop->value; + const uint32_t *end = value + prop->len/4; + assert (prop->len % 16 == 0); + for (int index = 0; end - value > 0; ++index) { + uint32_t phandle = bswap(value[0]); + int hart; + for (hart = 0; hart < MAX_HARTS; ++hart) + if (hart_phandles[hart] == phandle) + break; + if (hart < MAX_HARTS) { + hls_t *hls = hls_init(hart); + hls->ipi = (void*)(scan->address + index * 4); + hls->timecmp = (void*)(scan->address + 0x4000 + (index * 8)); + *hls->ipi = 1; // wakeup the hart + } + value += 4; + } + } +} + +void query_clint(uintptr_t fdt) +{ + struct clint_scan scan; + scan.base = 0; + scan.address = 0; + + fdt_scan(fdt, &find_clint_base, &scan); + assert (scan.base != 0); + + fdt_scan(fdt, &find_clint_reg, &scan); + assert (scan.address != 0); + + mtime = (void*)(scan.address + 0xbff8); + fdt_scan(fdt, &setup_clint, &scan); +} diff --git a/machine/fdt.h b/machine/fdt.h new file mode 100644 index 0000000..71726ce --- /dev/null +++ b/machine/fdt.h @@ -0,0 +1,54 @@ +#ifndef FDT_H +#define FDT_H + +#define FDT_MAGIC 0xd00dfeed +#define FDT_VERSION 17 + +struct fdt_header { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; /* <= 17 */ + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +#define FDT_BEGIN_NODE 1 +#define FDT_END_NODE 2 +#define FDT_PROP 3 +#define FDT_NOP 4 +#define FDT_END 9 + +struct fdt_scan_node { + const struct fdt_scan_node *parent; + const uint32_t *base; // token that began the node + const char *name; + int address_cells; + int size_cells; +}; + +struct fdt_scan_prop { + const struct fdt_scan_node *node; + const char *name; + const uint32_t *value; + int len; // in bytes of value +}; + +// Scan the contents of FDT +typedef void (*fdt_cb)(const struct fdt_scan_prop *prop, void *extra); +void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra); + +// Extract fields +const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); +const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); + +// Setup memory+clint+plic +void query_mem(uintptr_t fdt); +void query_harts(uintptr_t fdt); +void query_clint(uintptr_t fdt); + +#endif diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 6267f5f..10d85b4 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -4,6 +4,7 @@ machine_subproject_deps = \ machine_hdrs = \ atomic.h \ bits.h \ + fdt.h \ emulation.h \ encoding.h \ fp_emulation.h \ @@ -14,6 +15,7 @@ machine_hdrs = \ vm.h \ machine_c_srcs = \ + fdt.c \ mtrap.c \ minit.c \ htif.c \ diff --git a/machine/minit.c b/machine/minit.c index 76d9bae..2616f19 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -2,6 +2,7 @@ #include "atomic.h" #include "vm.h" #include "fp_emulation.h" +#include "fdt.h" #include #include @@ -71,11 +72,10 @@ hls_t* hls_init(uintptr_t id) return hls; } +#define DTB 0x1014 + static void memory_init() { - // TODO FDT: mem_size - mem_size = 16 << 20; - mem_size = mem_size / MEGAPAGE_SIZE * MEGAPAGE_SIZE; } @@ -107,9 +107,6 @@ static void prci_test() static void hart_plic_init() { - // TODO FDT: mtime, ipi, timecmp - return; - // clear pending interrupts *HLS()->ipi = 0; *HLS()->timecmp = -1ULL; @@ -129,7 +126,11 @@ void init_first_hart() { hart_init(); hls_init(0); // this might get called again from parse_config_string - //parse_config_string(); + + query_mem(DTB); + query_harts(DTB); + query_clint(DTB); + plic_init(); hart_plic_init(); //prci_test(); -- cgit v1.1 From 23ab37ad78673166a8300584d177ace77fca5101 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 22 Mar 2017 14:35:13 -0700 Subject: SBI: a0+a1 hold hartid+dtb pointer between boot loader stages --- bbl/bbl.c | 8 ++++---- machine/mentry.S | 27 ++++++++++++++------------- machine/minit.c | 16 +++++++--------- machine/mtrap.h | 4 ++-- pk/pk.c | 6 +++--- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 9553ddb..3550c9a 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -8,17 +8,17 @@ static const void* entry_point; -void boot_other_hart() +void boot_other_hart(uintptr_t dtb) { const void* entry; do { entry = entry_point; mb(); } while (!entry); - enter_supervisor_mode(entry, read_csr(mhartid), 0); + enter_supervisor_mode(entry, read_csr(mhartid), dtb); } -void boot_loader() +void boot_loader(uintptr_t dtb) { extern char _payload_start; #ifdef PK_ENABLE_LOGO @@ -26,5 +26,5 @@ void boot_loader() #endif mb(); entry_point = &_payload_start; - boot_other_hart(); + boot_other_hart(dtb); } diff --git a/machine/mentry.S b/machine/mentry.S index 01db536..9ce3257 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -217,8 +217,9 @@ do_reset: li x7, 0 li x8, 0 li x9, 0 - li x10, 0 - li x11, 0 +// save a0 and a1; arguments from previous boot loader stage: +// li x10, 0 +// li x11, 0 li x12, 0 li x13, 0 li x14, 0 @@ -249,28 +250,28 @@ do_reset: la sp, stacks + RISCV_PGSIZE - MENTRY_FRAME_SIZE - csrr a0, mhartid - slli a1, a0, RISCV_PGSHIFT - add sp, sp, a1 + csrr a3, mhartid + slli a2, a3, RISCV_PGSHIFT + add sp, sp, a2 - beqz a0, init_first_hart + beqz a3, init_first_hart # set MSIE bit to receive IPI - li a1, MIP_MSIP - csrw mie, a1 + li a2, MIP_MSIP + csrw mie, a2 .LmultiHart: #if MAX_HARTS > 1 # wait for an IPI to signal that it's safe to boot wfi - csrr a1, mip - andi a1, a1, MIP_MSIP - beqz a1, .LmultiHart + csrr a2, mip + andi a2, a2, MIP_MSIP + beqz a2, .LmultiHart # make sure our hart id is within a valid range fence - li a1, MAX_HARTS - bltu a0, a1, init_other_hart + li a2, MAX_HARTS + bltu a3, a2, init_other_hart #endif wfi j .LmultiHart diff --git a/machine/minit.c b/machine/minit.c index 2616f19..f02f205 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -72,8 +72,6 @@ hls_t* hls_init(uintptr_t id) return hls; } -#define DTB 0x1014 - static void memory_init() { mem_size = mem_size / MEGAPAGE_SIZE * MEGAPAGE_SIZE; @@ -122,27 +120,27 @@ static void hart_plic_init() *HLS()->plic_s_thresh = 0; } -void init_first_hart() +void init_first_hart(uintptr_t hartid, uintptr_t dtb) { hart_init(); hls_init(0); // this might get called again from parse_config_string - query_mem(DTB); - query_harts(DTB); - query_clint(DTB); + query_mem(dtb); + query_harts(dtb); + query_clint(dtb); plic_init(); hart_plic_init(); //prci_test(); memory_init(); - boot_loader(); + boot_loader(dtb); } -void init_other_hart() +void init_other_hart(uintptr_t hartid, uintptr_t dtb) { hart_init(); hart_plic_init(); - boot_other_hart(); + boot_other_hart(dtb); } void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1) diff --git a/machine/mtrap.h b/machine/mtrap.h index 2f0fc69..e8dfc49 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -64,8 +64,8 @@ void putstring(const char* s); void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1) __attribute__((noreturn)); -void boot_loader(); -void boot_other_hart(); +void boot_loader(uintptr_t dtb); +void boot_other_hart(uintptr_t dtb); static inline void wfi() { diff --git a/pk/pk.c b/pk/pk.c index c0b6407..1a2e540 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -154,7 +154,7 @@ static void rest_of_boot_loader(uintptr_t kstack_top) run_loaded_program(argc, args.argv, kstack_top); } -void boot_loader() +void boot_loader(uintptr_t dtb) { extern char trap_entry; write_csr(stvec, &trap_entry); @@ -163,10 +163,10 @@ void boot_loader() set_csr(sstatus, SSTATUS_SUM); file_init(); - enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), 0); + enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), dtb); } -void boot_other_hart() +void boot_other_hart(uintptr_t dtb) { // stall all harts besides hart 0 while (1) -- cgit v1.1 From fc1af65c1585b2a9ad1dd2cf1b50d552ee65c742 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 23 Mar 2017 12:55:40 -0700 Subject: Set up PMPs, permissively for now --- machine/minit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/machine/minit.c b/machine/minit.c index f02f205..7083b05 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -145,6 +145,17 @@ void init_other_hart(uintptr_t hartid, uintptr_t dtb) void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1) { + // Set up a PMP to permit access to all of memory. + // Ignore the illegal-instruction trap if PMPs aren't supported. + uintptr_t pmpc = PMP_EN | PMP_NAPOT | PMP_M | PMP_R | PMP_W | PMP_X; + asm volatile ("la t0, 1f\n\t" + "csrrw t0, mtvec, t0\n\t" + "csrw pmpaddr0, %1\n\t" + "csrw pmpcfg0, %0\n\t" + ".align 2\n\t" + "1: csrw mtvec, t0" + : : "r" (pmpc), "r" (-1UL) : "t0"); + uintptr_t mstatus = read_csr(mstatus); mstatus = INSERT_FIELD(mstatus, MSTATUS_MPP, PRV_S); mstatus = INSERT_FIELD(mstatus, MSTATUS_MPIE, 0); -- cgit v1.1 From a1a5cbcacbbb43527fb6a4991ead1ae64cf18463 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 23 Mar 2017 19:11:44 -0700 Subject: fdt: add a size method --- machine/fdt.c | 10 ++++++++++ machine/fdt.h | 1 + 2 files changed, 11 insertions(+) diff --git a/machine/fdt.c b/machine/fdt.c index f297e52..a040e87 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -68,6 +68,16 @@ void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra) fdt_scan_helper(lex, strings, "/", 0, cb, extra); } +uint32_t fdt_size(uintptr_t fdt) +{ + struct fdt_header *header = (struct fdt_header *)fdt; + + // Only process FDT that we understand + if (bswap(header->magic) != FDT_MAGIC || + bswap(header->last_comp_version) > FDT_VERSION) return 0; + return bswap(header->totalsize); +} + const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *value, uintptr_t *result) { *result = 0; diff --git a/machine/fdt.h b/machine/fdt.h index 71726ce..8b01bc8 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -41,6 +41,7 @@ struct fdt_scan_prop { // Scan the contents of FDT typedef void (*fdt_cb)(const struct fdt_scan_prop *prop, void *extra); void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra); +uint32_t fdt_size(uintptr_t fdt); // Extract fields const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); -- cgit v1.1 From 96965a8cc670d10055dbf64d42fedcda5b35beff Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 23 Mar 2017 19:12:08 -0700 Subject: pk: does not use dtb --- pk/pk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pk/pk.c b/pk/pk.c index 1a2e540..11a2cdf 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -163,7 +163,7 @@ void boot_loader(uintptr_t dtb) set_csr(sstatus, SSTATUS_SUM); file_init(); - enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), dtb); + enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), 0); } void boot_other_hart(uintptr_t dtb) -- cgit v1.1 From 96e5ed750e7447f2c0316368e5592fd331ee345c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 23 Mar 2017 19:16:43 -0700 Subject: bbl: copy dtb after the kernel --- bbl/bbl.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 3550c9a..300182c 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -4,10 +4,25 @@ #include "vm.h" #include "bits.h" #include "config.h" +#include "fdt.h" #include static const void* entry_point; +static uintptr_t dtb_output() +{ + extern char _payload_end; + uintptr_t end = (uintptr_t) &_payload_end; + return (end + MEGAPAGE_SIZE - 1) / MEGAPAGE_SIZE * MEGAPAGE_SIZE; +} + +static void filter_dtb(uintptr_t source) +{ + uintptr_t dest = dtb_output(); + uint32_t size = fdt_size(source); + memcpy((void*)dest, (void*)source, size); +} + void boot_other_hart(uintptr_t dtb) { const void* entry; @@ -15,12 +30,13 @@ void boot_other_hart(uintptr_t dtb) entry = entry_point; mb(); } while (!entry); - enter_supervisor_mode(entry, read_csr(mhartid), dtb); + enter_supervisor_mode(entry, read_csr(mhartid), dtb_output()); } void boot_loader(uintptr_t dtb) { extern char _payload_start; + filter_dtb(dtb); #ifdef PK_ENABLE_LOGO print_logo(); #endif -- cgit v1.1 From 3473915b3a3fd925a68fc3260c64824cab2846d2 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 27 Mar 2017 14:30:58 -0700 Subject: Separate page faults from physical memory access exceptions --- machine/encoding.h | 23 ++++++++++++++--------- machine/mentry.S | 11 +++++++---- machine/minit.c | 6 +++--- machine/mtrap.c | 12 ++++++++++-- pk/handlers.c | 6 +++--- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index 4f0d0a4..b07d976 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -147,9 +147,8 @@ #define IRQ_HOST 13 #define DEFAULT_RSTVEC 0x00001000 -#define DEFAULT_NMIVEC 0x00001004 -#define DEFAULT_MTVEC 0x00001010 -#define CONFIG_STRING_ADDR 0x0000100C +#define CLINT_BASE 0x02000000 +#define CLINT_SIZE 0x000c0000 #define EXT_IO_BASE 0x40000000 #define DRAM_BASE 0x80000000 @@ -959,17 +958,20 @@ #define CSR_MHPMCOUNTER30H 0xb9e #define CSR_MHPMCOUNTER31H 0xb9f #define CAUSE_MISALIGNED_FETCH 0x0 -#define CAUSE_FAULT_FETCH 0x1 +#define CAUSE_FETCH_ACCESS 0x1 #define CAUSE_ILLEGAL_INSTRUCTION 0x2 #define CAUSE_BREAKPOINT 0x3 #define CAUSE_MISALIGNED_LOAD 0x4 -#define CAUSE_FAULT_LOAD 0x5 +#define CAUSE_LOAD_ACCESS 0x5 #define CAUSE_MISALIGNED_STORE 0x6 -#define CAUSE_FAULT_STORE 0x7 +#define CAUSE_STORE_ACCESS 0x7 #define CAUSE_USER_ECALL 0x8 #define CAUSE_SUPERVISOR_ECALL 0x9 #define CAUSE_HYPERVISOR_ECALL 0xa #define CAUSE_MACHINE_ECALL 0xb +#define CAUSE_FETCH_PAGE_FAULT 0xc +#define CAUSE_LOAD_PAGE_FAULT 0xd +#define CAUSE_STORE_PAGE_FAULT 0xf #endif #ifdef DECLARE_INSN DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) @@ -1451,15 +1453,18 @@ DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) #endif #ifdef DECLARE_CAUSE DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) -DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) +DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS) DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) -DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) +DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS) DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) -DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) +DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS) DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT) +DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT) +DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT) #endif diff --git a/machine/mentry.S b/machine/mentry.S index 9ce3257..9575dc9 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -8,19 +8,22 @@ trap_table: #define BAD_TRAP_VECTOR 0 .word bad_trap - .word bad_trap + .word pmp_trap .word illegal_insn_trap .word bad_trap .word misaligned_load_trap - .word bad_trap + .word pmp_trap .word misaligned_store_trap - .word bad_trap + .word pmp_trap .word bad_trap .word mcall_trap .word bad_trap .word bad_trap -#define TRAP_FROM_MACHINE_MODE_VECTOR 12 + .word bad_trap +#define TRAP_FROM_MACHINE_MODE_VECTOR 13 .word __trap_from_machine_mode + .word bad_trap + .word bad_trap .option norvc .section .text.init,"ax",@progbits diff --git a/machine/minit.c b/machine/minit.c index 7083b05..48366d7 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -35,10 +35,10 @@ static void delegate_traps() uintptr_t interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP; uintptr_t exceptions = (1U << CAUSE_MISALIGNED_FETCH) | - (1U << CAUSE_FAULT_FETCH) | + (1U << CAUSE_FETCH_PAGE_FAULT) | (1U << CAUSE_BREAKPOINT) | - (1U << CAUSE_FAULT_LOAD) | - (1U << CAUSE_FAULT_STORE) | + (1U << CAUSE_LOAD_PAGE_FAULT) | + (1U << CAUSE_STORE_PAGE_FAULT) | (1U << CAUSE_BREAKPOINT) | (1U << CAUSE_USER_ECALL); diff --git a/machine/mtrap.c b/machine/mtrap.c index 15859d1..6e85d26 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -167,6 +167,11 @@ void redirect_trap(uintptr_t epc, uintptr_t mstatus) return __redirect_trap(); } +void pmp_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) +{ + redirect_trap(mepc, read_csr(mstatus)); +} + static void machine_page_fault(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) { // MPRV=1 iff this trap occurred while emulating an instruction on behalf @@ -184,8 +189,11 @@ void trap_from_machine_mode(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) switch (mcause) { - case CAUSE_FAULT_LOAD: - case CAUSE_FAULT_STORE: + case CAUSE_LOAD_PAGE_FAULT: + case CAUSE_STORE_PAGE_FAULT: + case CAUSE_FETCH_ACCESS: + case CAUSE_LOAD_ACCESS: + case CAUSE_STORE_ACCESS: return machine_page_fault(regs, dummy, mepc); default: bad_trap(regs, dummy, mepc); diff --git a/pk/handlers.c b/pk/handlers.c index 1961852..b0eb76b 100644 --- a/pk/handlers.c +++ b/pk/handlers.c @@ -83,13 +83,13 @@ void handle_trap(trapframe_t* tf) const static trap_handler trap_handlers[] = { [CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch, - [CAUSE_FAULT_FETCH] = handle_fault_fetch, + [CAUSE_FETCH_PAGE_FAULT] = handle_fault_fetch, [CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction, [CAUSE_USER_ECALL] = handle_syscall, [CAUSE_BREAKPOINT] = handle_breakpoint, [CAUSE_MISALIGNED_STORE] = handle_misaligned_store, - [CAUSE_FAULT_LOAD] = handle_fault_load, - [CAUSE_FAULT_STORE] = handle_fault_store, + [CAUSE_LOAD_PAGE_FAULT] = handle_fault_load, + [CAUSE_STORE_PAGE_FAULT] = handle_fault_store, }; kassert(tf->cause < ARRAY_SIZE(trap_handlers) && trap_handlers[tf->cause]); -- cgit v1.1 From 9fa7b30887301f149f2497469a442d0887b21149 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 12:13:53 -0700 Subject: uart: add physical device driver --- machine/machine.mk.in | 2 ++ machine/minit.c | 5 +++++ machine/mtrap.c | 13 +++++++++++-- machine/uart.c | 38 ++++++++++++++++++++++++++++++++++++++ machine/uart.h | 21 +++++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 machine/uart.c create mode 100644 machine/uart.h diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 10d85b4..cdcb4a7 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -11,6 +11,7 @@ machine_hdrs = \ htif.h \ mcall.h \ mtrap.h \ + uart.h \ unprivileged_memory.h \ vm.h \ @@ -23,6 +24,7 @@ machine_c_srcs = \ muldiv_emulation.c \ fp_emulation.c \ fp_ldst.c \ + uart.c \ misaligned_ldst.c \ machine_asm_srcs = \ diff --git a/machine/minit.c b/machine/minit.c index 48366d7..6fc51c6 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -3,6 +3,7 @@ #include "vm.h" #include "fp_emulation.h" #include "fdt.h" +#include "uart.h" #include #include @@ -125,6 +126,10 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb) hart_init(); hls_init(0); // this might get called again from parse_config_string + // Confirm console as early as possible + query_uart(dtb); + printm("SBI console now online\n"); + query_mem(dtb); query_harts(dtb); query_clint(dtb); diff --git a/machine/mtrap.c b/machine/mtrap.c index 6e85d26..d7def4c 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -4,6 +4,7 @@ #include "atomic.h" #include "bits.h" #include "vm.h" +#include "uart.h" #include "unprivileged_memory.h" #include #include @@ -16,7 +17,11 @@ void __attribute__((noreturn)) bad_trap(uintptr_t* regs, uintptr_t dummy, uintpt static uintptr_t mcall_console_putchar(uint8_t ch) { - htif_console_putchar(ch); + if (uart) { + uart_putchar(ch); + } else { + htif_console_putchar(ch); + } return 0; } @@ -52,7 +57,11 @@ static void send_ipi(uintptr_t recipient, int event) static uintptr_t mcall_console_getchar() { - return htif_console_getchar(); + if (uart) { + return uart_getchar(); + } else { + return htif_console_getchar(); + } } static uintptr_t mcall_clear_ipi() diff --git a/machine/uart.c b/machine/uart.c new file mode 100644 index 0000000..28cc21c --- /dev/null +++ b/machine/uart.c @@ -0,0 +1,38 @@ +#include "uart.h" +#include "fdt.h" + +volatile uint32_t* uart; + +void uart_putchar(uint8_t ch) +{ +#ifdef __riscv_atomic + int32_t r; + do { + __asm__ __volatile__ ( + "amoor.w %0, %2, %1\n" + : "=r" (r), "+A" (uart[UART_REG_TXFIFO]) + : "r" (ch)); + } while (r < 0); +#else + volatile uint32_t *tx = uart + UART_REG_TXFIFO; + while ((int32_t)(*tx) < 0); + *tx = ch; +#endif +} + +int uart_getchar() +{ + int32_t ch = uart[UART_REG_RXFIFO]; + if (ch < 0) return -1; + return ch; +} + +void query_uart(uintptr_t dtb) +{ + uart = 0; // (void*)fdt_get_reg(dtb, "sifive,uart0"); + if (!uart) return; + + // Enable Rx/Tx channels + uart[UART_REG_TXCTRL] = UART_TXEN; + uart[UART_REG_RXCTRL] = UART_RXEN; +} diff --git a/machine/uart.h b/machine/uart.h new file mode 100644 index 0000000..51e951f --- /dev/null +++ b/machine/uart.h @@ -0,0 +1,21 @@ +#ifndef _RISCV_UART_H +#define _RISCV_UART_H + +#include + +extern volatile uint32_t* uart; + +#define UART_REG_TXFIFO 0 +#define UART_REG_RXFIFO 1 +#define UART_REG_TXCTRL 2 +#define UART_REG_RXCTRL 3 +#define UART_REG_DIV 4 + +#define UART_TXEN 0x1 +#define UART_RXEN 0x1 + +void uart_putchar(uint8_t ch); +int uart_getchar(); +void query_uart(uintptr_t dtb); + +#endif -- cgit v1.1 From cfe60c100d103fc1547e1462522f08d8e6979e0c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 14:10:51 -0700 Subject: fdt: rewrite parser using a single design pattern --- machine/fdt.c | 269 ++++++++++++++++++++++++++++++++++++---------------------- machine/fdt.h | 12 ++- 2 files changed, 176 insertions(+), 105 deletions(-) diff --git a/machine/fdt.c b/machine/fdt.c index a040e87..5257f76 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -13,48 +13,59 @@ static inline uint32_t bswap(uint32_t x) static const uint32_t *fdt_scan_helper( const uint32_t *lex, const char *strings, - const char *name, - struct fdt_scan_node *parent, - fdt_cb cb, - void *extra) + struct fdt_scan_node *node, + const struct fdt_cb *cb) { - struct fdt_scan_node node; + struct fdt_scan_node child; struct fdt_scan_prop prop; + int last = 0; - node.parent = parent; - node.base = lex; - node.name = name; - node.address_cells = 2; - node.size_cells = 1; - prop.node = &node; + child.parent = node; + child.address_cells = 2; + child.size_cells = 1; + prop.node = node; while (1) { switch (bswap(lex[0])) { - case FDT_BEGIN_NODE: { - const char *child_name = (const char *)(lex+1); - lex = fdt_scan_helper( - lex + 2 + strlen(child_name)/4, - strings, child_name, &node, cb, extra); + case FDT_NOP: { + lex += 1; break; } case FDT_PROP: { + assert (!last); prop.name = strings + bswap(lex[2]); prop.len = bswap(lex[1]); prop.value = lex + 3; - if (!strcmp(prop.name, "#address-cells")) { node.address_cells = bswap(lex[3]); } - if (!strcmp(prop.name, "#size-cells")) { node.size_cells = bswap(lex[3]); } + if (node && !strcmp(prop.name, "#address-cells")) { node->address_cells = bswap(lex[3]); } + if (node && !strcmp(prop.name, "#size-cells")) { node->size_cells = bswap(lex[3]); } lex += 3 + (prop.len+3)/4; - cb(&prop, extra); + cb->prop(&prop, cb->extra); break; } - case FDT_END_NODE: return lex + 1; - case FDT_NOP: lex += 1; break; - default: return lex; // FDT_END + case FDT_BEGIN_NODE: { + if (!last && node && cb->done) cb->done(node, cb->extra); + last = 1; + child.name = (const char *)(lex+1); + if (cb->open) cb->open(&child, cb->extra); + lex = fdt_scan_helper( + lex + 2 + strlen(child.name)/4, + strings, &child, cb); + if (cb->close) cb->close(&child, cb->extra); + break; + } + case FDT_END_NODE: { + if (!last && node && cb->done) cb->done(node, cb->extra); + return lex + 1; + } + default: { // FDT_END + if (!last && node && cb->done) cb->done(node, cb->extra); + return lex; + } } } } -void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra) +void fdt_scan(uintptr_t fdt, const struct fdt_cb *cb) { struct fdt_header *header = (struct fdt_header *)fdt; @@ -65,7 +76,7 @@ void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra) const char *strings = (const char *)(fdt + bswap(header->off_dt_strings)); const uint32_t *lex = (const uint32_t *)(fdt + bswap(header->off_dt_struct)); - fdt_scan_helper(lex, strings, "/", 0, cb, extra); + fdt_scan_helper(lex, strings, 0, cb); } uint32_t fdt_size(uintptr_t fdt) @@ -92,37 +103,71 @@ const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *v return value; } -static void find_mem(const struct fdt_scan_prop *prop, void *extra) +//////////////////////////////////////////// MEMORY SCAN ///////////////////////////////////////// + +struct mem_scan { + int memory; + const uint32_t *reg_value; + int reg_len; +}; + +static void mem_open(const struct fdt_scan_node *node, void *extra) { - const uint32_t **base = (const uint32_t **)extra; + struct mem_scan *scan = (struct mem_scan *)extra; + memset(scan, 0, sizeof(*scan)); +} + +static void mem_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct mem_scan *scan = (struct mem_scan *)extra; if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "memory")) { - *base = prop->node->base; - } else if (!strcmp(prop->name, "reg") && prop->node->base == *base) { - const uint32_t *value = prop->value; - const uint32_t *end = value + prop->len/4; - assert (prop->len % 4 == 0); - while (end - value > 0) { - uintptr_t base, size; - value = fdt_get_address(prop->node->parent, value, &base); - value = fdt_get_size (prop->node->parent, value, &size); - if (base == DRAM_BASE) { mem_size = size; } - } - assert (end == value); + scan->memory = 1; + } else if (!strcmp(prop->name, "reg")) { + scan->reg_value = prop->value; + scan->reg_len = prop->len; + } +} + +static void mem_done(const struct fdt_scan_node *node, void *extra) +{ + struct mem_scan *scan = (struct mem_scan *)extra; + const uint32_t *value = scan->reg_value; + const uint32_t *end = value + scan->reg_len/4; + uintptr_t self = (uintptr_t)mem_done; + + if (!scan->memory) return; + assert (scan->reg_value && scan->reg_len % 4 == 0); + + while (end - value > 0) { + uintptr_t base, size; + value = fdt_get_address(node->parent, value, &base); + value = fdt_get_size (node->parent, value, &size); + if (base <= self && self <= base + size) { mem_size = size; } } + assert (end == value); } void query_mem(uintptr_t fdt) { + struct fdt_cb cb; + struct mem_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = mem_open; + cb.prop = mem_prop; + cb.done = mem_done; + cb.extra = &scan; + mem_size = 0; - const uint32_t *base = 0; - fdt_scan(fdt, &find_mem, &base); + fdt_scan(fdt, &cb); assert (mem_size > 0); } +///////////////////////////////////////////// HART SCAN ////////////////////////////////////////// + static uint32_t hart_phandles[MAX_HARTS]; struct hart_scan { - const uint32_t *base; int cpu; int controller; int cells; @@ -130,36 +175,17 @@ struct hart_scan { uint32_t phandle; }; -static void init_hart(struct hart_scan *scan, const uint32_t *base) +static void hart_open(const struct fdt_scan_node *node, void *extra) { - scan->base = base; - scan->cpu = 0; - scan->controller = 0; + struct hart_scan *scan = (struct hart_scan *)extra; + memset(scan, 0, sizeof(*scan)); scan->cells = -1; scan->hart = -1; - scan->phandle = 0; } -static void done_hart(struct hart_scan *scan) -{ - if (scan->cpu) { - assert (scan->controller == 1); - assert (scan->cells == 1); - assert (scan->hart >= 0); - if (scan->hart < MAX_HARTS) { - hart_phandles[scan->hart] = scan->phandle; - if (scan->hart >= num_harts) num_harts = scan->hart + 1; - } - } -} - -static void count_harts(const struct fdt_scan_prop *prop, void *extra) +static void hart_prop(const struct fdt_scan_prop *prop, void *extra) { struct hart_scan *scan = (struct hart_scan *)extra; - if (prop->node->base != scan->base) { - done_hart(scan); - init_hart(scan, prop->node->base); - } if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "cpu")) { scan->cpu = 1; } else if (!strcmp(prop->name, "interrupt-controller")) { @@ -175,72 +201,111 @@ static void count_harts(const struct fdt_scan_prop *prop, void *extra) } } +static void hart_done(const struct fdt_scan_node *node, void *extra) +{ + struct hart_scan *scan = (struct hart_scan *)extra; + + if (!scan->cpu) return; + assert (scan->controller == 1); + assert (scan->cells == 1); + assert (scan->hart >= 0); + + if (scan->hart < MAX_HARTS) { + hart_phandles[scan->hart] = scan->phandle; + if (scan->hart >= num_harts) num_harts = scan->hart + 1; + } +} + void query_harts(uintptr_t fdt) { + struct fdt_cb cb; struct hart_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = hart_open; + cb.prop = hart_prop; + cb.done = hart_done; + cb.extra = &scan; + num_harts = 0; - init_hart(&scan, 0); - fdt_scan(fdt, &count_harts, &scan); - done_hart(&scan); + fdt_scan(fdt, &cb); assert (num_harts > 0); } +///////////////////////////////////////////// CLINT SCAN ///////////////////////////////////////// + struct clint_scan { - const uint32_t *base; - uintptr_t address; + int compat; + uintptr_t reg; + const uint32_t *int_value; + int int_len; + int done; }; -static void find_clint_base(const struct fdt_scan_prop *prop, void *extra) +static void clint_open(const struct fdt_scan_node *node, void *extra) { struct clint_scan *scan = (struct clint_scan *)extra; - if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,clint0")) - scan->base = prop->node->base; + scan->compat = 0; + scan->reg = 0; + scan->int_value = 0; } -static void find_clint_reg(const struct fdt_scan_prop *prop, void *extra) +static void clint_prop(const struct fdt_scan_prop *prop, void *extra) { struct clint_scan *scan = (struct clint_scan *)extra; - if (!strcmp(prop->name, "reg") && scan->base == prop->node->base) - fdt_get_address(prop->node->parent, prop->value, &scan->address); + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,clint0")) { + scan->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + fdt_get_address(prop->node->parent, prop->value, &scan->reg); + } else if (!strcmp(prop->name, "interrupts-extended")) { + scan->int_value = prop->value; + scan->int_len = prop->len; + } } -static void setup_clint(const struct fdt_scan_prop *prop, void *extra) +static void clint_done(const struct fdt_scan_node *node, void *extra) { struct clint_scan *scan = (struct clint_scan *)extra; - if (!strcmp(prop->name, "interrupts-extended") && scan->base == prop->node->base) { - const uint32_t *value = prop->value; - const uint32_t *end = value + prop->len/4; - assert (prop->len % 16 == 0); - for (int index = 0; end - value > 0; ++index) { - uint32_t phandle = bswap(value[0]); - int hart; - for (hart = 0; hart < MAX_HARTS; ++hart) - if (hart_phandles[hart] == phandle) - break; - if (hart < MAX_HARTS) { - hls_t *hls = hls_init(hart); - hls->ipi = (void*)(scan->address + index * 4); - hls->timecmp = (void*)(scan->address + 0x4000 + (index * 8)); - *hls->ipi = 1; // wakeup the hart - } - value += 4; + const uint32_t *value = scan->int_value; + const uint32_t *end = value + scan->int_len/4; + + if (!scan->compat) return; + assert (scan->reg != 0); + assert (scan->int_value && scan->int_len % 16 == 0); + assert (!scan->done); // only one clint + + scan->done = 1; + mtime = (void*)(scan->reg + 0xbff8); + + for (int index = 0; end - value > 0; ++index) { + uint32_t phandle = bswap(value[0]); + int hart; + for (hart = 0; hart < MAX_HARTS; ++hart) + if (hart_phandles[hart] == phandle) + break; + if (hart < MAX_HARTS) { + hls_t *hls = hls_init(hart); + hls->ipi = (void*)(scan->reg + index * 4); + hls->timecmp = (void*)(scan->reg + 0x4000 + (index * 8)); + *hls->ipi = 1; // wakeup the hart } + value += 4; } } void query_clint(uintptr_t fdt) { + struct fdt_cb cb; struct clint_scan scan; - scan.base = 0; - scan.address = 0; - - fdt_scan(fdt, &find_clint_base, &scan); - assert (scan.base != 0); - fdt_scan(fdt, &find_clint_reg, &scan); - assert (scan.address != 0); + memset(&cb, 0, sizeof(cb)); + cb.open = clint_open; + cb.prop = clint_prop; + cb.done = clint_done; + cb.extra = &scan; - mtime = (void*)(scan.address + 0xbff8); - fdt_scan(fdt, &setup_clint, &scan); + scan.done = 0; + fdt_scan(fdt, &cb); + assert (scan.done); } diff --git a/machine/fdt.h b/machine/fdt.h index 8b01bc8..ee17007 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -25,7 +25,6 @@ struct fdt_header { struct fdt_scan_node { const struct fdt_scan_node *parent; - const uint32_t *base; // token that began the node const char *name; int address_cells; int size_cells; @@ -38,9 +37,16 @@ struct fdt_scan_prop { int len; // in bytes of value }; +struct fdt_cb { + void (*open)(const struct fdt_scan_node *node, void *extra); + void (*prop)(const struct fdt_scan_prop *prop, void *extra); + void (*done)(const struct fdt_scan_node *node, void *extra); // last property was seen + void (*close)(const struct fdt_scan_node *node, void *extra); + void *extra; +}; + // Scan the contents of FDT -typedef void (*fdt_cb)(const struct fdt_scan_prop *prop, void *extra); -void fdt_scan(uintptr_t fdt, fdt_cb cb, void *extra); +void fdt_scan(uintptr_t fdt, const struct fdt_cb *cb); uint32_t fdt_size(uintptr_t fdt); // Extract fields -- cgit v1.1 From b394a92597a5ee766dca42478e12492aba399543 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 14:16:05 -0700 Subject: uart: find it using fdt --- machine/uart.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/machine/uart.c b/machine/uart.c index 28cc21c..a55e27e 100644 --- a/machine/uart.c +++ b/machine/uart.c @@ -1,3 +1,4 @@ +#include #include "uart.h" #include "fdt.h" @@ -27,12 +28,49 @@ int uart_getchar() return ch; } -void query_uart(uintptr_t dtb) +struct uart_scan { - uart = 0; // (void*)fdt_get_reg(dtb, "sifive,uart0"); - if (!uart) return; + int compat; + uintptr_t reg; +}; + +static void uart_open(const struct fdt_scan_node *node, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + memset(scan, 0, sizeof(*scan)); +} + +static void uart_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "sifive,uart0")) { + scan->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + fdt_get_address(prop->node->parent, prop->value, &scan->reg); + } +} + +static void uart_done(const struct fdt_scan_node *node, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + if (!scan->compat || !scan->reg || uart) return; // Enable Rx/Tx channels + uart = (void*)scan->reg; uart[UART_REG_TXCTRL] = UART_TXEN; uart[UART_REG_RXCTRL] = UART_RXEN; } + +void query_uart(uintptr_t fdt) +{ + struct fdt_cb cb; + struct uart_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = uart_open; + cb.prop = uart_prop; + cb.done = uart_done; + cb.extra = &scan; + + fdt_scan(fdt, &cb); +} -- cgit v1.1 From 75f1854cd9d665dd6a7ed3bff7556b98e5a4a26c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 20:46:05 -0700 Subject: plic: discovered via fdt --- machine/fdt.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ machine/fdt.h | 1 + machine/minit.c | 1 + 3 files changed, 103 insertions(+) diff --git a/machine/fdt.c b/machine/fdt.c index 5257f76..b0ba260 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -309,3 +309,104 @@ void query_clint(uintptr_t fdt) fdt_scan(fdt, &cb); assert (scan.done); } + +///////////////////////////////////////////// PLIC SCAN ///////////////////////////////////////// + +struct plic_scan +{ + int compat; + uintptr_t reg; + const uint32_t *int_value; + int int_len; + int done; + int ndev; +}; + +static void plic_open(const struct fdt_scan_node *node, void *extra) +{ + struct plic_scan *scan = (struct plic_scan *)extra; + scan->compat = 0; + scan->reg = 0; + scan->int_value = 0; +} + +static void plic_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct plic_scan *scan = (struct plic_scan *)extra; + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,plic0")) { + scan->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + fdt_get_address(prop->node->parent, prop->value, &scan->reg); + } else if (!strcmp(prop->name, "interrupts-extended")) { + scan->int_value = prop->value; + scan->int_len = prop->len; + } else if (!strcmp(prop->name, "riscv,ndev")) { + scan->ndev = bswap(prop->value[0]); + } +} + +#define HART_BASE 0x200000 +#define HART_SIZE 0x1000 +#define ENABLE_BASE 0x2000 +#define ENABLE_SIZE 0x80 + +static void plic_done(const struct fdt_scan_node *node, void *extra) +{ + struct plic_scan *scan = (struct plic_scan *)extra; + const uint32_t *value = scan->int_value; + const uint32_t *end = value + scan->int_len/4; + + if (!scan->compat) return; + assert (scan->reg != 0); + assert (scan->int_value && scan->int_len % 8 == 0); + assert (scan->ndev >= 0 && scan->ndev < 1024); + assert (!scan->done); // only one plic + + scan->done = 1; + plic_priorities = (uint32_t*)scan->reg; + plic_ndevs = scan->ndev; + + for (int index = 0; end - value > 0; ++index) { + uint32_t phandle = bswap(value[0]); + uint32_t cpu_int = bswap(value[1]); + int hart; + for (hart = 0; hart < MAX_HARTS; ++hart) + if (hart_phandles[hart] == phandle) + break; + if (hart < MAX_HARTS) { + hls_t *hls = OTHER_HLS(hart); + if (cpu_int == IRQ_M_EXT) { + hls->plic_m_ie = (uintptr_t*)(scan->reg + ENABLE_BASE + ENABLE_SIZE * index); + hls->plic_m_thresh = (uint32_t*) (scan->reg + HART_BASE + HART_SIZE * index); + } else if (cpu_int == IRQ_S_EXT) { + hls->plic_s_ie = (uintptr_t*)(scan->reg + ENABLE_BASE + ENABLE_SIZE * index); + hls->plic_s_thresh = (uint32_t*) (scan->reg + HART_BASE + HART_SIZE * index); + } else { + printm("PLIC wired hart %d to wrong interrupt %d", hart, cpu_int); + } + } + value += 2; + } +#if 0 + printm("PLIC: prio %x devs %d\n", (uint32_t)(uintptr_t)plic_priorities, plic_ndevs); + for (int i = 0; i < MAX_HARTS; ++i) { + hls_t *hls = OTHER_HLS(i); + printm("CPU %d: %x %x %x %x\n", i, (uint32_t)(uintptr_t)hls->plic_m_ie, (uint32_t)(uintptr_t)hls->plic_m_thresh, (uint32_t)(uintptr_t)hls->plic_s_ie, (uint32_t)(uintptr_t)hls->plic_s_thresh); + } +#endif +} + +void query_plic(uintptr_t fdt) +{ + struct fdt_cb cb; + struct plic_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = plic_open; + cb.prop = plic_prop; + cb.done = plic_done; + cb.extra = &scan; + + scan.done = 0; + fdt_scan(fdt, &cb); +} diff --git a/machine/fdt.h b/machine/fdt.h index ee17007..41c1b52 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -56,6 +56,7 @@ const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *b // Setup memory+clint+plic void query_mem(uintptr_t fdt); void query_harts(uintptr_t fdt); +void query_plic(uintptr_t fdt); void query_clint(uintptr_t fdt); #endif diff --git a/machine/minit.c b/machine/minit.c index 6fc51c6..c584e9d 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -132,6 +132,7 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb) query_mem(dtb); query_harts(dtb); + query_plic(dtb); query_clint(dtb); plic_init(); -- cgit v1.1 From 6f407a8d549620be5cfbdaa0b9fda967d633d736 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 29 Mar 2017 16:27:11 -0700 Subject: Attempt to read instruction from mbadaddr --- machine/emulation.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/machine/emulation.c b/machine/emulation.c index 25b39af..b5d3410 100644 --- a/machine/emulation.c +++ b/machine/emulation.c @@ -128,11 +128,15 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) " .word truly_illegal_insn\n" " .popsection"); - uintptr_t mstatus; - insn_t insn = get_insn(mepc, &mstatus); - - if ((insn & 3) != 3) - return emulate_rvc(regs, mcause, mepc, mstatus, insn); + uintptr_t mstatus = read_csr(mstatus); + insn_t insn = read_csr(mbadaddr); + + if (unlikely((insn & 3) != 3)) { + if (insn == 0) + insn = get_insn(mepc, &mstatus); + if ((insn & 3) != 3) + return emulate_rvc(regs, mcause, mepc, mstatus, insn); + } write_csr(mepc, mepc + 4); -- cgit v1.1 From 52d46dd684ecb8c2fabda82b5246964d69dc867c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 30 Mar 2017 00:16:40 -0700 Subject: fdt: look for the phandle of a cpu's nested interrupt controller --- machine/fdt.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/machine/fdt.c b/machine/fdt.c index b0ba260..60b65c7 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -168,28 +168,34 @@ void query_mem(uintptr_t fdt) static uint32_t hart_phandles[MAX_HARTS]; struct hart_scan { - int cpu; - int controller; - int cells; + const struct fdt_scan_node *cpu; int hart; + const struct fdt_scan_node *controller; + int cells; uint32_t phandle; }; static void hart_open(const struct fdt_scan_node *node, void *extra) { struct hart_scan *scan = (struct hart_scan *)extra; - memset(scan, 0, sizeof(*scan)); - scan->cells = -1; - scan->hart = -1; + if (!scan->cpu) { + scan->hart = -1; + } + if (!scan->controller) { + scan->cells = 0; + scan->phandle = 0; + } } static void hart_prop(const struct fdt_scan_prop *prop, void *extra) { struct hart_scan *scan = (struct hart_scan *)extra; if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "cpu")) { - scan->cpu = 1; + assert (!scan->cpu); + scan->cpu = prop->node; } else if (!strcmp(prop->name, "interrupt-controller")) { - scan->controller = 1; + assert (!scan->controller); + scan->controller = prop->node; } else if (!strcmp(prop->name, "#interrupt-cells")) { scan->cells = bswap(prop->value[0]); } else if (!strcmp(prop->name, "phandle")) { @@ -205,26 +211,39 @@ static void hart_done(const struct fdt_scan_node *node, void *extra) { struct hart_scan *scan = (struct hart_scan *)extra; - if (!scan->cpu) return; - assert (scan->controller == 1); - assert (scan->cells == 1); - assert (scan->hart >= 0); + if (scan->cpu == node) { + assert (scan->hart >= 0); + } + + if (scan->controller == node && scan->cpu) { + assert (scan->phandle > 0); + assert (scan->cells == 1); - if (scan->hart < MAX_HARTS) { - hart_phandles[scan->hart] = scan->phandle; - if (scan->hart >= num_harts) num_harts = scan->hart + 1; + if (scan->hart < MAX_HARTS) { + hart_phandles[scan->hart] = scan->phandle; + if (scan->hart >= num_harts) num_harts = scan->hart + 1; + } } } +static void hart_close(const struct fdt_scan_node *node, void *extra) +{ + struct hart_scan *scan = (struct hart_scan *)extra; + if (scan->cpu == node) scan->cpu = 0; + if (scan->controller == node) scan->controller = 0; +} + void query_harts(uintptr_t fdt) { struct fdt_cb cb; struct hart_scan scan; memset(&cb, 0, sizeof(cb)); + memset(&scan, 0, sizeof(scan)); cb.open = hart_open; cb.prop = hart_prop; cb.done = hart_done; + cb.close= hart_close; cb.extra = &scan; num_harts = 0; -- cgit v1.1 From 078ea399c6c1f2d6e8461559bf8cc1ba34ca89b6 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 30 Mar 2017 00:21:52 -0700 Subject: New PMP encoding --- machine/encoding.h | 11 ++++++----- machine/minit.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index b07d976..55f8461 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -127,13 +127,14 @@ #define PMP_R 0x01 #define PMP_W 0x02 #define PMP_X 0x04 -#define PMP_M 0x08 -#define PMP_NAPOT 0x10 -#define PMP_TOR 0x20 -#define PMP_EN 0x40 -#define PMP_LOCK 0x80 +#define PMP_A 0x18 +#define PMP_L 0x80 #define PMP_SHIFT 2 +#define PMP_TOR 0x08 +#define PMP_NA4 0x10 +#define PMP_NAPOT 0x18 + #define IRQ_S_SOFT 1 #define IRQ_H_SOFT 2 #define IRQ_M_SOFT 3 diff --git a/machine/minit.c b/machine/minit.c index c584e9d..68c29ad 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -153,7 +153,7 @@ void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1 { // Set up a PMP to permit access to all of memory. // Ignore the illegal-instruction trap if PMPs aren't supported. - uintptr_t pmpc = PMP_EN | PMP_NAPOT | PMP_M | PMP_R | PMP_W | PMP_X; + uintptr_t pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X; asm volatile ("la t0, 1f\n\t" "csrrw t0, mtvec, t0\n\t" "csrw pmpaddr0, %1\n\t" -- cgit v1.1 From 733fae9216f27b3d63c16f8608c3a5e2c6317afc Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 31 Mar 2017 17:51:51 -0700 Subject: clint: move hart wakeup till after all FDT parsing The clint was wiping out information discovered by the plic. Initialize hart stacks as they are discovered. Then fill in clint+plic info Then wake the harts. --- machine/fdt.c | 10 ++++++---- machine/fdt.h | 3 +++ machine/minit.c | 13 +++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/machine/fdt.c b/machine/fdt.c index 60b65c7..d388d04 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -166,6 +166,7 @@ void query_mem(uintptr_t fdt) ///////////////////////////////////////////// HART SCAN ////////////////////////////////////////// static uint32_t hart_phandles[MAX_HARTS]; +uint64_t hart_mask; struct hart_scan { const struct fdt_scan_node *cpu; @@ -221,7 +222,9 @@ static void hart_done(const struct fdt_scan_node *node, void *extra) if (scan->hart < MAX_HARTS) { hart_phandles[scan->hart] = scan->phandle; + hart_mask |= 1 << scan->hart; if (scan->hart >= num_harts) num_harts = scan->hart + 1; + hls_init(scan->hart); } } } @@ -304,10 +307,9 @@ static void clint_done(const struct fdt_scan_node *node, void *extra) if (hart_phandles[hart] == phandle) break; if (hart < MAX_HARTS) { - hls_t *hls = hls_init(hart); + hls_t *hls = OTHER_HLS(hart); hls->ipi = (void*)(scan->reg + index * 4); hls->timecmp = (void*)(scan->reg + 0x4000 + (index * 8)); - *hls->ipi = 1; // wakeup the hart } value += 4; } @@ -407,10 +409,10 @@ static void plic_done(const struct fdt_scan_node *node, void *extra) value += 2; } #if 0 - printm("PLIC: prio %x devs %d\n", (uint32_t)(uintptr_t)plic_priorities, plic_ndevs); + printm("PLIC: prio %x devs %d\r\n", (uint32_t)(uintptr_t)plic_priorities, plic_ndevs); for (int i = 0; i < MAX_HARTS; ++i) { hls_t *hls = OTHER_HLS(i); - printm("CPU %d: %x %x %x %x\n", i, (uint32_t)(uintptr_t)hls->plic_m_ie, (uint32_t)(uintptr_t)hls->plic_m_thresh, (uint32_t)(uintptr_t)hls->plic_s_ie, (uint32_t)(uintptr_t)hls->plic_s_thresh); + printm("CPU %d: %x %x %x %x\r\n", i, (uint32_t)(uintptr_t)hls->plic_m_ie, (uint32_t)(uintptr_t)hls->plic_m_thresh, (uint32_t)(uintptr_t)hls->plic_s_ie, (uint32_t)(uintptr_t)hls->plic_s_thresh); } #endif } diff --git a/machine/fdt.h b/machine/fdt.h index 41c1b52..7f44db6 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -59,4 +59,7 @@ void query_harts(uintptr_t fdt); void query_plic(uintptr_t fdt); void query_clint(uintptr_t fdt); +// The hartids of available harts +extern uint64_t hart_mask; + #endif diff --git a/machine/minit.c b/machine/minit.c index 68c29ad..cfe1c43 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -121,6 +121,13 @@ static void hart_plic_init() *HLS()->plic_s_thresh = 0; } +static void wake_harts() +{ + for (int hart = 0; hart < MAX_HARTS; ++hart) + if (((hart_mask >> hart) & 1)) + *OTHER_HLS(hart)->ipi = 1; // wakeup the hart +} + void init_first_hart(uintptr_t hartid, uintptr_t dtb) { hart_init(); @@ -128,12 +135,14 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb) // Confirm console as early as possible query_uart(dtb); - printm("SBI console now online\n"); + printm("SBI console now online\r\n"); query_mem(dtb); query_harts(dtb); - query_plic(dtb); query_clint(dtb); + query_plic(dtb); + + wake_harts(); plic_init(); hart_plic_init(); -- cgit v1.1 From d1200e3a54e9328d37833a4a155c6549c03a654f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 4 Apr 2017 00:24:38 -0700 Subject: Remove SBI console printm to speed up PK simulation --- machine/minit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/machine/minit.c b/machine/minit.c index cfe1c43..baf45a5 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -135,7 +135,6 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb) // Confirm console as early as possible query_uart(dtb); - printm("SBI console now online\r\n"); query_mem(dtb); query_harts(dtb); -- cgit v1.1 From cd558016be4fdc99055814bd1adcfc2962b425c0 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 5 Apr 2017 14:53:01 -0700 Subject: fdt: support redaction --- machine/fdt.c | 18 +++++++++++------- machine/fdt.h | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/machine/fdt.c b/machine/fdt.c index d388d04..bd8da74 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -10,8 +10,8 @@ static inline uint32_t bswap(uint32_t x) return z; } -static const uint32_t *fdt_scan_helper( - const uint32_t *lex, +static uint32_t *fdt_scan_helper( + uint32_t *lex, const char *strings, struct fdt_scan_node *node, const struct fdt_cb *cb) @@ -43,14 +43,17 @@ static const uint32_t *fdt_scan_helper( break; } case FDT_BEGIN_NODE: { + uint32_t *lex_next; if (!last && node && cb->done) cb->done(node, cb->extra); last = 1; child.name = (const char *)(lex+1); if (cb->open) cb->open(&child, cb->extra); - lex = fdt_scan_helper( + lex_next = fdt_scan_helper( lex + 2 + strlen(child.name)/4, strings, &child, cb); - if (cb->close) cb->close(&child, cb->extra); + if (cb->close && cb->close(&child, cb->extra) == -1) + while (lex != lex_next) *lex++ = bswap(FDT_NOP); + lex = lex_next; break; } case FDT_END_NODE: { @@ -74,7 +77,7 @@ void fdt_scan(uintptr_t fdt, const struct fdt_cb *cb) bswap(header->last_comp_version) > FDT_VERSION) return; const char *strings = (const char *)(fdt + bswap(header->off_dt_strings)); - const uint32_t *lex = (const uint32_t *)(fdt + bswap(header->off_dt_struct)); + uint32_t *lex = (uint32_t *)(fdt + bswap(header->off_dt_struct)); fdt_scan_helper(lex, strings, 0, cb); } @@ -229,11 +232,12 @@ static void hart_done(const struct fdt_scan_node *node, void *extra) } } -static void hart_close(const struct fdt_scan_node *node, void *extra) +static int hart_close(const struct fdt_scan_node *node, void *extra) { struct hart_scan *scan = (struct hart_scan *)extra; if (scan->cpu == node) scan->cpu = 0; if (scan->controller == node) scan->controller = 0; + return 0; } void query_harts(uintptr_t fdt) @@ -337,7 +341,7 @@ struct plic_scan { int compat; uintptr_t reg; - const uint32_t *int_value; + uint32_t *int_value; int int_len; int done; int ndev; diff --git a/machine/fdt.h b/machine/fdt.h index 7f44db6..235bb2e 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -33,7 +33,7 @@ struct fdt_scan_node { struct fdt_scan_prop { const struct fdt_scan_node *node; const char *name; - const uint32_t *value; + uint32_t *value; int len; // in bytes of value }; @@ -41,7 +41,7 @@ struct fdt_cb { void (*open)(const struct fdt_scan_node *node, void *extra); void (*prop)(const struct fdt_scan_prop *prop, void *extra); void (*done)(const struct fdt_scan_node *node, void *extra); // last property was seen - void (*close)(const struct fdt_scan_node *node, void *extra); + int (*close)(const struct fdt_scan_node *node, void *extra); // -1 => delete the node + children void *extra; }; -- cgit v1.1 From 91636ac4639a7993c485288d34f1c8e22b1980b4 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 5 Apr 2017 16:22:47 -0700 Subject: fdt: redact clint, plic, and debug hardware --- bbl/bbl.c | 6 +++ machine/fdt.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- machine/fdt.h | 6 +++ 3 files changed, 166 insertions(+), 2 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 300182c..44802c1 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -21,6 +21,12 @@ static void filter_dtb(uintptr_t source) uintptr_t dest = dtb_output(); uint32_t size = fdt_size(source); memcpy((void*)dest, (void*)source, size); + + // Remove information from the chained FDT + // filter_harts(dest, 0x2); + filter_plic(dest); + filter_compat(dest, "riscv,clint0"); + filter_compat(dest, "riscv,debug-013"); } void boot_other_hart(uintptr_t dtb) diff --git a/machine/fdt.c b/machine/fdt.c index bd8da74..908b2ea 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -106,6 +106,19 @@ const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *v return value; } +int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str) +{ + const char *list = (const char *)prop->value; + const char *end = list + prop->len; + int index = 0; + while (end - list > 0) { + if (!strcmp(list, str)) return index; + ++index; + list += strlen(list) + 1; + } + return -1; +} + //////////////////////////////////////////// MEMORY SCAN ///////////////////////////////////////// struct mem_scan { @@ -280,7 +293,7 @@ static void clint_open(const struct fdt_scan_node *node, void *extra) static void clint_prop(const struct fdt_scan_prop *prop, void *extra) { struct clint_scan *scan = (struct clint_scan *)extra; - if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,clint0")) { + if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, "riscv,clint0") >= 0) { scan->compat = 1; } else if (!strcmp(prop->name, "reg")) { fdt_get_address(prop->node->parent, prop->value, &scan->reg); @@ -358,7 +371,7 @@ static void plic_open(const struct fdt_scan_node *node, void *extra) static void plic_prop(const struct fdt_scan_prop *prop, void *extra) { struct plic_scan *scan = (struct plic_scan *)extra; - if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,plic0")) { + if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, "riscv,plic0") >= 0) { scan->compat = 1; } else if (!strcmp(prop->name, "reg")) { fdt_get_address(prop->node->parent, prop->value, &scan->reg); @@ -435,3 +448,142 @@ void query_plic(uintptr_t fdt) scan.done = 0; fdt_scan(fdt, &cb); } + +static void plic_redact(const struct fdt_scan_node *node, void *extra) +{ + struct plic_scan *scan = (struct plic_scan *)extra; + uint32_t *value = scan->int_value; + uint32_t *end = value + scan->int_len/4; + + if (!scan->compat) return; + scan->done = 1; + + while (end - value > 0) { + if (bswap(value[1]) == IRQ_M_EXT) value[1] = bswap(-1); + value += 2; + } +} + +void filter_plic(uintptr_t fdt) +{ + struct fdt_cb cb; + struct plic_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = plic_open; + cb.prop = plic_prop; + cb.done = plic_redact; + cb.extra = &scan; + + scan.done = 0; + fdt_scan(fdt, &cb); +} + +//////////////////////////////////////////// COMPAT SCAN //////////////////////////////////////// + +struct compat_scan +{ + const char *compat; + int depth; + int kill; +}; + +static void compat_open(const struct fdt_scan_node *node, void *extra) +{ + struct compat_scan *scan = (struct compat_scan *)extra; + ++scan->depth; +} + +static void compat_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct compat_scan *scan = (struct compat_scan *)extra; + if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, scan->compat) >= 0) + if (scan->depth < scan->kill) + scan->kill = scan->depth; +} + +static int compat_close(const struct fdt_scan_node *node, void *extra) +{ + struct compat_scan *scan = (struct compat_scan *)extra; + if (scan->kill == scan->depth--) { + scan->kill = 999; + return -1; + } else { + return 0; + } +} + +void filter_compat(uintptr_t fdt, const char *compat) +{ + struct fdt_cb cb; + struct compat_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = compat_open; + cb.prop = compat_prop; + cb.close = compat_close; + cb.extra = &scan; + + scan.compat = compat; + scan.depth = 0; + scan.kill = 999; + fdt_scan(fdt, &cb); +} + +//////////////////////////////////////////// HART FILTER //////////////////////////////////////// + +struct hart_filter { + int compat; + int hart; + char *status; + unsigned long mask; +}; + +static void hart_filter_open(const struct fdt_scan_node *node, void *extra) +{ + struct hart_filter *filter = (struct hart_filter *)extra; + filter->status = 0; + filter->compat = 0; + filter->hart = -1; +} + +static void hart_filter_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct hart_filter *filter = (struct hart_filter *)extra; + if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "cpu")) { + filter->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + uintptr_t reg; + fdt_get_address(prop->node->parent, prop->value, ®); + filter->hart = reg; + } else if (!strcmp(prop->name, "status")) { + filter->status = (char*)prop->value; + } +} + +static void hart_filter_done(const struct fdt_scan_node *node, void *extra) +{ + struct hart_filter *filter = (struct hart_filter *)extra; + + if (!filter->compat) return; + assert (filter->status); + assert (filter->hart >= 0); + + if (((filter->mask >> filter->hart) & 1)) + strcpy(filter->status, "masked"); +} + +void filter_harts(uintptr_t fdt, unsigned long hart_mask) +{ + struct fdt_cb cb; + struct hart_filter filter; + + memset(&cb, 0, sizeof(cb)); + cb.open = hart_filter_open; + cb.prop = hart_filter_prop; + cb.done = hart_filter_done; + cb.extra = &filter; + + filter.mask = hart_mask; + fdt_scan(fdt, &cb); +} diff --git a/machine/fdt.h b/machine/fdt.h index 235bb2e..0581e95 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -52,6 +52,7 @@ uint32_t fdt_size(uintptr_t fdt); // Extract fields const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); +int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str); // -1 if not found // Setup memory+clint+plic void query_mem(uintptr_t fdt); @@ -59,6 +60,11 @@ void query_harts(uintptr_t fdt); void query_plic(uintptr_t fdt); void query_clint(uintptr_t fdt); +// Remove information from FDT +void filter_harts(uintptr_t fdt, unsigned long hart_mask); +void filter_plic(uintptr_t fdt); +void filter_compat(uintptr_t fdt, const char *compat); + // The hartids of available harts extern uint64_t hart_mask; -- cgit v1.1 From 8b4421bacba28f97da2ddeb6a6fba9e184e91bee Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 5 Apr 2017 16:27:19 -0700 Subject: bbl: prevent named cores from booting --- bbl/bbl.c | 2 +- machine/mentry.S | 14 +++++++++++++- machine/minit.c | 2 +- machine/mtrap.c | 1 + machine/mtrap.h | 3 +++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 44802c1..f64b2e7 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -23,7 +23,7 @@ static void filter_dtb(uintptr_t source) memcpy((void*)dest, (void*)source, size); // Remove information from the chained FDT - // filter_harts(dest, 0x2); + filter_harts(dest, HART_MASK); filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); diff --git a/machine/mentry.S b/machine/mentry.S index 9575dc9..62a850d 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -257,7 +257,11 @@ do_reset: slli a2, a3, RISCV_PGSHIFT add sp, sp, a2 - beqz a3, init_first_hart + # Boot on the first unmasked hart + li a4, (~HART_MASK & (HART_MASK+1)) + srl a4, a4, a3 + andi a4, a4, 1 + bnez a4, init_first_hart # set MSIE bit to receive IPI li a2, MIP_MSIP @@ -267,6 +271,14 @@ do_reset: #if MAX_HARTS > 1 # wait for an IPI to signal that it's safe to boot wfi + + # masked harts never start + li a4, HART_MASK + srl a4, a4, a3 + andi a4, a4, 1 + bnez a4, .LmultiHart + + # only start if mip is set csrr a2, mip andi a2, a2, MIP_MSIP beqz a2, .LmultiHart diff --git a/machine/minit.c b/machine/minit.c index baf45a5..94a1491 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -124,7 +124,7 @@ static void hart_plic_init() static void wake_harts() { for (int hart = 0; hart < MAX_HARTS; ++hart) - if (((hart_mask >> hart) & 1)) + if ((((~HART_MASK & hart_mask) >> hart) & 1)) *OTHER_HLS(hart)->ipi = 1; // wakeup the hart } diff --git a/machine/mtrap.c b/machine/mtrap.c index d7def4c..be264f3 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -50,6 +50,7 @@ void printm(const char* s, ...) static void send_ipi(uintptr_t recipient, int event) { + if (((HART_MASK >> recipient) & 1)) return; atomic_or(&OTHER_HLS(recipient)->mipi_pending, event); mb(); *OTHER_HLS(recipient)->ipi = 1; diff --git a/machine/mtrap.h b/machine/mtrap.h index e8dfc49..1437b11 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -9,6 +9,9 @@ # define MAX_HARTS 1 #endif +// These harts will be prevented from booting beyond bbl +#define HART_MASK 0x0UL + #ifndef __ASSEMBLER__ #include -- cgit v1.1 From 31eab7e4dd7856d48ee352fc941490257840a87c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 5 Apr 2017 17:42:26 -0700 Subject: fdt: update the status length when masking cpus --- machine/fdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/machine/fdt.c b/machine/fdt.c index 908b2ea..34ff87b 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -569,8 +569,11 @@ static void hart_filter_done(const struct fdt_scan_node *node, void *extra) assert (filter->status); assert (filter->hart >= 0); - if (((filter->mask >> filter->hart) & 1)) + if (((filter->mask >> filter->hart) & 1) && !strcmp(filter->status, "okay")) { strcpy(filter->status, "masked"); + uint32_t *len = (uint32_t*)filter->status; + len[-2] = bswap(strlen("masked")+1); + } } void filter_harts(uintptr_t fdt, unsigned long hart_mask) -- cgit v1.1 From dce2b7dd8ede804f54f54fafabd82b24c1a0be62 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 5 Apr 2017 17:39:58 -0700 Subject: Rename HART_MASK to DISABLED_HART_MASK to clarify polarity --- bbl/bbl.c | 2 +- machine/mentry.S | 4 ++-- machine/minit.c | 2 +- machine/mtrap.c | 2 +- machine/mtrap.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index f64b2e7..5ee95ad 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -23,7 +23,7 @@ static void filter_dtb(uintptr_t source) memcpy((void*)dest, (void*)source, size); // Remove information from the chained FDT - filter_harts(dest, HART_MASK); + filter_harts(dest, DISABLED_HART_MASK); filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); diff --git a/machine/mentry.S b/machine/mentry.S index 62a850d..64fb507 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -258,7 +258,7 @@ do_reset: add sp, sp, a2 # Boot on the first unmasked hart - li a4, (~HART_MASK & (HART_MASK+1)) + li a4, (~DISABLED_HART_MASK & (DISABLED_HART_MASK+1)) srl a4, a4, a3 andi a4, a4, 1 bnez a4, init_first_hart @@ -273,7 +273,7 @@ do_reset: wfi # masked harts never start - li a4, HART_MASK + li a4, DISABLED_HART_MASK srl a4, a4, a3 andi a4, a4, 1 bnez a4, .LmultiHart diff --git a/machine/minit.c b/machine/minit.c index 94a1491..0052eb7 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -124,7 +124,7 @@ static void hart_plic_init() static void wake_harts() { for (int hart = 0; hart < MAX_HARTS; ++hart) - if ((((~HART_MASK & hart_mask) >> hart) & 1)) + if ((((~DISABLED_HART_MASK & hart_mask) >> hart) & 1)) *OTHER_HLS(hart)->ipi = 1; // wakeup the hart } diff --git a/machine/mtrap.c b/machine/mtrap.c index be264f3..49d652f 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -50,7 +50,7 @@ void printm(const char* s, ...) static void send_ipi(uintptr_t recipient, int event) { - if (((HART_MASK >> recipient) & 1)) return; + if (((DISABLED_HART_MASK >> recipient) & 1)) return; atomic_or(&OTHER_HLS(recipient)->mipi_pending, event); mb(); *OTHER_HLS(recipient)->ipi = 1; diff --git a/machine/mtrap.h b/machine/mtrap.h index 1437b11..ead7150 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -10,7 +10,7 @@ #endif // These harts will be prevented from booting beyond bbl -#define HART_MASK 0x0UL +#define DISABLED_HART_MASK 0x0UL #ifndef __ASSEMBLER__ -- cgit v1.1 From a2c8937e631f7531c3d59e4f179369f51eb44d19 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 5 Apr 2017 17:46:48 -0700 Subject: Remove num_harts; use hart_mask exclusively --- machine/fdt.c | 6 +++--- machine/minit.c | 1 - machine/mtrap.c | 3 ++- machine/mtrap.h | 1 - 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/machine/fdt.c b/machine/fdt.c index 34ff87b..cfa7ee9 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -239,7 +239,6 @@ static void hart_done(const struct fdt_scan_node *node, void *extra) if (scan->hart < MAX_HARTS) { hart_phandles[scan->hart] = scan->phandle; hart_mask |= 1 << scan->hart; - if (scan->hart >= num_harts) num_harts = scan->hart + 1; hls_init(scan->hart); } } @@ -266,9 +265,10 @@ void query_harts(uintptr_t fdt) cb.close= hart_close; cb.extra = &scan; - num_harts = 0; fdt_scan(fdt, &cb); - assert (num_harts > 0); + + // The current hart should have been detected + assert ((hart_mask >> read_csr(mhartid)) != 0); } ///////////////////////////////////////////// CLINT SCAN ///////////////////////////////////////// diff --git a/machine/minit.c b/machine/minit.c index 0052eb7..e78bbbb 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -9,7 +9,6 @@ pte_t* root_page_table; uintptr_t mem_size; -uintptr_t num_harts; volatile uint64_t* mtime; volatile uint32_t* plic_priorities; size_t plic_ndevs; diff --git a/machine/mtrap.c b/machine/mtrap.c index 49d652f..c114757 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -5,6 +5,7 @@ #include "bits.h" #include "vm.h" #include "uart.h" +#include "fdt.h" #include "unprivileged_memory.h" #include #include @@ -86,7 +87,7 @@ static uintptr_t mcall_set_timer(uint64_t when) static void send_ipi_many(uintptr_t* pmask, int event) { _Static_assert(MAX_HARTS <= 8 * sizeof(*pmask), "# harts > uintptr_t bits"); - uintptr_t mask = ((uintptr_t)1 << num_harts) - 1; + uintptr_t mask = hart_mask; if (pmask) mask &= load_uintptr_t(pmask, read_csr(mepc)); diff --git a/machine/mtrap.h b/machine/mtrap.h index ead7150..16453d7 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -32,7 +32,6 @@ static inline int xlen() } extern uintptr_t mem_size; -extern uintptr_t num_harts; extern volatile uint64_t* mtime; extern volatile uint32_t* plic_priorities; extern size_t plic_ndevs; -- cgit v1.1 From 8197cad40c5af8e4e315429be9f20aefbcc803ee Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 6 Apr 2017 10:48:46 -0700 Subject: mtrap: allow override of DISABLED_HART_MASK from CFLAGS --- machine/mtrap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machine/mtrap.h b/machine/mtrap.h index 16453d7..df71797 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -10,7 +10,9 @@ #endif // These harts will be prevented from booting beyond bbl +#ifndef DISABLED_HART_MASK #define DISABLED_HART_MASK 0x0UL +#endif #ifndef __ASSEMBLER__ -- cgit v1.1 From 3a3c1f5a1a797b8d054652c6a5eecc13699dee51 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 11 Apr 2017 19:42:45 -0700 Subject: Load instructions as unsigned values, not signed This matches the behavior of mbabaddr/mtval. --- machine/unprivileged_memory.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h index 6b84861..67ae98b 100644 --- a/machine/unprivileged_memory.h +++ b/machine/unprivileged_memory.h @@ -2,6 +2,7 @@ #define _RISCV_MISALIGNED_H #include "encoding.h" +#include "bits.h" #include #define DECLARE_UNPRIVILEGED_LOAD_FUNCTION(type, insn) \ @@ -39,13 +40,12 @@ DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int32_t, lw) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint8_t, sb) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint16_t, sh) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint32_t, sw) +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, LWU) #if __riscv_xlen == 64 -DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lwu) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint64_t, ld) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint64_t, sd) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, ld) #else -DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lw) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, lw) static inline uint64_t load_uint64_t(const uint64_t* addr, uintptr_t mepc) @@ -68,7 +68,7 @@ static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr uintptr_t val; #ifndef __riscv_compressed asm ("csrrs %[mstatus], mstatus, %[mprv]\n" - "lw %[insn], (%[addr])\n" + STR(LWU) " %[insn], (%[addr])\n" "csrw mstatus, %[mstatus]" : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val) : [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc)); @@ -78,7 +78,7 @@ static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr "lhu %[insn], (%[addr])\n" "and %[tmp], %[insn], %[rvc_mask]\n" "bne %[tmp], %[rvc_mask], 1f\n" - "lh %[tmp], 2(%[addr])\n" + "lhu %[tmp], 2(%[addr])\n" "sll %[tmp], %[tmp], 16\n" "add %[insn], %[insn], %[tmp]\n" "1: csrw mstatus, %[mstatus]" -- cgit v1.1 From 5f736b9ab82ad19e03fc720c63f08e01a72712cc Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 11 Apr 2017 19:48:01 -0700 Subject: Always write sbadaddr on trap redirection --- machine/emulation.c | 2 +- machine/emulation.h | 2 +- machine/mtrap.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/machine/emulation.c b/machine/emulation.c index b5d3410..b86fa36 100644 --- a/machine/emulation.c +++ b/machine/emulation.c @@ -149,7 +149,7 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) __attribute__((noinline)) DECLARE_EMULATION_FUNC(truly_illegal_insn) { - return redirect_trap(mepc, mstatus); + return redirect_trap(mepc, mstatus, insn); } static inline int emulate_read_csr(int num, uintptr_t mstatus, uintptr_t* result) diff --git a/machine/emulation.h b/machine/emulation.h index 156d847..f75173d 100644 --- a/machine/emulation.h +++ b/machine/emulation.h @@ -11,7 +11,7 @@ typedef void (*emulation_func)(uintptr_t*, uintptr_t, uintptr_t, uintptr_t, insn void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc); void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc); -void redirect_trap(uintptr_t epc, uintptr_t mstatus); +void redirect_trap(uintptr_t epc, uintptr_t mstatus, uintptr_t badaddr); DECLARE_EMULATION_FUNC(truly_illegal_insn); DECLARE_EMULATION_FUNC(emulate_rvc_0); DECLARE_EMULATION_FUNC(emulate_rvc_2); diff --git a/machine/mtrap.c b/machine/mtrap.c index c114757..d0c1684 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -161,8 +161,9 @@ send_ipi: regs[10] = retval; } -void redirect_trap(uintptr_t epc, uintptr_t mstatus) +void redirect_trap(uintptr_t epc, uintptr_t mstatus, uintptr_t badaddr) { + write_csr(sbadaddr, badaddr); write_csr(sepc, epc); write_csr(scause, read_csr(mcause)); write_csr(mepc, read_csr(stvec)); @@ -180,7 +181,7 @@ void redirect_trap(uintptr_t epc, uintptr_t mstatus) void pmp_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) { - redirect_trap(mepc, read_csr(mstatus)); + redirect_trap(mepc, read_csr(mstatus), read_csr(mbadaddr)); } static void machine_page_fault(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) @@ -188,8 +189,7 @@ static void machine_page_fault(uintptr_t* regs, uintptr_t dummy, uintptr_t mepc) // MPRV=1 iff this trap occurred while emulating an instruction on behalf // of a lower privilege level. In that case, a2=epc and a3=mstatus. if (read_csr(mstatus) & MSTATUS_MPRV) { - write_csr(sbadaddr, read_csr(mbadaddr)); - return redirect_trap(regs[12], regs[13]); + return redirect_trap(regs[12], regs[13], read_csr(mbadaddr)); } bad_trap(regs, dummy, mepc); } -- cgit v1.1 From 0f0ac647fe646529c51b5f5c68221502dc88d239 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 18 Apr 2017 09:59:04 -0700 Subject: Increase PK stack size to 3% of memory, up to 8 MiB --- pk/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pk/mmap.c b/pk/mmap.c index a063f42..94fecdd 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -401,7 +401,7 @@ uintptr_t pk_vm_init() current.mmap_max = current.brk_max = MIN(DRAM_BASE, mem_size - (first_free_paddr - DRAM_BASE)); - size_t stack_size = RISCV_PGSIZE * 64; + size_t stack_size = MIN(mem_pages >> 5, 2048) * RISCV_PGSIZE; size_t stack_bottom = __do_mmap(current.mmap_max - stack_size, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); kassert(stack_bottom != (uintptr_t)-1); current.stack_top = stack_bottom + stack_size; -- cgit v1.1 From 770dcd9f1f468436292439eef53ff1888f1b8bad Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 18 Apr 2017 10:40:21 -0700 Subject: Fix RV32 compilation error --- machine/unprivileged_memory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h index 67ae98b..787f5f8 100644 --- a/machine/unprivileged_memory.h +++ b/machine/unprivileged_memory.h @@ -40,12 +40,13 @@ DECLARE_UNPRIVILEGED_LOAD_FUNCTION(int32_t, lw) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint8_t, sb) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint16_t, sh) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint32_t, sw) -DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, LWU) #if __riscv_xlen == 64 +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lwu) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint64_t, ld) DECLARE_UNPRIVILEGED_STORE_FUNCTION(uint64_t, sd) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, ld) #else +DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uint32_t, lw) DECLARE_UNPRIVILEGED_LOAD_FUNCTION(uintptr_t, lw) static inline uint64_t load_uint64_t(const uint64_t* addr, uintptr_t mepc) -- cgit v1.1 From 5ca090ba6c467e1a4b3506fb16bd1406e835fcbc Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 18 Apr 2017 13:04:39 -0700 Subject: Use uint64_t, not uintptr_t, to represent FDT addresses/sizes This fixes RV32 pk. --- machine/fdt.c | 37 ++++++++++++++++++++----------------- machine/fdt.h | 4 ++-- machine/uart.c | 4 ++-- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/machine/fdt.c b/machine/fdt.c index cfa7ee9..4f72f73 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -21,6 +21,7 @@ static uint32_t *fdt_scan_helper( int last = 0; child.parent = node; + // these are the default cell counts, as per the FDT spec child.address_cells = 2; child.size_cells = 1; prop.node = node; @@ -92,17 +93,19 @@ uint32_t fdt_size(uintptr_t fdt) return bswap(header->totalsize); } -const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *value, uintptr_t *result) +const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *value, uint64_t *result) { *result = 0; - for (int cells = node->address_cells; cells > 0; --cells) *result += bswap(*value++); + for (int cells = node->address_cells; cells > 0; --cells) + *result = (*result << 32) + bswap(*value++); return value; } -const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *value, uintptr_t *result) +const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *value, uint64_t *result) { *result = 0; - for (int cells = node->size_cells; cells > 0; --cells) *result += bswap(*value++); + for (int cells = node->size_cells; cells > 0; --cells) + *result = (*result << 32) + bswap(*value++); return value; } @@ -155,7 +158,7 @@ static void mem_done(const struct fdt_scan_node *node, void *extra) assert (scan->reg_value && scan->reg_len % 4 == 0); while (end - value > 0) { - uintptr_t base, size; + uint64_t base, size; value = fdt_get_address(node->parent, value, &base); value = fdt_get_size (node->parent, value, &size); if (base <= self && self <= base + size) { mem_size = size; } @@ -218,7 +221,7 @@ static void hart_prop(const struct fdt_scan_prop *prop, void *extra) } else if (!strcmp(prop->name, "phandle")) { scan->phandle = bswap(prop->value[0]); } else if (!strcmp(prop->name, "reg")) { - uintptr_t reg; + uint64_t reg; fdt_get_address(prop->node->parent, prop->value, ®); scan->hart = reg; } @@ -276,7 +279,7 @@ void query_harts(uintptr_t fdt) struct clint_scan { int compat; - uintptr_t reg; + uint64_t reg; const uint32_t *int_value; int int_len; int done; @@ -315,7 +318,7 @@ static void clint_done(const struct fdt_scan_node *node, void *extra) assert (!scan->done); // only one clint scan->done = 1; - mtime = (void*)(scan->reg + 0xbff8); + mtime = (void*)((uintptr_t)scan->reg + 0xbff8); for (int index = 0; end - value > 0; ++index) { uint32_t phandle = bswap(value[0]); @@ -325,8 +328,8 @@ static void clint_done(const struct fdt_scan_node *node, void *extra) break; if (hart < MAX_HARTS) { hls_t *hls = OTHER_HLS(hart); - hls->ipi = (void*)(scan->reg + index * 4); - hls->timecmp = (void*)(scan->reg + 0x4000 + (index * 8)); + hls->ipi = (void*)((uintptr_t)scan->reg + index * 4); + hls->timecmp = (void*)((uintptr_t)scan->reg + 0x4000 + (index * 8)); } value += 4; } @@ -353,7 +356,7 @@ void query_clint(uintptr_t fdt) struct plic_scan { int compat; - uintptr_t reg; + uint64_t reg; uint32_t *int_value; int int_len; int done; @@ -401,7 +404,7 @@ static void plic_done(const struct fdt_scan_node *node, void *extra) assert (!scan->done); // only one plic scan->done = 1; - plic_priorities = (uint32_t*)scan->reg; + plic_priorities = (uint32_t*)(uintptr_t)scan->reg; plic_ndevs = scan->ndev; for (int index = 0; end - value > 0; ++index) { @@ -414,11 +417,11 @@ static void plic_done(const struct fdt_scan_node *node, void *extra) if (hart < MAX_HARTS) { hls_t *hls = OTHER_HLS(hart); if (cpu_int == IRQ_M_EXT) { - hls->plic_m_ie = (uintptr_t*)(scan->reg + ENABLE_BASE + ENABLE_SIZE * index); - hls->plic_m_thresh = (uint32_t*) (scan->reg + HART_BASE + HART_SIZE * index); + hls->plic_m_ie = (uintptr_t*)((uintptr_t)scan->reg + ENABLE_BASE + ENABLE_SIZE * index); + hls->plic_m_thresh = (uint32_t*) ((uintptr_t)scan->reg + HART_BASE + HART_SIZE * index); } else if (cpu_int == IRQ_S_EXT) { - hls->plic_s_ie = (uintptr_t*)(scan->reg + ENABLE_BASE + ENABLE_SIZE * index); - hls->plic_s_thresh = (uint32_t*) (scan->reg + HART_BASE + HART_SIZE * index); + hls->plic_s_ie = (uintptr_t*)((uintptr_t)scan->reg + ENABLE_BASE + ENABLE_SIZE * index); + hls->plic_s_thresh = (uint32_t*) ((uintptr_t)scan->reg + HART_BASE + HART_SIZE * index); } else { printm("PLIC wired hart %d to wrong interrupt %d", hart, cpu_int); } @@ -553,7 +556,7 @@ static void hart_filter_prop(const struct fdt_scan_prop *prop, void *extra) if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "cpu")) { filter->compat = 1; } else if (!strcmp(prop->name, "reg")) { - uintptr_t reg; + uint64_t reg; fdt_get_address(prop->node->parent, prop->value, ®); filter->hart = reg; } else if (!strcmp(prop->name, "status")) { diff --git a/machine/fdt.h b/machine/fdt.h index 0581e95..c12905e 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -50,8 +50,8 @@ void fdt_scan(uintptr_t fdt, const struct fdt_cb *cb); uint32_t fdt_size(uintptr_t fdt); // Extract fields -const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); -const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value); +const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *base, uint64_t *value); +const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *base, uint64_t *value); int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str); // -1 if not found // Setup memory+clint+plic diff --git a/machine/uart.c b/machine/uart.c index a55e27e..0645500 100644 --- a/machine/uart.c +++ b/machine/uart.c @@ -31,7 +31,7 @@ int uart_getchar() struct uart_scan { int compat; - uintptr_t reg; + uint64_t reg; }; static void uart_open(const struct fdt_scan_node *node, void *extra) @@ -56,7 +56,7 @@ static void uart_done(const struct fdt_scan_node *node, void *extra) if (!scan->compat || !scan->reg || uart) return; // Enable Rx/Tx channels - uart = (void*)scan->reg; + uart = (void*)(uintptr_t)scan->reg; uart[UART_REG_TXCTRL] = UART_TXEN; uart[UART_REG_RXCTRL] = UART_RXEN; } -- cgit v1.1 From 3aebe0db7f08f0aeed154be9c78ea872c66fb1ec Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sat, 29 Apr 2017 15:07:47 -0700 Subject: README.md: Explicitly list the requirement of a separate build directory. h/t Karsten Merker --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 754c296..799234a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Build Steps We assume that the RISCV environment variable is set to the RISC-V tools install path, and that the riscv-gnu-toolchain package is installed. +Please note that building the binaries directly inside the source +directory is not supported; you need to use a separate build directory. $ mkdir build $ cd build -- cgit v1.1 From 66701f82f88d08d3700d8b0bc5d5306abfd0044f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 4 May 2017 17:07:15 -0700 Subject: FMV.X.S/FMV.S.X -> FMV.X.W/FMV.W.X --- machine/encoding.h | 15 ++++++--------- machine/fp_emulation.c | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index 55f8461..1463801 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -401,8 +401,6 @@ #define MASK_URET 0xffffffff #define MATCH_SRET 0x10200073 #define MASK_SRET 0xffffffff -#define MATCH_HRET 0x20200073 -#define MASK_HRET 0xffffffff #define MATCH_MRET 0x30200073 #define MASK_MRET 0xffffffff #define MATCH_DRET 0x7b200073 @@ -521,8 +519,8 @@ #define MASK_FCVT_L_S 0xfff0007f #define MATCH_FCVT_LU_S 0xc0300053 #define MASK_FCVT_LU_S 0xfff0007f -#define MATCH_FMV_X_S 0xe0000053 -#define MASK_FMV_X_S 0xfff0707f +#define MATCH_FMV_X_W 0xe0000053 +#define MASK_FMV_X_W 0xfff0707f #define MATCH_FCLASS_S 0xe0001053 #define MASK_FCLASS_S 0xfff0707f #define MATCH_FCVT_W_D 0xc2000053 @@ -557,8 +555,8 @@ #define MASK_FCVT_S_L 0xfff0007f #define MATCH_FCVT_S_LU 0xd0300053 #define MASK_FCVT_S_LU 0xfff0007f -#define MATCH_FMV_S_X 0xf0000053 -#define MASK_FMV_S_X 0xfff0707f +#define MATCH_FMV_W_X 0xf0000053 +#define MASK_FMV_W_X 0xfff0707f #define MATCH_FCVT_D_W 0xd2000053 #define MASK_FCVT_D_W 0xfff0007f #define MATCH_FCVT_D_WU 0xd2100053 @@ -1065,7 +1063,6 @@ DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) DECLARE_INSN(uret, MATCH_URET, MASK_URET) DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) -DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA) @@ -1125,7 +1122,7 @@ DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) -DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) +DECLARE_INSN(fmv_x_w, MATCH_FMV_X_W, MASK_FMV_X_W) DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) @@ -1143,7 +1140,7 @@ DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) -DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) +DECLARE_INSN(fmv_w_x, MATCH_FMV_W_X, MASK_FMV_W_X) DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) diff --git a/machine/fp_emulation.c b/machine/fp_emulation.c index 0bbe83c..ffa431b 100644 --- a/machine/fp_emulation.c +++ b/machine/fp_emulation.c @@ -344,7 +344,7 @@ DECLARE_EMULATION_FUNC(emulate_fmv_if) if (GET_PRECISION(insn) == PRECISION_S) { result = GET_F32_RS1(insn, regs); switch (GET_RM(insn)) { - case GET_RM(MATCH_FMV_X_S): break; + case GET_RM(MATCH_FMV_X_W): break; case GET_RM(MATCH_FCLASS_S): result = f32_classify(result); break; default: return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); } @@ -367,7 +367,7 @@ DECLARE_EMULATION_FUNC(emulate_fmv_fi) { uintptr_t rs1 = GET_RS1(insn, regs); - if ((insn & MASK_FMV_S_X) == MATCH_FMV_S_X) + if ((insn & MASK_FMV_W_X) == MATCH_FMV_W_X) SET_F32_RD(insn, regs, rs1); #if __riscv_xlen == 64 else if ((insn & MASK_FMV_D_X) == MATCH_FMV_D_X) -- cgit v1.1 From 57bb80fb7df07b40295a70a5aca6e110ba4dcbb0 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 17 Jul 2017 15:02:31 -0700 Subject: Fix emulation of misaligned RVC loads/stores We were accidentally advancing the PC by 4, not 2. --- machine/misaligned_ldst.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/machine/misaligned_ldst.c b/machine/misaligned_ldst.c index 8c96c18..2fccd50 100644 --- a/machine/misaligned_ldst.c +++ b/machine/misaligned_ldst.c @@ -3,6 +3,7 @@ #include "unprivileged_memory.h" #include "mtrap.h" #include "config.h" +#include "pk.h" union byte_array { uint8_t bytes[8]; @@ -15,6 +16,7 @@ void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) union byte_array val; uintptr_t mstatus; insn_t insn = get_insn(mepc, &mstatus); + uintptr_t npc = mepc + insn_len(insn); uintptr_t addr = read_csr(mbadaddr); int shift = 0, fp = 0, len; @@ -74,7 +76,7 @@ void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) else SET_F32_RD(insn, regs, val.intx); - write_csr(mepc, mepc + 4); + write_csr(mepc, npc); } void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) @@ -82,6 +84,7 @@ void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) union byte_array val; uintptr_t mstatus; insn_t insn = get_insn(mepc, &mstatus); + uintptr_t npc = mepc + insn_len(insn); int len; val.intx = GET_RS2(insn, regs); @@ -130,5 +133,5 @@ void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) for (int i = 0; i < len; i++) store_uint8_t((void *)(addr + i), val.bytes[i], mepc); - write_csr(mepc, mepc + 4); + write_csr(mepc, npc); } -- cgit v1.1 From 8b80f2ea28c0167f9dc75462147447b144ed4ea9 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 27 Jul 2017 13:21:54 -0700 Subject: Ignore some generated files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 54ac075..8595aa6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ build/ autom4te.cache/ - +*.swp +*~ -- cgit v1.1 From 9037b1d9f2130770228be62c66b88b47fccd99b6 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 27 Jul 2017 13:23:49 -0700 Subject: Add a platform interface SiFive's pk fork is the second one I've had to maintain, and it's a huge pain because people keep just leaving changes all over the tree. I want to introduce an interface that the platform-specific details can live behind so I don't have to keep doing these painful merges. --- bbl/bbl.mk.in | 1 + config.h.in | 3 +++ configure | 46 +++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- machine/machine.mk.in | 1 + pk/pk.mk.in | 1 + platform/platform.ac | 0 platform/platform.mk.in | 9 +++++++++ platform/platform_interface.h | 14 +++++++++++++ platform/spike.c | 1 + 10 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 platform/platform.ac create mode 100644 platform/platform.mk.in create mode 100644 platform/platform_interface.h create mode 100644 platform/spike.c diff --git a/bbl/bbl.mk.in b/bbl/bbl.mk.in index 5abe2cd..e3c5876 100644 --- a/bbl/bbl.mk.in +++ b/bbl/bbl.mk.in @@ -3,6 +3,7 @@ bbl_subproject_deps = \ softfloat \ machine \ dummy_payload \ + platform \ bbl_hdrs = \ bbl.h \ diff --git a/config.h.in b/config.h.in index bc6369e..9557930 100644 --- a/config.h.in +++ b/config.h.in @@ -40,6 +40,9 @@ #undef PK_ENABLE_VM /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ +#undef PLATFORM_ENABLED + +/* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef SOFTFLOAT_ENABLED /* Define to 1 if you have the ANSI C header files. */ diff --git a/configure b/configure index c1b2b73..25de84d 100755 --- a/configure +++ b/configure @@ -4433,6 +4433,51 @@ $as_echo "#define UTIL_ENABLED /**/" >>confdefs.h + # Determine if this is a required or an optional subproject + + + + # Determine if there is a group with the same name + + + + # Create variations of the subproject name suitable for use as a CPP + # enabled define, a shell enabled variable, and a shell function + + + + + + + + + + + + # Add subproject to our running list + + subprojects="$subprojects platform" + + # Process the subproject appropriately. If enabled add it to the + # $enabled_subprojects running shell variable, set a + # SUBPROJECT_ENABLED C define, and include the appropriate + # 'subproject.ac'. + + + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : platform" >&5 +$as_echo "$as_me: configuring default subproject : platform" >&6;} + ac_config_files="$ac_config_files platform.mk:platform/platform.mk.in" + + enable_platform_sproj="yes" + subprojects_enabled="$subprojects_enabled platform" + +$as_echo "#define PLATFORM_ENABLED /**/" >>confdefs.h + + + + + + # Output make variables @@ -5155,6 +5200,7 @@ do "dummy_payload.mk") CONFIG_FILES="$CONFIG_FILES dummy_payload.mk:dummy_payload/dummy_payload.mk.in" ;; "machine.mk") CONFIG_FILES="$CONFIG_FILES machine.mk:machine/machine.mk.in" ;; "util.mk") CONFIG_FILES="$CONFIG_FILES util.mk:util/util.mk.in" ;; + "platform.mk") CONFIG_FILES="$CONFIG_FILES platform.mk:platform/platform.mk.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; diff --git a/configure.ac b/configure.ac index b4a58fd..d4db795 100644 --- a/configure.ac +++ b/configure.ac @@ -111,7 +111,7 @@ AC_SUBST(install_subdir) # The '*' suffix indicates an optional subproject. The '**' suffix # indicates an optional subproject which is also the name of a group. -MCPPBS_SUBPROJECTS([ pk, bbl, softfloat, dummy_payload, machine, util ]) +MCPPBS_SUBPROJECTS([ pk, bbl, softfloat, dummy_payload, machine, util, platform ]) #------------------------------------------------------------------------- # MCPPBS subproject groups diff --git a/machine/machine.mk.in b/machine/machine.mk.in index cdcb4a7..76e02d9 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -1,5 +1,6 @@ machine_subproject_deps = \ softfloat \ + platform \ machine_hdrs = \ atomic.h \ diff --git a/pk/pk.mk.in b/pk/pk.mk.in index 3caa25d..d4be009 100644 --- a/pk/pk.mk.in +++ b/pk/pk.mk.in @@ -1,4 +1,5 @@ pk_subproject_deps = \ + platform \ util \ softfloat \ machine \ diff --git a/platform/platform.ac b/platform/platform.ac new file mode 100644 index 0000000..e69de29 diff --git a/platform/platform.mk.in b/platform/platform.mk.in new file mode 100644 index 0000000..90ee269 --- /dev/null +++ b/platform/platform.mk.in @@ -0,0 +1,9 @@ +platform_subproject_deps = + +platform_hdrs = \ + platform_interface.h + +platform_c_srcs = \ + spike.c + +platform_asm_srcs = diff --git a/platform/platform_interface.h b/platform/platform_interface.h new file mode 100644 index 0000000..0f49056 --- /dev/null +++ b/platform/platform_interface.h @@ -0,0 +1,14 @@ +#ifndef PLATFORM__PLATFORM_H +#define PLATFORM__PLATFORM_H + +/* This interface is designed to allow BBL/PK to be portable to multiple target + * platforms. The current interface has been hacked up based on SiFive's fork + * of pk that runs on our FPGA boards. The idea here is that rather than + * forking pk and touching things all over the tree, changes should be local to + * the target directory. + * + * This interface isn't meant to be stable or sane, just better than what we + * had before. + */ + +#endif diff --git a/platform/spike.c b/platform/spike.c new file mode 100644 index 0000000..9764057 --- /dev/null +++ b/platform/spike.c @@ -0,0 +1 @@ +#include "platform_interface.h" -- cgit v1.1 From bb19fef663a5ce32d7e2d3557362a51da8d99365 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 27 Jul 2017 13:30:08 -0700 Subject: Move the logo behind the platform interface SiFive has a different logo, so let platforms override said logo. --- bbl/logo.c | 28 ++-------------------------- platform/platform_interface.h | 4 ++++ platform/spike.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/bbl/logo.c b/bbl/logo.c index 673899d..63ff1ce 100644 --- a/bbl/logo.c +++ b/bbl/logo.c @@ -1,32 +1,8 @@ #include #include "mtrap.h" - -static const char logo[] = -" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" -" vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" -"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" -"rr vvvvvvvvvvvvvvvvvvvvvv \n" -"rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" -"rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" -"rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" -"rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" -"rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" -"rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" -"rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" -"\n" -" INSTRUCTION SETS WANT TO BE FREE\n"; +#include "platform_interface.h" void print_logo() { - putstring(logo); + putstring(platform__get_logo()); } diff --git a/platform/platform_interface.h b/platform/platform_interface.h index 0f49056..9c52cde 100644 --- a/platform/platform_interface.h +++ b/platform/platform_interface.h @@ -11,4 +11,8 @@ * had before. */ +/* Returns a pointer to what's expected to be a staticly allocated logo string. + * This will be printed when BBL boots. */ +const char *platform__get_logo(void); + #endif diff --git a/platform/spike.c b/platform/spike.c index 9764057..06aa742 100644 --- a/platform/spike.c +++ b/platform/spike.c @@ -1 +1,32 @@ #include "platform_interface.h" + +static const char logo[] = +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" +" vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" +"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" +"rr vvvvvvvvvvvvvvvvvvvvvv \n" +"rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" +"rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" +"rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" +"rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" +"rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" +"rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" +"rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" +"\n" +" INSTRUCTION SETS WANT TO BE FREE\n"; + + +const char *platform__get_logo(void) +{ + return logo; +} -- cgit v1.1 From 62effc6bfe4f1a7e8a771c49966c4ab7755d6612 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Fri, 28 Jul 2017 14:10:20 -0700 Subject: Allow the platform to disable HTIF --- machine/mtrap.c | 13 ++++++++++--- platform/platform_interface.h | 3 +++ platform/spike.c | 6 +++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/machine/mtrap.c b/machine/mtrap.c index d0c1684..ff4eb60 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -7,6 +7,7 @@ #include "uart.h" #include "fdt.h" #include "unprivileged_memory.h" +#include "platform_interface.h" #include #include #include @@ -20,7 +21,7 @@ static uintptr_t mcall_console_putchar(uint8_t ch) { if (uart) { uart_putchar(ch); - } else { + } else if (platform__use_htif()) { htif_console_putchar(ch); } return 0; @@ -28,7 +29,11 @@ static uintptr_t mcall_console_putchar(uint8_t ch) void poweroff() { - htif_poweroff(); + if (platform__use_htif()) { + htif_poweroff(); + } else { + while (1); + } } void putstring(const char* s) @@ -61,8 +66,10 @@ static uintptr_t mcall_console_getchar() { if (uart) { return uart_getchar(); - } else { + } else if (platform__use_htif()) { return htif_console_getchar(); + } else { + return '\0'; } } diff --git a/platform/platform_interface.h b/platform/platform_interface.h index 9c52cde..dd521e3 100644 --- a/platform/platform_interface.h +++ b/platform/platform_interface.h @@ -15,4 +15,7 @@ * This will be printed when BBL boots. */ const char *platform__get_logo(void); +/* Returns TRUE if it's valid to use the HTIF */ +int platform__use_htif(void); + #endif diff --git a/platform/spike.c b/platform/spike.c index 06aa742..159255f 100644 --- a/platform/spike.c +++ b/platform/spike.c @@ -25,8 +25,12 @@ static const char logo[] = "\n" " INSTRUCTION SETS WANT TO BE FREE\n"; - const char *platform__get_logo(void) { return logo; } + +int platform__use_htif(void) +{ + return 1; +} -- cgit v1.1 From 298984cbe6ffd7ab8507fa40e15199c7d5386aab Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Wed, 2 Aug 2017 10:29:44 -0700 Subject: Move DISABLED_HART_MASK to the platform Some platforms can't boot Linux on all the harts. This commit allows platforms to define the set of harts that should be prevented from booting past BBL. This is essentially just a new mechanism for defining the DISABLED_HART_MASK. --- bbl/bbl.c | 3 ++- machine/mentry.S | 9 +++++++-- machine/minit.c | 3 ++- machine/mtrap.c | 2 +- machine/mtrap.h | 5 ----- platform/platform_interface.h | 8 ++++++++ platform/spike.c | 2 ++ 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 5ee95ad..b0a862d 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -5,6 +5,7 @@ #include "bits.h" #include "config.h" #include "fdt.h" +#include "platform_interface.h" #include static const void* entry_point; @@ -23,7 +24,7 @@ static void filter_dtb(uintptr_t source) memcpy((void*)dest, (void*)source, size); // Remove information from the chained FDT - filter_harts(dest, DISABLED_HART_MASK); + filter_harts(dest, platform__disabled_hart_mask); filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); diff --git a/machine/mentry.S b/machine/mentry.S index 64fb507..33d7be4 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -258,7 +258,11 @@ do_reset: add sp, sp, a2 # Boot on the first unmasked hart - li a4, (~DISABLED_HART_MASK & (DISABLED_HART_MASK+1)) + la a4, platform__disabled_hart_mask + LOAD a4, 0(a4) + addi a5, a4, 1 + not a4, a4 + and a4, a4, a5 srl a4, a4, a3 andi a4, a4, 1 bnez a4, init_first_hart @@ -273,7 +277,8 @@ do_reset: wfi # masked harts never start - li a4, DISABLED_HART_MASK + la a4, platform__disabled_hart_mask + LOAD a4, 0(a4) srl a4, a4, a3 andi a4, a4, 1 bnez a4, .LmultiHart diff --git a/machine/minit.c b/machine/minit.c index e78bbbb..0fb5f21 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -4,6 +4,7 @@ #include "fp_emulation.h" #include "fdt.h" #include "uart.h" +#include "platform_interface.h" #include #include @@ -123,7 +124,7 @@ static void hart_plic_init() static void wake_harts() { for (int hart = 0; hart < MAX_HARTS; ++hart) - if ((((~DISABLED_HART_MASK & hart_mask) >> hart) & 1)) + if ((((~platform__disabled_hart_mask & hart_mask) >> hart) & 1)) *OTHER_HLS(hart)->ipi = 1; // wakeup the hart } diff --git a/machine/mtrap.c b/machine/mtrap.c index ff4eb60..62137ff 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -56,7 +56,7 @@ void printm(const char* s, ...) static void send_ipi(uintptr_t recipient, int event) { - if (((DISABLED_HART_MASK >> recipient) & 1)) return; + if (((platform__disabled_hart_mask >> recipient) & 1)) return; atomic_or(&OTHER_HLS(recipient)->mipi_pending, event); mb(); *OTHER_HLS(recipient)->ipi = 1; diff --git a/machine/mtrap.h b/machine/mtrap.h index df71797..4ec0924 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -9,11 +9,6 @@ # define MAX_HARTS 1 #endif -// These harts will be prevented from booting beyond bbl -#ifndef DISABLED_HART_MASK -#define DISABLED_HART_MASK 0x0UL -#endif - #ifndef __ASSEMBLER__ #include diff --git a/platform/platform_interface.h b/platform/platform_interface.h index dd521e3..f083085 100644 --- a/platform/platform_interface.h +++ b/platform/platform_interface.h @@ -1,6 +1,8 @@ #ifndef PLATFORM__PLATFORM_H #define PLATFORM__PLATFORM_H +#ifndef __ASSEMBLY__ + /* This interface is designed to allow BBL/PK to be portable to multiple target * platforms. The current interface has been hacked up based on SiFive's fork * of pk that runs on our FPGA boards. The idea here is that rather than @@ -18,4 +20,10 @@ const char *platform__get_logo(void); /* Returns TRUE if it's valid to use the HTIF */ int platform__use_htif(void); +/* The harts that should be excluded from booting to the target program and + * should intsead be held in a loop. */ +extern long platform__disabled_hart_mask; + +#endif + #endif diff --git a/platform/spike.c b/platform/spike.c index 159255f..4d9d397 100644 --- a/platform/spike.c +++ b/platform/spike.c @@ -25,6 +25,8 @@ static const char logo[] = "\n" " INSTRUCTION SETS WANT TO BE FREE\n"; +long platform__disabled_hart_mask = 0; + const char *platform__get_logo(void) { return logo; -- cgit v1.1 From 0d202e9dd4c8dd6c6aaba173a958bf29eeb7bcee Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Wed, 2 Aug 2017 10:42:45 -0700 Subject: Add the '--with-platform' argument and the sifive-vc707-devkit platform Since we don't have a coherent platform specification right now, we've ended up with slightly different platforms between spike and our FPGA dev kit. For now I've added an autoconf option that allows users to select the relevant platform. --- configure | 14 ++++++++++++++ configure.ac | 6 ++++++ platform/platform.mk.in | 2 +- platform/sifive-vc707-devkit.c | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 platform/sifive-vc707-devkit.c diff --git a/configure b/configure index 25de84d..a9296e0 100755 --- a/configure +++ b/configure @@ -592,6 +592,7 @@ subprojects_enabled subprojects BBL_PAYLOAD install_subdir +PLATFORM_NAME RISCV EGREP GREP @@ -669,6 +670,7 @@ ac_user_opts=' enable_option_checking enable_stow enable_32bit +with_platform enable_optional_subprojects enable_vm enable_logo @@ -1325,6 +1327,7 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-platform=spike Select the target platform --with-payload Set ELF payload for bbl Some influential environment variables: @@ -4090,6 +4093,17 @@ case "${BUILD_32BIT}" in esac +# Check whether --with-platform was given. +if test "${with_platform+set}" = set; then : + withval=$with_platform; PLATFORM_NAME=$withval +else + PLATFORM_NAME=spike +fi + +PLATFORM_NAME=$PLATFORM_NAME + + + LIBS="-lgcc" diff --git a/configure.ac b/configure.ac index d4db795..5813f3b 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,12 @@ case "${BUILD_32BIT}" in ;; esac +AC_ARG_WITH([platform], + AS_HELP_STRING([--with-platform=spike], [Select the target platform]), + PLATFORM_NAME=$withval, + PLATFORM_NAME=spike) +AC_SUBST(PLATFORM_NAME, $PLATFORM_NAME) + AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST([LIBS], ["-lgcc"]) diff --git a/platform/platform.mk.in b/platform/platform.mk.in index 90ee269..eded238 100644 --- a/platform/platform.mk.in +++ b/platform/platform.mk.in @@ -4,6 +4,6 @@ platform_hdrs = \ platform_interface.h platform_c_srcs = \ - spike.c + @PLATFORM_NAME@.c platform_asm_srcs = diff --git a/platform/sifive-vc707-devkit.c b/platform/sifive-vc707-devkit.c new file mode 100644 index 0000000..cc0e0f1 --- /dev/null +++ b/platform/sifive-vc707-devkit.c @@ -0,0 +1,41 @@ +#include "platform_interface.h" + +static const char logo[] = +"\r\n" +" SIFIVE, INC.\r\n" +"\r\n" +" 5555555555555555555555555\r\n" +" 5555 5555\r\n" +" 5555 5555\r\n" +" 5555 5555\r\n" +" 5555 5555555555555555555555\r\n" +" 5555 555555555555555555555555\r\n" +" 5555 5555\r\n" +" 5555 5555\r\n" +" 5555 5555\r\n" +"5555555555555555555555555555 55555\r\n" +" 55555 555555555 55555\r\n" +" 55555 55555 55555\r\n" +" 55555 5 55555\r\n" +" 55555 55555\r\n" +" 55555 55555\r\n" +" 55555 55555\r\n" +" 55555 55555\r\n" +" 55555 55555\r\n" +" 555555555\r\n" +" 55555\r\n" +" 5\r\n" +"\r\n" +" SiFive RISC-V Coreplex\r\n"; + +long platform__disabled_hart_mask = 0x1; + +const char *platform__get_logo(void) +{ + return logo; +} + +int platform__use_htif(void) +{ + return 0; +} -- cgit v1.1 From f0f85949a006e201432031c8b5b1adb21eb22f4a Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 3 Aug 2017 08:45:08 -0700 Subject: Allow platform__get_logo to return NULL --- bbl/logo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bbl/logo.c b/bbl/logo.c index 63ff1ce..89b1fa3 100644 --- a/bbl/logo.c +++ b/bbl/logo.c @@ -4,5 +4,7 @@ void print_logo() { - putstring(platform__get_logo()); + const char *logo = platform__get_logo(); + if (logo != NULL) + putstring(logo); } -- cgit v1.1 From ca24f3c904186cb6babfc74fd6c4e133e4542b5e Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 3 Aug 2017 14:39:23 -0700 Subject: Add the '--enable-print-device-tree' argument I'm trying to debug some device tree problems while booting Linux and figured it would be really nice to have access to the device tree while trying to debug these problems. I think this might be useful for lots of people, so I went ahead and cleaned up the code enough that it should actaully work in most cases. --- bbl/bbl.c | 11 +++-- config.h.in | 3 ++ configure | 16 +++++++ configure.ac | 5 +++ machine/fdt.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ machine/fdt.h | 5 +++ machine/mtrap.c | 12 ++++-- machine/mtrap.h | 2 + 8 files changed, 174 insertions(+), 7 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index b0a862d..7d1be2a 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -17,7 +17,7 @@ static uintptr_t dtb_output() return (end + MEGAPAGE_SIZE - 1) / MEGAPAGE_SIZE * MEGAPAGE_SIZE; } -static void filter_dtb(uintptr_t source) +static uintptr_t filter_dtb(uintptr_t source) { uintptr_t dest = dtb_output(); uint32_t size = fdt_size(source); @@ -28,6 +28,8 @@ static void filter_dtb(uintptr_t source) filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); + + return dest; } void boot_other_hart(uintptr_t dtb) @@ -37,16 +39,19 @@ void boot_other_hart(uintptr_t dtb) entry = entry_point; mb(); } while (!entry); - enter_supervisor_mode(entry, read_csr(mhartid), dtb_output()); + enter_supervisor_mode(entry, read_csr(mhartid), dtb); } void boot_loader(uintptr_t dtb) { extern char _payload_start; - filter_dtb(dtb); + dtb = filter_dtb(dtb); #ifdef PK_ENABLE_LOGO print_logo(); #endif +#ifdef PK_PRINT_DEVICE_TREE + fdt_print(dtb); +#endif mb(); entry_point = &_payload_start; boot_other_hart(dtb); diff --git a/config.h.in b/config.h.in index 9557930..179cbf0 100644 --- a/config.h.in +++ b/config.h.in @@ -39,6 +39,9 @@ /* Define if virtual memory support is enabled */ #undef PK_ENABLE_VM +/* Define if the DTS is to be displayed */ +#undef PK_PRINT_DEVICE_TREE + /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef PLATFORM_ENABLED diff --git a/configure b/configure index a9296e0..335fe2d 100755 --- a/configure +++ b/configure @@ -671,6 +671,7 @@ enable_option_checking enable_stow enable_32bit with_platform +enable_print_device_tree enable_optional_subprojects enable_vm enable_logo @@ -1318,6 +1319,8 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-stow Enable stow-based install --enable-32bit Build a 32-bit pk + --enable-print-device-tree + Print DTS when booting --enable-optional-subprojects Enable all optional subprojects --disable-vm Disable virtual memory @@ -4103,6 +4106,19 @@ fi PLATFORM_NAME=$PLATFORM_NAME +# Check whether --enable-print-device-tree was given. +if test "${enable_print_device_tree+set}" = set; then : + enableval=$enable_print_device_tree; +fi + +if test "x$enable_print_device_tree" == "xyes"; then : + + +$as_echo "#define PK_PRINT_DEVICE_TREE /**/" >>confdefs.h + + +fi + LIBS="-lgcc" diff --git a/configure.ac b/configure.ac index 5813f3b..31b275f 100644 --- a/configure.ac +++ b/configure.ac @@ -105,6 +105,11 @@ AC_ARG_WITH([platform], PLATFORM_NAME=spike) AC_SUBST(PLATFORM_NAME, $PLATFORM_NAME) +AC_ARG_ENABLE([print-device-tree], AS_HELP_STRING([--enable-print-device-tree], [Print DTS when booting])) +AS_IF([test "x$enable_print_device_tree" == "xyes"], [ + AC_DEFINE([PK_PRINT_DEVICE_TREE],,[Define if the DTS is to be displayed]) +]) + AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST([LIBS], ["-lgcc"]) diff --git a/machine/fdt.c b/machine/fdt.c index 4f72f73..35681f8 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -1,5 +1,6 @@ #include #include +#include "config.h" #include "fdt.h" #include "mtrap.h" @@ -10,6 +11,19 @@ static inline uint32_t bswap(uint32_t x) return z; } +static inline int isstring(char c) +{ + if (c >= 'A' && c <= 'Z') + return 1; + if (c >= 'a' && c <= 'z') + return 1; + if (c >= '0' && c <= '9') + return 1; + if (c == '\0' || c == ' ' || c == ',' || c == '-') + return 1; + return 0; +} + static uint32_t *fdt_scan_helper( uint32_t *lex, const char *strings, @@ -593,3 +607,116 @@ void filter_harts(uintptr_t fdt, unsigned long hart_mask) filter.mask = hart_mask; fdt_scan(fdt, &cb); } + +//////////////////////////////////////////// PRINT ////////////////////////////////////////////// + +#ifdef PK_PRINT_DEVICE_TREE +#define FDT_PRINT_MAX_DEPTH 32 + +struct fdt_print_info { + int depth; + const struct fdt_scan_node *stack[FDT_PRINT_MAX_DEPTH]; +}; + +void fdt_print_printm(struct fdt_print_info *info, const char *format, ...) +{ + va_list vl; + + for (int i = 0; i < info->depth; ++i) + printm(" "); + + va_start(vl, format); + vprintm(format, vl); + va_end(vl); +} + +static void fdt_print_open(const struct fdt_scan_node *node, void *extra) +{ + struct fdt_print_info *info = (struct fdt_print_info *)extra; + + while (node->parent != NULL && info->stack[info->depth-1] != node->parent) { + info->depth--; + fdt_print_printm(info, "}\r\n"); + } + + fdt_print_printm(info, "%s {\r\n", node->name); + info->stack[info->depth] = node; + info->depth++; +} + +static void fdt_print_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct fdt_print_info *info = (struct fdt_print_info *)extra; + int asstring = 1; + char *char_data = (char *)(prop->value); + + fdt_print_printm(info, "%s", prop->name); + + if (prop->len == 0) { + printm(";\r\n"); + return; + } else { + printm(" = "); + } + + /* It appears that dtc uses a hueristic to detect strings so I'm using a + * similar one here. */ + for (int i = 0; i < prop->len; ++i) { + if (!isstring(char_data[i])) + asstring = 0; + if (i > 0 && char_data[i] == '\0' && char_data[i-1] == '\0') + asstring = 0; + } + + if (asstring) { + for (size_t i = 0; i < prop->len; i += strlen(char_data + i) + 1) { + if (i != 0) + printm(", "); + printm("\"%s\"", char_data + i); + } + } else { + printm("<"); + for (size_t i = 0; i < prop->len/4; ++i) { + if (i != 0) + printm(" "); + printm("0x%08x", bswap(prop->value[i])); + } + printm(">"); + } + + printm(";\r\n"); +} + +static void fdt_print_done(const struct fdt_scan_node *node, void *extra) +{ + struct fdt_print_info *info = (struct fdt_print_info *)extra; +} + +static int fdt_print_close(const struct fdt_scan_node *node, void *extra) +{ + struct fdt_print_info *info = (struct fdt_print_info *)extra; + return 0; +} + +void fdt_print(uintptr_t fdt) +{ + struct fdt_print_info info; + struct fdt_cb cb; + + info.depth = 0; + + memset(&cb, 0, sizeof(cb)); + cb.open = fdt_print_open; + cb.prop = fdt_print_prop; + cb.done = fdt_print_done; + cb.close = fdt_print_close; + cb.extra = &info; + + fdt_scan(fdt, &cb); + + while (info.depth > 0) { + info.depth--; + fdt_print_printm(&info, "}\r\n"); + } +} +#endif diff --git a/machine/fdt.h b/machine/fdt.h index c12905e..5932e17 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -68,4 +68,9 @@ void filter_compat(uintptr_t fdt, const char *compat); // The hartids of available harts extern uint64_t hart_mask; +#ifdef PK_PRINT_DEVICE_TREE +// Prints the device tree to the console as a DTS +void fdt_print(uintptr_t fdt); +#endif + #endif diff --git a/machine/mtrap.c b/machine/mtrap.c index 62137ff..a72b373 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -42,16 +42,20 @@ void putstring(const char* s) mcall_console_putchar(*s++); } -void printm(const char* s, ...) +void vprintm(const char* s, va_list vl) { char buf[256]; + vsnprintf(buf, sizeof buf, s, vl); + putstring(buf); +} + +void printm(const char* s, ...) +{ va_list vl; va_start(vl, s); - vsnprintf(buf, sizeof buf, s, vl); + vprintm(s, vl); va_end(vl); - - putstring(buf); } static void send_ipi(uintptr_t recipient, int event) diff --git a/machine/mtrap.h b/machine/mtrap.h index 4ec0924..a15b265 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -13,6 +13,7 @@ #include #include +#include #define read_const_csr(reg) ({ unsigned long __tmp; \ asm ("csrr %0, " #reg : "=r"(__tmp)); \ @@ -57,6 +58,7 @@ hls_t* hls_init(uintptr_t hart_id); void parse_config_string(); void poweroff(void) __attribute((noreturn)); void printm(const char* s, ...); +void vprintm(const char *s, va_list args); void putstring(const char* s); #define assert(x) ({ if (!(x)) die("assertion failed: %s", #x); }) #define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(); }) -- cgit v1.1 From 147cfa612b8a601ee7646da3bce5267e08c30bdc Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Wed, 9 Aug 2017 17:13:55 -0700 Subject: The DTB argument to boot_other_hart shouldn't be used in BBL I screwed up refactoring bbl. --- bbl/bbl.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index 7d1be2a..d3d6d9f 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -17,7 +17,7 @@ static uintptr_t dtb_output() return (end + MEGAPAGE_SIZE - 1) / MEGAPAGE_SIZE * MEGAPAGE_SIZE; } -static uintptr_t filter_dtb(uintptr_t source) +static void filter_dtb(uintptr_t source) { uintptr_t dest = dtb_output(); uint32_t size = fdt_size(source); @@ -28,31 +28,29 @@ static uintptr_t filter_dtb(uintptr_t source) filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); - - return dest; } -void boot_other_hart(uintptr_t dtb) +void boot_other_hart(uintptr_t unused __attribute__((unused))) { const void* entry; do { entry = entry_point; mb(); } while (!entry); - enter_supervisor_mode(entry, read_csr(mhartid), dtb); + enter_supervisor_mode(entry, read_csr(mhartid), dtb_output()); } void boot_loader(uintptr_t dtb) { extern char _payload_start; - dtb = filter_dtb(dtb); + filter_dtb(dtb); #ifdef PK_ENABLE_LOGO print_logo(); #endif #ifdef PK_PRINT_DEVICE_TREE - fdt_print(dtb); + fdt_print(dtb_output()); #endif mb(); entry_point = &_payload_start; - boot_other_hart(dtb); + boot_other_hart(0); } -- cgit v1.1 From 3f20915effa623e11b139ba431841c7af2689cdd Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 14 Aug 2017 17:55:31 -0700 Subject: finisher: support terminating sifive devices simulation (#61) --- machine/finisher.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ machine/finisher.h | 13 ++++++++++++ machine/machine.mk.in | 2 ++ machine/minit.c | 4 ++++ machine/mtrap.c | 7 +++++-- machine/mtrap.h | 4 ++-- 6 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 machine/finisher.c create mode 100644 machine/finisher.h diff --git a/machine/finisher.c b/machine/finisher.c new file mode 100644 index 0000000..d113096 --- /dev/null +++ b/machine/finisher.c @@ -0,0 +1,58 @@ +#include +#include "finisher.h" +#include "fdt.h" + +volatile uint32_t* finisher; + +void finisher_exit(uint16_t code) +{ + if (!finisher) return; + if (code == 0) { + *finisher = FINISHER_PASS; + } else { + *finisher = code << 16 | FINISHER_FAIL; + } +} + +struct finisher_scan +{ + int compat; + uint64_t reg; +}; + +static void finisher_open(const struct fdt_scan_node *node, void *extra) +{ + struct finisher_scan *scan = (struct finisher_scan *)extra; + memset(scan, 0, sizeof(*scan)); +} + +static void finisher_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct finisher_scan *scan = (struct finisher_scan *)extra; + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "sifive,test0")) { + scan->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + fdt_get_address(prop->node->parent, prop->value, &scan->reg); + } +} + +static void finisher_done(const struct fdt_scan_node *node, void *extra) +{ + struct finisher_scan *scan = (struct finisher_scan *)extra; + if (!scan->compat || !scan->reg || finisher) return; + finisher = (uint32_t*)(uintptr_t)scan->reg; +} + +void query_finisher(uintptr_t fdt) +{ + struct fdt_cb cb; + struct finisher_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = finisher_open; + cb.prop = finisher_prop; + cb.done = finisher_done; + cb.extra = &scan; + + fdt_scan(fdt, &cb); +} diff --git a/machine/finisher.h b/machine/finisher.h new file mode 100644 index 0000000..60d10b4 --- /dev/null +++ b/machine/finisher.h @@ -0,0 +1,13 @@ +#ifndef _RISCV_FINISHER_H +#define _RISCV_FINISHER_H + +#include + +#define FINISHER_REG_FINISH 0 +#define FINISHER_FAIL 0x3333 +#define FINISHER_PASS 0x5555 + +void finisher_exit(uint16_t code); +void query_finisher(uintptr_t fdt); + +#endif diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 76e02d9..59d0eb4 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -13,6 +13,7 @@ machine_hdrs = \ mcall.h \ mtrap.h \ uart.h \ + finisher.h \ unprivileged_memory.h \ vm.h \ @@ -26,6 +27,7 @@ machine_c_srcs = \ fp_emulation.c \ fp_ldst.c \ uart.c \ + finisher.c \ misaligned_ldst.c \ machine_asm_srcs = \ diff --git a/machine/minit.c b/machine/minit.c index 0fb5f21..187bef7 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -4,6 +4,7 @@ #include "fp_emulation.h" #include "fdt.h" #include "uart.h" +#include "finisher.h" #include "platform_interface.h" #include #include @@ -136,6 +137,9 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb) // Confirm console as early as possible query_uart(dtb); + // Find the power button early as well so die() works + query_finisher(dtb); + query_mem(dtb); query_harts(dtb); query_clint(dtb); diff --git a/machine/mtrap.c b/machine/mtrap.c index a72b373..e5faae3 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -5,6 +5,7 @@ #include "bits.h" #include "vm.h" #include "uart.h" +#include "finisher.h" #include "fdt.h" #include "unprivileged_memory.h" #include "platform_interface.h" @@ -27,8 +28,10 @@ static uintptr_t mcall_console_putchar(uint8_t ch) return 0; } -void poweroff() +void poweroff(uint16_t code) { + printm("Power off\n"); + finisher_exit(code); if (platform__use_htif()) { htif_poweroff(); } else { @@ -84,7 +87,7 @@ static uintptr_t mcall_clear_ipi() static uintptr_t mcall_shutdown() { - poweroff(); + poweroff(0); } static uintptr_t mcall_set_timer(uint64_t when) diff --git a/machine/mtrap.h b/machine/mtrap.h index a15b265..eafdb14 100644 --- a/machine/mtrap.h +++ b/machine/mtrap.h @@ -56,12 +56,12 @@ typedef struct { hls_t* hls_init(uintptr_t hart_id); void parse_config_string(); -void poweroff(void) __attribute((noreturn)); +void poweroff(uint16_t code) __attribute((noreturn)); void printm(const char* s, ...); void vprintm(const char *s, va_list args); void putstring(const char* s); #define assert(x) ({ if (!(x)) die("assertion failed: %s", #x); }) -#define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(); }) +#define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(-1); }) void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1) __attribute__((noreturn)); -- cgit v1.1 From fb4e31229fb072297dad9fcdf2c67b053c5d0322 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 29 Aug 2017 15:12:52 -0700 Subject: Stub out sys_prlimit64 --- pk/syscall.c | 1 + pk/syscall.h | 1 + 2 files changed, 2 insertions(+) diff --git a/pk/syscall.c b/pk/syscall.c index 9f3b739..7f1f196 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -442,6 +442,7 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, unsigned l [SYS_munmap] = sys_munmap, [SYS_mremap] = sys_mremap, [SYS_mprotect] = sys_mprotect, + [SYS_prlimit64] = sys_stub_nosys, [SYS_rt_sigaction] = sys_rt_sigaction, [SYS_gettimeofday] = sys_gettimeofday, [SYS_times] = sys_times, diff --git a/pk/syscall.h b/pk/syscall.h index 05360b7..d73af7f 100644 --- a/pk/syscall.h +++ b/pk/syscall.h @@ -33,6 +33,7 @@ #define SYS_munmap 215 #define SYS_mremap 216 #define SYS_mprotect 226 +#define SYS_prlimit64 261 #define SYS_getmainvars 2011 #define SYS_rt_sigaction 134 #define SYS_writev 66 -- cgit v1.1 From 4c64de3213e7a08e4097970b26a14ad835cabfab Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 19 Oct 2017 17:29:14 -0700 Subject: Order __page_alloc before writing vmrs --- pk/mmap.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pk/mmap.c b/pk/mmap.c index 94fecdd..1b995f4 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -40,10 +40,14 @@ static vmr_t* __vmr_alloc(uintptr_t addr, size_t length, file_t* file, { if (!vmrs) { spinlock_lock(&vm_lock); - if (!vmrs) - vmrs = (vmr_t*)__page_alloc(); + if (!vmrs) { + vmr_t* page = (vmr_t*)__page_alloc(); + mb(); + vmrs = page; + } spinlock_unlock(&vm_lock); } + mb(); for (vmr_t* v = vmrs; v < vmrs + MAX_VMR; v++) { if (v->refcnt == 0) { -- cgit v1.1 From 18087efa98d77918d55127c3d7745cd6d6d9d77b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 23 Oct 2017 23:38:41 -0700 Subject: Make 4-byte aligned instruction-emulation loads atomic Per the Unix-class platform spec --- machine/unprivileged_memory.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/machine/unprivileged_memory.h b/machine/unprivileged_memory.h index 787f5f8..5cf2727 100644 --- a/machine/unprivileged_memory.h +++ b/machine/unprivileged_memory.h @@ -76,16 +76,25 @@ static uintptr_t __attribute__((always_inline)) get_insn(uintptr_t mepc, uintptr #else uintptr_t rvc_mask = 3, tmp; asm ("csrrs %[mstatus], mstatus, %[mprv]\n" + "and %[tmp], %[addr], 2\n" + "bnez %[tmp], 1f\n" + STR(LWU) " %[insn], (%[addr])\n" + "and %[tmp], %[insn], %[rvc_mask]\n" + "beq %[tmp], %[rvc_mask], 2f\n" + "sll %[insn], %[insn], %[xlen_minus_16]\n" + "srl %[insn], %[insn], %[xlen_minus_16]\n" + "j 2f\n" + "1:\n" "lhu %[insn], (%[addr])\n" "and %[tmp], %[insn], %[rvc_mask]\n" - "bne %[tmp], %[rvc_mask], 1f\n" + "bne %[tmp], %[rvc_mask], 2f\n" "lhu %[tmp], 2(%[addr])\n" "sll %[tmp], %[tmp], 16\n" "add %[insn], %[insn], %[tmp]\n" - "1: csrw mstatus, %[mstatus]" + "2: csrw mstatus, %[mstatus]" : [mstatus] "+&r" (__mstatus), [insn] "=&r" (val), [tmp] "=&r" (tmp) : [mprv] "r" (MSTATUS_MPRV | MSTATUS_MXR), [addr] "r" (__mepc), - [rvc_mask] "r" (rvc_mask)); + [rvc_mask] "r" (rvc_mask), [xlen_minus_16] "i" (__riscv_xlen - 16)); #endif *mstatus = __mstatus; return val; -- cgit v1.1 From 220b1bee10d9399864131cd1dbe5037714237f03 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 1 Nov 2017 01:13:45 -0700 Subject: Fix(?) fcvt.s.w emulation for rs1 = -2^31 (#66) --- machine/fp_emulation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machine/fp_emulation.c b/machine/fp_emulation.c index ffa431b..c83ef73 100644 --- a/machine/fp_emulation.c +++ b/machine/fp_emulation.c @@ -201,7 +201,7 @@ DECLARE_EMULATION_FUNC(emulate_fcvt_fi) { case 0: // int32 negative = (int32_t)uint_val < 0; - uint_val = negative ? -(int32_t)uint_val : (int32_t)uint_val; + uint_val = (uint32_t)(negative ? -uint_val : uint_val); break; case 1: // uint32 uint_val = (uint32_t)uint_val; -- cgit v1.1 From 9204785053e9a488b8990f9f98ff8f05c71fd0d5 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 2 Nov 2017 15:44:15 -0700 Subject: Detect harts that can't boot Linux instead of hard-coding them This checks to see if a hart can't boot Linux by looking for a compatible "mmu-type" field. If the hart can't boot Linux, then bbl masks it off. --- bbl/bbl.c | 16 ++++++++++++++-- machine/disabled_hart_mask.h | 4 ++++ machine/fdt.c | 28 +++++++++++++++++++++++----- machine/fdt.h | 2 +- machine/mentry.S | 4 ++-- machine/minit.c | 3 ++- machine/mtrap.c | 3 ++- pk/pk.c | 1 + platform/platform_interface.h | 4 ---- platform/sifive-vc707-devkit.c | 2 -- platform/spike.c | 2 -- 11 files changed, 49 insertions(+), 20 deletions(-) create mode 100644 machine/disabled_hart_mask.h diff --git a/bbl/bbl.c b/bbl/bbl.c index d3d6d9f..1f91ea2 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -9,6 +9,7 @@ #include static const void* entry_point; +long disabled_hart_mask; static uintptr_t dtb_output() { @@ -24,7 +25,7 @@ static void filter_dtb(uintptr_t source) memcpy((void*)dest, (void*)source, size); // Remove information from the chained FDT - filter_harts(dest, platform__disabled_hart_mask); + filter_harts(dest, &disabled_hart_mask); filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); @@ -37,7 +38,18 @@ void boot_other_hart(uintptr_t unused __attribute__((unused))) entry = entry_point; mb(); } while (!entry); - enter_supervisor_mode(entry, read_csr(mhartid), dtb_output()); + + long hartid = read_csr(mhartid); + if ((1 << hartid) & disabled_hart_mask) { + while (1) { + __asm__ volatile("wfi"); +#ifdef __riscv_div + __asm__ volatile("div x0, x0, x0"); +#endif + } + } + + enter_supervisor_mode(entry, hartid, dtb_output()); } void boot_loader(uintptr_t dtb) diff --git a/machine/disabled_hart_mask.h b/machine/disabled_hart_mask.h new file mode 100644 index 0000000..2a3a73c --- /dev/null +++ b/machine/disabled_hart_mask.h @@ -0,0 +1,4 @@ +#ifndef DISABLED_HART_MASK_H +#define DISABLED_HART_MASK_H +extern long disabled_hart_mask; +#endif diff --git a/machine/fdt.c b/machine/fdt.c index 35681f8..061b19e 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -1,3 +1,4 @@ +#include #include #include #include "config.h" @@ -553,13 +554,15 @@ struct hart_filter { int compat; int hart; char *status; - unsigned long mask; + char *mmu_type; + long *disabled_hart_mask; }; static void hart_filter_open(const struct fdt_scan_node *node, void *extra) { struct hart_filter *filter = (struct hart_filter *)extra; - filter->status = 0; + filter->status = NULL; + filter->mmu_type = NULL; filter->compat = 0; filter->hart = -1; } @@ -575,9 +578,22 @@ static void hart_filter_prop(const struct fdt_scan_prop *prop, void *extra) filter->hart = reg; } else if (!strcmp(prop->name, "status")) { filter->status = (char*)prop->value; + } else if (!strcmp(prop->name, "mmu-type")) { + filter->mmu_type = (char*)prop->value; } } +static bool hart_filter_mask(const struct hart_filter *filter) +{ + if (filter->mmu_type == NULL) return true; + if (strcmp(filter->status, "okay")) return true; + if (!strcmp(filter->mmu_type, "riscv,sv39")) return false; + if (!strcmp(filter->mmu_type, "riscv,sv48")) return false; + printm("hart_filter_mask saw unknown hart type: status=\"%s\", mmu_type=\"%s\"\n", + filter->status, filter->mmu_type); + return true; +} + static void hart_filter_done(const struct fdt_scan_node *node, void *extra) { struct hart_filter *filter = (struct hart_filter *)extra; @@ -586,14 +602,15 @@ static void hart_filter_done(const struct fdt_scan_node *node, void *extra) assert (filter->status); assert (filter->hart >= 0); - if (((filter->mask >> filter->hart) & 1) && !strcmp(filter->status, "okay")) { + if (hart_filter_mask(filter)) { strcpy(filter->status, "masked"); uint32_t *len = (uint32_t*)filter->status; len[-2] = bswap(strlen("masked")+1); + *filter->disabled_hart_mask |= (1 << filter->hart); } } -void filter_harts(uintptr_t fdt, unsigned long hart_mask) +void filter_harts(uintptr_t fdt, long *disabled_hart_mask) { struct fdt_cb cb; struct hart_filter filter; @@ -604,7 +621,8 @@ void filter_harts(uintptr_t fdt, unsigned long hart_mask) cb.done = hart_filter_done; cb.extra = &filter; - filter.mask = hart_mask; + filter.disabled_hart_mask = disabled_hart_mask; + *disabled_hart_mask = 0; fdt_scan(fdt, &cb); } diff --git a/machine/fdt.h b/machine/fdt.h index 5932e17..d436778 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -61,7 +61,7 @@ void query_plic(uintptr_t fdt); void query_clint(uintptr_t fdt); // Remove information from FDT -void filter_harts(uintptr_t fdt, unsigned long hart_mask); +void filter_harts(uintptr_t fdt, long *disabled_hart_mask); void filter_plic(uintptr_t fdt); void filter_compat(uintptr_t fdt, const char *compat); diff --git a/machine/mentry.S b/machine/mentry.S index 33d7be4..11c053c 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -258,7 +258,7 @@ do_reset: add sp, sp, a2 # Boot on the first unmasked hart - la a4, platform__disabled_hart_mask + la a4, disabled_hart_mask LOAD a4, 0(a4) addi a5, a4, 1 not a4, a4 @@ -277,7 +277,7 @@ do_reset: wfi # masked harts never start - la a4, platform__disabled_hart_mask + la a4, disabled_hart_mask LOAD a4, 0(a4) srl a4, a4, a3 andi a4, a4, 1 diff --git a/machine/minit.c b/machine/minit.c index 187bef7..8ce96b1 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -6,6 +6,7 @@ #include "uart.h" #include "finisher.h" #include "platform_interface.h" +#include "disabled_hart_mask.h" #include #include @@ -125,7 +126,7 @@ static void hart_plic_init() static void wake_harts() { for (int hart = 0; hart < MAX_HARTS; ++hart) - if ((((~platform__disabled_hart_mask & hart_mask) >> hart) & 1)) + if ((((~disabled_hart_mask & hart_mask) >> hart) & 1)) *OTHER_HLS(hart)->ipi = 1; // wakeup the hart } diff --git a/machine/mtrap.c b/machine/mtrap.c index e5faae3..dba3613 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -9,6 +9,7 @@ #include "fdt.h" #include "unprivileged_memory.h" #include "platform_interface.h" +#include "disabled_hart_mask.h" #include #include #include @@ -63,7 +64,7 @@ void printm(const char* s, ...) static void send_ipi(uintptr_t recipient, int event) { - if (((platform__disabled_hart_mask >> recipient) & 1)) return; + if (((disabled_hart_mask >> recipient) & 1)) return; atomic_or(&OTHER_HLS(recipient)->mipi_pending, event); mb(); *OTHER_HLS(recipient)->ipi = 1; diff --git a/pk/pk.c b/pk/pk.c index 11a2cdf..e7cfc3a 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -7,6 +7,7 @@ #include elf_info current; +long disabled_hart_mask; static void handle_option(const char* s) { diff --git a/platform/platform_interface.h b/platform/platform_interface.h index f083085..203457d 100644 --- a/platform/platform_interface.h +++ b/platform/platform_interface.h @@ -20,10 +20,6 @@ const char *platform__get_logo(void); /* Returns TRUE if it's valid to use the HTIF */ int platform__use_htif(void); -/* The harts that should be excluded from booting to the target program and - * should intsead be held in a loop. */ -extern long platform__disabled_hart_mask; - #endif #endif diff --git a/platform/sifive-vc707-devkit.c b/platform/sifive-vc707-devkit.c index cc0e0f1..bd27861 100644 --- a/platform/sifive-vc707-devkit.c +++ b/platform/sifive-vc707-devkit.c @@ -28,8 +28,6 @@ static const char logo[] = "\r\n" " SiFive RISC-V Coreplex\r\n"; -long platform__disabled_hart_mask = 0x1; - const char *platform__get_logo(void) { return logo; diff --git a/platform/spike.c b/platform/spike.c index 4d9d397..159255f 100644 --- a/platform/spike.c +++ b/platform/spike.c @@ -25,8 +25,6 @@ static const char logo[] = "\n" " INSTRUCTION SETS WANT TO BE FREE\n"; -long platform__disabled_hart_mask = 0; - const char *platform__get_logo(void) { return logo; -- cgit v1.1 From 21209988c72ee891727d5b9d548a224ae6958986 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 2 Nov 2017 18:02:09 -0700 Subject: Initialize the UART first Without this I can't get printf to show me debug info during early boot. --- machine/minit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/machine/minit.c b/machine/minit.c index 8ce96b1..a324d06 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -132,12 +132,12 @@ static void wake_harts() void init_first_hart(uintptr_t hartid, uintptr_t dtb) { - hart_init(); - hls_init(0); // this might get called again from parse_config_string - // Confirm console as early as possible query_uart(dtb); + hart_init(); + hls_init(0); // this might get called again from parse_config_string + // Find the power button early as well so die() works query_finisher(dtb); -- cgit v1.1 From 27498013ad7684a5f22a99790ac29badea205a3f Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 2 Nov 2017 18:22:37 -0700 Subject: Check if we have extensions before using them --- machine/minit.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/machine/minit.c b/machine/minit.c index a324d06..5f98501 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -19,22 +19,28 @@ size_t plic_ndevs; static void mstatus_init() { // Enable FPU - write_csr(mstatus, MSTATUS_FS); + if (supports_extension('D') || supports_extension('F')) + write_csr(mstatus, MSTATUS_FS); // Enable user/supervisor use of perf counters - write_csr(scounteren, -1); + if (supports_extension('S')) + write_csr(scounteren, -1); write_csr(mcounteren, -1); // Enable software interrupts write_csr(mie, MIP_MSIP); // Disable paging - write_csr(sptbr, 0); + if (supports_extension('S')) + write_csr(sptbr, 0); } // send S-mode interrupts and most exceptions straight to S-mode static void delegate_traps() { + if (!supports_extension('S')) + return; + uintptr_t interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP; uintptr_t exceptions = (1U << CAUSE_MISALIGNED_FETCH) | @@ -53,11 +59,12 @@ static void delegate_traps() static void fp_init() { + if (!supports_extension('D') && !supports_extension('F')) + return; + assert(read_csr(mstatus) & MSTATUS_FS); #ifdef __riscv_flen - if (!supports_extension('D')) - die("FPU not found; recompile pk with -msoft-float"); for (int i = 0; i < 32; i++) init_fp_reg(i); write_csr(fcsr, 0); -- cgit v1.1 From d1849cb5e3b8c714c2dae78bb15465f288707ac5 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Fri, 3 Nov 2017 16:30:35 -0700 Subject: Remove the platform interface We now automatically detect everything that the platform interface used to be used for, so it's now obsolete! --- bbl/bbl.c | 1 - bbl/bbl.lds | 1 + bbl/bbl.mk.in | 1 - bbl/logo.c | 30 ++++++++++++++++++--- config.h.in | 3 --- configure | 60 ------------------------------------------ configure.ac | 8 +----- machine/htif.c | 51 +++++++++++++++++++++++++++++++++++ machine/htif.h | 2 ++ machine/machine.mk.in | 1 - machine/minit.c | 3 ++- machine/mtrap.c | 7 +++-- pk/pk.lds | 1 + pk/pk.mk.in | 1 - platform/platform.ac | 0 platform/platform.mk.in | 9 ------- platform/platform_interface.h | 25 ------------------ platform/sifive-vc707-devkit.c | 39 --------------------------- platform/spike.c | 36 ------------------------- 19 files changed, 87 insertions(+), 192 deletions(-) delete mode 100644 platform/platform.ac delete mode 100644 platform/platform.mk.in delete mode 100644 platform/platform_interface.h delete mode 100644 platform/sifive-vc707-devkit.c delete mode 100644 platform/spike.c diff --git a/bbl/bbl.c b/bbl/bbl.c index 1f91ea2..1b96a9d 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -5,7 +5,6 @@ #include "bits.h" #include "config.h" #include "fdt.h" -#include "platform_interface.h" #include static const void* entry_point; diff --git a/bbl/bbl.lds b/bbl/bbl.lds index b90e99f..2fd0d7c 100644 --- a/bbl/bbl.lds +++ b/bbl/bbl.lds @@ -46,6 +46,7 @@ SECTIONS . = ALIGN(0x1000); .htif : { + PROVIDE( __htif_base = .); *(.htif) } . = ALIGN(0x1000); diff --git a/bbl/bbl.mk.in b/bbl/bbl.mk.in index e3c5876..5abe2cd 100644 --- a/bbl/bbl.mk.in +++ b/bbl/bbl.mk.in @@ -3,7 +3,6 @@ bbl_subproject_deps = \ softfloat \ machine \ dummy_payload \ - platform \ bbl_hdrs = \ bbl.h \ diff --git a/bbl/logo.c b/bbl/logo.c index 89b1fa3..673899d 100644 --- a/bbl/logo.c +++ b/bbl/logo.c @@ -1,10 +1,32 @@ #include #include "mtrap.h" -#include "platform_interface.h" + +static const char logo[] = +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" +" vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" +"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" +"rr vvvvvvvvvvvvvvvvvvvvvv \n" +"rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" +"rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" +"rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" +"rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" +"rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" +"rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" +"rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" +"\n" +" INSTRUCTION SETS WANT TO BE FREE\n"; void print_logo() { - const char *logo = platform__get_logo(); - if (logo != NULL) - putstring(logo); + putstring(logo); } diff --git a/config.h.in b/config.h.in index 179cbf0..4674a2e 100644 --- a/config.h.in +++ b/config.h.in @@ -43,9 +43,6 @@ #undef PK_PRINT_DEVICE_TREE /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ -#undef PLATFORM_ENABLED - -/* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef SOFTFLOAT_ENABLED /* Define to 1 if you have the ANSI C header files. */ diff --git a/configure b/configure index 335fe2d..e67142c 100755 --- a/configure +++ b/configure @@ -592,7 +592,6 @@ subprojects_enabled subprojects BBL_PAYLOAD install_subdir -PLATFORM_NAME RISCV EGREP GREP @@ -670,7 +669,6 @@ ac_user_opts=' enable_option_checking enable_stow enable_32bit -with_platform enable_print_device_tree enable_optional_subprojects enable_vm @@ -1330,7 +1328,6 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-platform=spike Select the target platform --with-payload Set ELF payload for bbl Some influential environment variables: @@ -4095,17 +4092,6 @@ case "${BUILD_32BIT}" in ;; esac - -# Check whether --with-platform was given. -if test "${with_platform+set}" = set; then : - withval=$with_platform; PLATFORM_NAME=$withval -else - PLATFORM_NAME=spike -fi - -PLATFORM_NAME=$PLATFORM_NAME - - # Check whether --enable-print-device-tree was given. if test "${enable_print_device_tree+set}" = set; then : enableval=$enable_print_device_tree; @@ -4463,51 +4449,6 @@ $as_echo "#define UTIL_ENABLED /**/" >>confdefs.h - # Determine if this is a required or an optional subproject - - - - # Determine if there is a group with the same name - - - - # Create variations of the subproject name suitable for use as a CPP - # enabled define, a shell enabled variable, and a shell function - - - - - - - - - - - - # Add subproject to our running list - - subprojects="$subprojects platform" - - # Process the subproject appropriately. If enabled add it to the - # $enabled_subprojects running shell variable, set a - # SUBPROJECT_ENABLED C define, and include the appropriate - # 'subproject.ac'. - - - { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : platform" >&5 -$as_echo "$as_me: configuring default subproject : platform" >&6;} - ac_config_files="$ac_config_files platform.mk:platform/platform.mk.in" - - enable_platform_sproj="yes" - subprojects_enabled="$subprojects_enabled platform" - -$as_echo "#define PLATFORM_ENABLED /**/" >>confdefs.h - - - - - - # Output make variables @@ -5230,7 +5171,6 @@ do "dummy_payload.mk") CONFIG_FILES="$CONFIG_FILES dummy_payload.mk:dummy_payload/dummy_payload.mk.in" ;; "machine.mk") CONFIG_FILES="$CONFIG_FILES machine.mk:machine/machine.mk.in" ;; "util.mk") CONFIG_FILES="$CONFIG_FILES util.mk:util/util.mk.in" ;; - "platform.mk") CONFIG_FILES="$CONFIG_FILES platform.mk:platform/platform.mk.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; diff --git a/configure.ac b/configure.ac index 31b275f..4cf9b61 100644 --- a/configure.ac +++ b/configure.ac @@ -99,12 +99,6 @@ case "${BUILD_32BIT}" in ;; esac -AC_ARG_WITH([platform], - AS_HELP_STRING([--with-platform=spike], [Select the target platform]), - PLATFORM_NAME=$withval, - PLATFORM_NAME=spike) -AC_SUBST(PLATFORM_NAME, $PLATFORM_NAME) - AC_ARG_ENABLE([print-device-tree], AS_HELP_STRING([--enable-print-device-tree], [Print DTS when booting])) AS_IF([test "x$enable_print_device_tree" == "xyes"], [ AC_DEFINE([PK_PRINT_DEVICE_TREE],,[Define if the DTS is to be displayed]) @@ -122,7 +116,7 @@ AC_SUBST(install_subdir) # The '*' suffix indicates an optional subproject. The '**' suffix # indicates an optional subproject which is also the name of a group. -MCPPBS_SUBPROJECTS([ pk, bbl, softfloat, dummy_payload, machine, util, platform ]) +MCPPBS_SUBPROJECTS([ pk, bbl, softfloat, dummy_payload, machine, util ]) #------------------------------------------------------------------------- # MCPPBS subproject groups diff --git a/machine/htif.c b/machine/htif.c index fa3db53..44ec2dd 100644 --- a/machine/htif.c +++ b/machine/htif.c @@ -1,11 +1,21 @@ #include "htif.h" #include "atomic.h" #include "mtrap.h" +#include "fdt.h" +#include +extern uint64_t __htif_base; volatile uint64_t tohost __attribute__((section(".htif"))); volatile uint64_t fromhost __attribute__((section(".htif"))); volatile int htif_console_buf; static spinlock_t htif_lock = SPINLOCK_INIT; +uintptr_t htif; + +#define TOHOST(base_int) (uint64_t *)(base_int + TOHOST_OFFSET) +#define FROMHOST(base_int) (uint64_t *)(base_int + FROMHOST_OFFSET) + +#define TOHOST_OFFSET ((uintptr_t)tohost - (uintptr_t)__htif_base) +#define FROMHOST_OFFSET ((uintptr_t)fromhost - (uintptr_t)__htif_base) static void __check_fromhost() { @@ -85,3 +95,44 @@ void htif_poweroff() tohost = 1; } } + +struct htif_scan +{ + int compat; +}; + +static void htif_open(const struct fdt_scan_node *node, void *extra) +{ + struct htif_scan *scan = (struct htif_scan *)extra; + memset(scan, 0, sizeof(*scan)); +} + +static void htif_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct htif_scan *scan = (struct htif_scan *)extra; + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "ucb,htif0")) { + scan->compat = 1; + } +} + +static void htif_done(const struct fdt_scan_node *node, void *extra) +{ + struct htif_scan *scan = (struct htif_scan *)extra; + if (!scan->compat) return; + + htif = 1; +} + +void query_htif(uintptr_t fdt) +{ + struct fdt_cb cb; + struct htif_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = htif_open; + cb.prop = htif_prop; + cb.done = htif_done; + cb.extra = &scan; + + fdt_scan(fdt, &cb); +} diff --git a/machine/htif.h b/machine/htif.h index fa768d8..a96bf60 100644 --- a/machine/htif.h +++ b/machine/htif.h @@ -15,6 +15,8 @@ #define FROMHOST_CMD(fromhost_value) ((uint64_t)(fromhost_value) << 8 >> 56) #define FROMHOST_DATA(fromhost_value) ((uint64_t)(fromhost_value) << 16 >> 16) +extern uintptr_t htif; +void query_htif(uintptr_t dtb); void htif_console_putchar(uint8_t); int htif_console_getchar(); void htif_poweroff() __attribute__((noreturn)); diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 59d0eb4..dc8492f 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -1,6 +1,5 @@ machine_subproject_deps = \ softfloat \ - platform \ machine_hdrs = \ atomic.h \ diff --git a/machine/minit.c b/machine/minit.c index 5f98501..3623f38 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -5,8 +5,8 @@ #include "fdt.h" #include "uart.h" #include "finisher.h" -#include "platform_interface.h" #include "disabled_hart_mask.h" +#include "htif.h" #include #include @@ -141,6 +141,7 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb) { // Confirm console as early as possible query_uart(dtb); + query_htif(dtb); hart_init(); hls_init(0); // this might get called again from parse_config_string diff --git a/machine/mtrap.c b/machine/mtrap.c index dba3613..0f77def 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -8,7 +8,6 @@ #include "finisher.h" #include "fdt.h" #include "unprivileged_memory.h" -#include "platform_interface.h" #include "disabled_hart_mask.h" #include #include @@ -23,7 +22,7 @@ static uintptr_t mcall_console_putchar(uint8_t ch) { if (uart) { uart_putchar(ch); - } else if (platform__use_htif()) { + } else if (htif) { htif_console_putchar(ch); } return 0; @@ -33,7 +32,7 @@ void poweroff(uint16_t code) { printm("Power off\n"); finisher_exit(code); - if (platform__use_htif()) { + if (htif) { htif_poweroff(); } else { while (1); @@ -74,7 +73,7 @@ static uintptr_t mcall_console_getchar() { if (uart) { return uart_getchar(); - } else if (platform__use_htif()) { + } else if (htif) { return htif_console_getchar(); } else { return '\0'; diff --git a/pk/pk.lds b/pk/pk.lds index 5348635..f1f3f95 100644 --- a/pk/pk.lds +++ b/pk/pk.lds @@ -46,6 +46,7 @@ SECTIONS . = ALIGN(0x1000); .htif : { + PROVIDE( __htif_base = . ); *(.htif) } . = ALIGN(0x1000); diff --git a/pk/pk.mk.in b/pk/pk.mk.in index d4be009..3caa25d 100644 --- a/pk/pk.mk.in +++ b/pk/pk.mk.in @@ -1,5 +1,4 @@ pk_subproject_deps = \ - platform \ util \ softfloat \ machine \ diff --git a/platform/platform.ac b/platform/platform.ac deleted file mode 100644 index e69de29..0000000 diff --git a/platform/platform.mk.in b/platform/platform.mk.in deleted file mode 100644 index eded238..0000000 --- a/platform/platform.mk.in +++ /dev/null @@ -1,9 +0,0 @@ -platform_subproject_deps = - -platform_hdrs = \ - platform_interface.h - -platform_c_srcs = \ - @PLATFORM_NAME@.c - -platform_asm_srcs = diff --git a/platform/platform_interface.h b/platform/platform_interface.h deleted file mode 100644 index 203457d..0000000 --- a/platform/platform_interface.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef PLATFORM__PLATFORM_H -#define PLATFORM__PLATFORM_H - -#ifndef __ASSEMBLY__ - -/* This interface is designed to allow BBL/PK to be portable to multiple target - * platforms. The current interface has been hacked up based on SiFive's fork - * of pk that runs on our FPGA boards. The idea here is that rather than - * forking pk and touching things all over the tree, changes should be local to - * the target directory. - * - * This interface isn't meant to be stable or sane, just better than what we - * had before. - */ - -/* Returns a pointer to what's expected to be a staticly allocated logo string. - * This will be printed when BBL boots. */ -const char *platform__get_logo(void); - -/* Returns TRUE if it's valid to use the HTIF */ -int platform__use_htif(void); - -#endif - -#endif diff --git a/platform/sifive-vc707-devkit.c b/platform/sifive-vc707-devkit.c deleted file mode 100644 index bd27861..0000000 --- a/platform/sifive-vc707-devkit.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "platform_interface.h" - -static const char logo[] = -"\r\n" -" SIFIVE, INC.\r\n" -"\r\n" -" 5555555555555555555555555\r\n" -" 5555 5555\r\n" -" 5555 5555\r\n" -" 5555 5555\r\n" -" 5555 5555555555555555555555\r\n" -" 5555 555555555555555555555555\r\n" -" 5555 5555\r\n" -" 5555 5555\r\n" -" 5555 5555\r\n" -"5555555555555555555555555555 55555\r\n" -" 55555 555555555 55555\r\n" -" 55555 55555 55555\r\n" -" 55555 5 55555\r\n" -" 55555 55555\r\n" -" 55555 55555\r\n" -" 55555 55555\r\n" -" 55555 55555\r\n" -" 55555 55555\r\n" -" 555555555\r\n" -" 55555\r\n" -" 5\r\n" -"\r\n" -" SiFive RISC-V Coreplex\r\n"; - -const char *platform__get_logo(void) -{ - return logo; -} - -int platform__use_htif(void) -{ - return 0; -} diff --git a/platform/spike.c b/platform/spike.c deleted file mode 100644 index 159255f..0000000 --- a/platform/spike.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "platform_interface.h" - -static const char logo[] = -" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" -" vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" -"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" -"rr vvvvvvvvvvvvvvvvvvvvvv \n" -"rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" -"rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" -"rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" -"rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" -"rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" -"rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" -"rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" -"\n" -" INSTRUCTION SETS WANT TO BE FREE\n"; - -const char *platform__get_logo(void) -{ - return logo; -} - -int platform__use_htif(void) -{ - return 1; -} -- cgit v1.1 From 455608b465064eee862364796effeca91b4413f9 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Fri, 3 Nov 2017 17:02:06 -0700 Subject: Allow users to pick a logo --- Makefile.in | 2 +- bbl/bbl.ac | 4 ++++ bbl/bbl.mk.in | 1 + bbl/logo.c | 25 +------------------------ bbl/raw_logo.S | 7 +++++++ bbl/riscv_logo.txt | 23 +++++++++++++++++++++++ configure | 14 ++++++++++++++ 7 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 bbl/raw_logo.S create mode 100644 bbl/riscv_logo.txt diff --git a/Makefile.in b/Makefile.in index 7b9bb81..0d5e862 100644 --- a/Makefile.in +++ b/Makefile.in @@ -85,7 +85,7 @@ VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled)) CC := @CC@ READELF := @READELF@ OBJCOPY := @OBJCOPY@ -CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"bbl_payload\" +CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"bbl_payload\" -DBBL_LOGO_FILE=\"@BBL_LOGO_FILE@\" BBL_PAYLOAD := @BBL_PAYLOAD@ COMPILE := $(CC) -MMD -MP $(CFLAGS) \ $(sprojs_include) diff --git a/bbl/bbl.ac b/bbl/bbl.ac index 4b6a9f3..80d3b06 100644 --- a/bbl/bbl.ac +++ b/bbl/bbl.ac @@ -6,3 +6,7 @@ AS_IF([test "x$enable_logo" == "xyes"], [ AC_ARG_WITH([payload], AS_HELP_STRING([--with-payload], [Set ELF payload for bbl]), [AC_SUBST([BBL_PAYLOAD], $with_payload, [Kernel payload for bbl])], [AC_SUBST([BBL_PAYLOAD], [dummy_payload], [Kernel payload for bbl])]) + +AC_ARG_WITH([logo], AS_HELP_STRING([--with-logo], [Specify a better logo]), + [AC_SUBST([BBL_LOGO_FILE], $with_logo, [Logo for bbl])], + [AC_SUBST([BBL_LOGO_FILE], [riscv_logo.txt], [Logo for bbl])]) diff --git a/bbl/bbl.mk.in b/bbl/bbl.mk.in index 5abe2cd..0840859 100644 --- a/bbl/bbl.mk.in +++ b/bbl/bbl.mk.in @@ -12,6 +12,7 @@ bbl_c_srcs = \ bbl_asm_srcs = \ payload.S \ + raw_logo.S \ payload.o: bbl_payload diff --git a/bbl/logo.c b/bbl/logo.c index 673899d..fcd43ec 100644 --- a/bbl/logo.c +++ b/bbl/logo.c @@ -1,30 +1,7 @@ #include #include "mtrap.h" -static const char logo[] = -" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" -" vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" -"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" -"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" -"rr vvvvvvvvvvvvvvvvvvvvvv \n" -"rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" -"rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" -"rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" -"rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" -"rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" -"rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" -"rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" -"rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" -"\n" -" INSTRUCTION SETS WANT TO BE FREE\n"; +extern const char logo[]; void print_logo() { diff --git a/bbl/raw_logo.S b/bbl/raw_logo.S new file mode 100644 index 0000000..bddf8f4 --- /dev/null +++ b/bbl/raw_logo.S @@ -0,0 +1,7 @@ +#include "encoding.h" + + .section .rodata + .globl logo +logo: + .incbin BBL_LOGO_FILE + .byte 0 diff --git a/bbl/riscv_logo.txt b/bbl/riscv_logo.txt new file mode 100644 index 0000000..1f4c9f5 --- /dev/null +++ b/bbl/riscv_logo.txt @@ -0,0 +1,23 @@ + vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv +rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv +rr vvvvvvvvvvvvvvvvvvvvvv +rr vvvvvvvvvvvvvvvvvvvvvvvv rr +rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr +rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr +rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr +rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr +rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr +rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr +rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr +rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr +rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr +rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr + + INSTRUCTION SETS WANT TO BE FREE diff --git a/configure b/configure index e67142c..d7d3380 100755 --- a/configure +++ b/configure @@ -590,6 +590,7 @@ ac_subst_vars='LTLIBOBJS LIBOBJS subprojects_enabled subprojects +BBL_LOGO_FILE BBL_PAYLOAD install_subdir RISCV @@ -674,6 +675,7 @@ enable_optional_subprojects enable_vm enable_logo with_payload +with_logo enable_fp_emulation ' ac_precious_vars='build_alias @@ -1329,6 +1331,7 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-payload Set ELF payload for bbl + --with-logo Specify a better logo Some influential environment variables: CC C compiler command @@ -4254,6 +4257,17 @@ fi +# Check whether --with-logo was given. +if test "${with_logo+set}" = set; then : + withval=$with_logo; BBL_LOGO_FILE=$with_logo + +else + BBL_LOGO_FILE=riscv_logo.txt + +fi + + + -- cgit v1.1 From e22aaec27f16d5f36f4a2947a7b6d4de8c922b38 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Fri, 3 Nov 2017 17:16:02 -0700 Subject: Fix line endings in the logo --- Makefile.in | 2 +- bbl/bbl.mk.in | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 0d5e862..0268629 100644 --- a/Makefile.in +++ b/Makefile.in @@ -85,7 +85,7 @@ VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled)) CC := @CC@ READELF := @READELF@ OBJCOPY := @OBJCOPY@ -CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"bbl_payload\" -DBBL_LOGO_FILE=\"@BBL_LOGO_FILE@\" +CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"bbl_payload\" -DBBL_LOGO_FILE=\"bbl_logo_file\" BBL_PAYLOAD := @BBL_PAYLOAD@ COMPILE := $(CC) -MMD -MP $(CFLAGS) \ $(sprojs_include) diff --git a/bbl/bbl.mk.in b/bbl/bbl.mk.in index 0840859..2bc96e1 100644 --- a/bbl/bbl.mk.in +++ b/bbl/bbl.mk.in @@ -19,6 +19,11 @@ payload.o: bbl_payload bbl_payload: $(BBL_PAYLOAD) if $(READELF) -h $< 2> /dev/null > /dev/null; then $(OBJCOPY) -O binary $< $@; else cp $< $@; fi +raw_logo.o: bbl_logo_file + +bbl_logo_file: @BBL_LOGO_FILE@ + cat $^ | sed 's/$$/\r/' > $@ + bbl_test_srcs = bbl_install_prog_srcs = \ -- cgit v1.1 From 3d921d3c76db3af7b9ae0b5df0f0790f26222246 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 12 Dec 2017 00:38:34 -0800 Subject: Bump encoding.h --- machine/encoding.h | 43 +++++++++++++++++++++++-------------------- machine/vm.h | 4 ++-- pk/mmap.c | 2 +- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/machine/encoding.h b/machine/encoding.h index 1463801..c109ce1 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -23,6 +23,8 @@ #define MSTATUS_TW 0x00200000 #define MSTATUS_TSR 0x00400000 #define MSTATUS32_SD 0x80000000 +#define MSTATUS_UXL 0x0000000300000000 +#define MSTATUS_SXL 0x0000000C00000000 #define MSTATUS64_SD 0x8000000000000000 #define SSTATUS_UIE 0x00000001 @@ -35,6 +37,7 @@ #define SSTATUS_SUM 0x00040000 #define SSTATUS_MXR 0x00080000 #define SSTATUS32_SD 0x80000000 +#define SSTATUS_UXL 0x0000000300000000 #define SSTATUS64_SD 0x8000000000000000 #define DCSR_XDEBUGVER (3U<<30) @@ -110,19 +113,19 @@ #define PRV_H 2 #define PRV_M 3 -#define SPTBR32_MODE 0x80000000 -#define SPTBR32_ASID 0x7FC00000 -#define SPTBR32_PPN 0x003FFFFF -#define SPTBR64_MODE 0xF000000000000000 -#define SPTBR64_ASID 0x0FFFF00000000000 -#define SPTBR64_PPN 0x00000FFFFFFFFFFF +#define SATP32_MODE 0x80000000 +#define SATP32_ASID 0x7FC00000 +#define SATP32_PPN 0x003FFFFF +#define SATP64_MODE 0xF000000000000000 +#define SATP64_ASID 0x0FFFF00000000000 +#define SATP64_PPN 0x00000FFFFFFFFFFF -#define SPTBR_MODE_OFF 0 -#define SPTBR_MODE_SV32 1 -#define SPTBR_MODE_SV39 8 -#define SPTBR_MODE_SV48 9 -#define SPTBR_MODE_SV57 10 -#define SPTBR_MODE_SV64 11 +#define SATP_MODE_OFF 0 +#define SATP_MODE_SV32 1 +#define SATP_MODE_SV39 8 +#define SATP_MODE_SV48 9 +#define SATP_MODE_SV57 10 +#define SATP_MODE_SV64 11 #define PMP_R 0x01 #define PMP_W 0x02 @@ -174,12 +177,12 @@ # define MSTATUS_SD MSTATUS64_SD # define SSTATUS_SD SSTATUS64_SD # define RISCV_PGLEVEL_BITS 9 -# define SPTBR_MODE SPTBR64_MODE +# define SATP_MODE SATP64_MODE #else # define MSTATUS_SD MSTATUS32_SD # define SSTATUS_SD SSTATUS32_SD # define RISCV_PGLEVEL_BITS 10 -# define SPTBR_MODE SPTBR32_MODE +# define SATP_MODE SATP32_MODE #endif #define RISCV_PGSHIFT 12 #define RISCV_PGSIZE (1 << RISCV_PGSHIFT) @@ -787,9 +790,9 @@ #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 #define CSR_SCAUSE 0x142 -#define CSR_SBADADDR 0x143 +#define CSR_STVAL 0x143 #define CSR_SIP 0x144 -#define CSR_SPTBR 0x180 +#define CSR_SATP 0x180 #define CSR_MSTATUS 0x300 #define CSR_MISA 0x301 #define CSR_MEDELEG 0x302 @@ -800,7 +803,7 @@ #define CSR_MSCRATCH 0x340 #define CSR_MEPC 0x341 #define CSR_MCAUSE 0x342 -#define CSR_MBADADDR 0x343 +#define CSR_MTVAL 0x343 #define CSR_MIP 0x344 #define CSR_PMPCFG0 0x3a0 #define CSR_PMPCFG1 0x3a1 @@ -1279,9 +1282,9 @@ DECLARE_CSR(scounteren, CSR_SCOUNTEREN) DECLARE_CSR(sscratch, CSR_SSCRATCH) DECLARE_CSR(sepc, CSR_SEPC) DECLARE_CSR(scause, CSR_SCAUSE) -DECLARE_CSR(sbadaddr, CSR_SBADADDR) +DECLARE_CSR(stval, CSR_STVAL) DECLARE_CSR(sip, CSR_SIP) -DECLARE_CSR(sptbr, CSR_SPTBR) +DECLARE_CSR(satp, CSR_SATP) DECLARE_CSR(mstatus, CSR_MSTATUS) DECLARE_CSR(misa, CSR_MISA) DECLARE_CSR(medeleg, CSR_MEDELEG) @@ -1292,7 +1295,7 @@ DECLARE_CSR(mcounteren, CSR_MCOUNTEREN) DECLARE_CSR(mscratch, CSR_MSCRATCH) DECLARE_CSR(mepc, CSR_MEPC) DECLARE_CSR(mcause, CSR_MCAUSE) -DECLARE_CSR(mbadaddr, CSR_MBADADDR) +DECLARE_CSR(mtval, CSR_MTVAL) DECLARE_CSR(mip, CSR_MIP) DECLARE_CSR(pmpcfg0, CSR_PMPCFG0) DECLARE_CSR(pmpcfg1, CSR_PMPCFG1) diff --git a/machine/vm.h b/machine/vm.h index 29f4535..986f301 100644 --- a/machine/vm.h +++ b/machine/vm.h @@ -6,11 +6,11 @@ #define MEGAPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS)) #if __riscv_xlen == 64 -# define SPTBR_MODE_CHOICE INSERT_FIELD(0, SPTBR64_MODE, SPTBR_MODE_SV39) +# define SATP_MODE_CHOICE INSERT_FIELD(0, SATP64_MODE, SATP_MODE_SV39) # define VA_BITS 39 # define GIGAPAGE_SIZE (MEGAPAGE_SIZE << RISCV_PGLEVEL_BITS) #else -# define SPTBR_MODE_CHOICE INSERT_FIELD(0, SPTBR32_MODE, SPTBR_MODE_SV32) +# define SATP_MODE_CHOICE INSERT_FIELD(0, SATP32_MODE, SATP_MODE_SV32) # define VA_BITS 32 #endif diff --git a/pk/mmap.c b/pk/mmap.c index 1b995f4..3b52c23 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -411,7 +411,7 @@ uintptr_t pk_vm_init() current.stack_top = stack_bottom + stack_size; flush_tlb(); - write_csr(sptbr, ((uintptr_t)root_page_table >> RISCV_PGSHIFT) | SPTBR_MODE_CHOICE); + write_csr(sptbr, ((uintptr_t)root_page_table >> RISCV_PGSHIFT) | SATP_MODE_CHOICE); uintptr_t kernel_stack_top = __page_alloc() + RISCV_PGSIZE; return kernel_stack_top; -- cgit v1.1