Index: head/sys/riscv/include/db_machdep.h
===================================================================
--- head/sys/riscv/include/db_machdep.h (revision 367019)
+++ head/sys/riscv/include/db_machdep.h (revision 367020)
@@ -1,94 +1,94 @@
/*-
* Copyright (c) 2015-2016 Ruslan Bukin
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_DB_MACHDEP_H_
#define _MACHINE_DB_MACHDEP_H_
#include
#include
#include
-#define T_BREAKPOINT (EXCP_BREAKPOINT)
+#define T_BREAKPOINT (SCAUSE_BREAKPOINT)
#define T_WATCHPOINT (0)
typedef vm_offset_t db_addr_t;
typedef long db_expr_t;
#define PC_REGS() ((db_addr_t)kdb_frame->tf_sepc)
#define BKPT_INST (0x00100073)
#define BKPT_SIZE (INSN_SIZE)
#define BKPT_SET(inst) (BKPT_INST)
#define BKPT_SKIP do { \
uint32_t _instr; \
\
_instr = db_get_value(PC_REGS(), sizeof(uint32_t), FALSE); \
if ((_instr & 0x3) == 0x3) \
kdb_frame->tf_sepc += 4; /* ebreak */ \
else \
kdb_frame->tf_sepc += 2; /* c.ebreak */ \
} while (0)
#define db_clear_single_step kdb_cpu_clear_singlestep
#define db_set_single_step kdb_cpu_set_singlestep
#define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT)
#define IS_WATCHPOINT_TRAP(type, code) (type == T_WATCHPOINT)
#define inst_trap_return(ins) (ins == 0x10000073) /* eret */
#define inst_return(ins) (ins == 0x00008067) /* ret */
#define inst_call(ins) (((ins) & 0x7f) == 111 || \
((ins) & 0x7f) == 103) /* jal, jalr */
#define inst_load(ins) ({ \
uint32_t tmp_instr = db_get_value(PC_REGS(), sizeof(uint32_t), FALSE); \
is_load_instr(tmp_instr); \
})
#define inst_store(ins) ({ \
uint32_t tmp_instr = db_get_value(PC_REGS(), sizeof(uint32_t), FALSE); \
is_store_instr(tmp_instr); \
})
#define is_load_instr(ins) (((ins) & 0x7f) == 3)
#define is_store_instr(ins) (((ins) & 0x7f) == 35)
#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + 4))
#define DB_ELFSIZE 64
#endif /* !_MACHINE_DB_MACHDEP_H_ */
Index: head/sys/riscv/include/riscvreg.h
===================================================================
--- head/sys/riscv/include/riscvreg.h (revision 367019)
+++ head/sys/riscv/include/riscvreg.h (revision 367020)
@@ -1,251 +1,249 @@
/*-
* Copyright (c) 2015-2017 Ruslan Bukin
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_RISCVREG_H_
#define _MACHINE_RISCVREG_H_
-#define EXCP_MASK (~EXCP_INTR)
-#define EXCP_MISALIGNED_FETCH 0
-#define EXCP_FAULT_FETCH 1
-#define EXCP_ILLEGAL_INSTRUCTION 2
-#define EXCP_BREAKPOINT 3
-#define EXCP_MISALIGNED_LOAD 4
-#define EXCP_FAULT_LOAD 5
-#define EXCP_MISALIGNED_STORE 6
-#define EXCP_FAULT_STORE 7
-#define EXCP_USER_ECALL 8
-#define EXCP_SUPERVISOR_ECALL 9
-#define EXCP_HYPERVISOR_ECALL 10
-#define EXCP_MACHINE_ECALL 11
-#define EXCP_INST_PAGE_FAULT 12
-#define EXCP_LOAD_PAGE_FAULT 13
-#define EXCP_STORE_PAGE_FAULT 15
-#define EXCP_INTR (1ul << 63)
+#define SCAUSE_INTR (1ul << 63)
+#define SCAUSE_CODE (~SCAUSE_INTR)
+#define SCAUSE_INST_MISALIGNED 0
+#define SCAUSE_INST_ACCESS_FAULT 1
+#define SCAUSE_ILLEGAL_INSTRUCTION 2
+#define SCAUSE_BREAKPOINT 3
+#define SCAUSE_LOAD_MISALIGNED 4
+#define SCAUSE_LOAD_ACCESS_FAULT 5
+#define SCAUSE_STORE_MISALIGNED 6
+#define SCAUSE_STORE_ACCESS_FAULT 7
+#define SCAUSE_ECALL_USER 8
+#define SCAUSE_ECALL_SUPERVISOR 9
+#define SCAUSE_INST_PAGE_FAULT 12
+#define SCAUSE_LOAD_PAGE_FAULT 13
+#define SCAUSE_STORE_PAGE_FAULT 15
#define SSTATUS_UIE (1 << 0)
#define SSTATUS_SIE (1 << 1)
#define SSTATUS_UPIE (1 << 4)
#define SSTATUS_SPIE (1 << 5)
#define SSTATUS_SPIE_SHIFT 5
#define SSTATUS_SPP (1 << 8)
#define SSTATUS_SPP_SHIFT 8
#define SSTATUS_FS_SHIFT 13
#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_CLEAN (0x2 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_DIRTY (0x3 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_MASK (0x3 << SSTATUS_FS_SHIFT)
#define SSTATUS_XS_SHIFT 15
#define SSTATUS_XS_MASK (0x3 << SSTATUS_XS_SHIFT)
#define SSTATUS_SUM (1 << 18)
#if __riscv_xlen == 64
#define SSTATUS_SD (1ul << 63)
#else
#define SSTATUS_SD (1 << 31)
#endif
#define MSTATUS_UIE (1 << 0)
#define MSTATUS_SIE (1 << 1)
#define MSTATUS_HIE (1 << 2)
#define MSTATUS_MIE (1 << 3)
#define MSTATUS_UPIE (1 << 4)
#define MSTATUS_SPIE (1 << 5)
#define MSTATUS_SPIE_SHIFT 5
#define MSTATUS_HPIE (1 << 6)
#define MSTATUS_MPIE (1 << 7)
#define MSTATUS_MPIE_SHIFT 7
#define MSTATUS_SPP (1 << 8)
#define MSTATUS_SPP_SHIFT 8
#define MSTATUS_HPP_MASK 0x3
#define MSTATUS_HPP_SHIFT 9
#define MSTATUS_MPP_MASK 0x3
#define MSTATUS_MPP_SHIFT 11
#define MSTATUS_FS_MASK 0x3
#define MSTATUS_FS_SHIFT 13
#define MSTATUS_XS_MASK 0x3
#define MSTATUS_XS_SHIFT 15
#define MSTATUS_MPRV (1 << 17)
#define MSTATUS_PUM (1 << 18)
#define MSTATUS_VM_MASK 0x1f
#define MSTATUS_VM_SHIFT 24
#define MSTATUS_VM_MBARE 0
#define MSTATUS_VM_MBB 1
#define MSTATUS_VM_MBBID 2
#define MSTATUS_VM_SV32 8
#define MSTATUS_VM_SV39 9
#define MSTATUS_VM_SV48 10
#define MSTATUS_VM_SV57 11
#define MSTATUS_VM_SV64 12
#if __riscv_xlen == 64
#define MSTATUS_SD (1ul << 63)
#else
#define MSTATUS_SD (1 << 31)
#endif
#define MSTATUS_PRV_U 0 /* user */
#define MSTATUS_PRV_S 1 /* supervisor */
#define MSTATUS_PRV_H 2 /* hypervisor */
#define MSTATUS_PRV_M 3 /* machine */
#define MIE_USIE (1 << 0)
#define MIE_SSIE (1 << 1)
#define MIE_HSIE (1 << 2)
#define MIE_MSIE (1 << 3)
#define MIE_UTIE (1 << 4)
#define MIE_STIE (1 << 5)
#define MIE_HTIE (1 << 6)
#define MIE_MTIE (1 << 7)
#define MIP_USIP (1 << 0)
#define MIP_SSIP (1 << 1)
#define MIP_HSIP (1 << 2)
#define MIP_MSIP (1 << 3)
#define MIP_UTIP (1 << 4)
#define MIP_STIP (1 << 5)
#define MIP_HTIP (1 << 6)
#define MIP_MTIP (1 << 7)
#define SIE_USIE (1 << 0)
#define SIE_SSIE (1 << 1)
#define SIE_UTIE (1 << 4)
#define SIE_STIE (1 << 5)
#define SIE_UEIE (1 << 8)
#define SIE_SEIE (1 << 9)
#define MIP_SEIP (1 << 9)
/* Note: sip register has no SIP_STIP bit in Spike simulator */
#define SIP_SSIP (1 << 1)
#define SIP_STIP (1 << 5)
#define SATP_PPN_S 0
#define SATP_PPN_M (0xfffffffffff << SATP_PPN_S)
#define SATP_ASID_S 44
#define SATP_ASID_M (0xffff << SATP_ASID_S)
#define SATP_MODE_S 60
#define SATP_MODE_M (0xf << SATP_MODE_S)
#define SATP_MODE_SV39 (8ULL << SATP_MODE_S)
#define SATP_MODE_SV48 (9ULL << SATP_MODE_S)
#define XLEN __riscv_xlen
#define XLEN_BYTES (XLEN / 8)
#define INSN_SIZE 4
#define INSN_C_SIZE 2
#define X_RA 1
#define X_SP 2
#define X_GP 3
#define X_TP 4
#define X_T0 5
#define X_T1 6
#define X_T2 7
#define X_T3 28
#define RD_SHIFT 7
#define RD_MASK (0x1f << RD_SHIFT)
#define RS1_SHIFT 15
#define RS1_MASK (0x1f << RS1_SHIFT)
#define RS1_SP (X_SP << RS1_SHIFT)
#define RS2_SHIFT 20
#define RS2_MASK (0x1f << RS2_SHIFT)
#define RS2_RA (X_RA << RS2_SHIFT)
#define IMM_SHIFT 20
#define IMM_MASK (0xfff << IMM_SHIFT)
#define RS2_C_SHIFT 2
#define RS2_C_MASK (0x1f << RS2_C_SHIFT)
#define RS2_C_RA (X_RA << RS2_C_SHIFT)
#define CSR_ZIMM(val) \
(__builtin_constant_p(val) && ((u_long)(val) < 32))
#define csr_swap(csr, val) \
({ if (CSR_ZIMM(val)) \
__asm __volatile("csrrwi %0, " #csr ", %1" \
: "=r" (val) : "i" (val)); \
else \
__asm __volatile("csrrw %0, " #csr ", %1" \
: "=r" (val) : "r" (val)); \
val; \
})
#define csr_write(csr, val) \
({ if (CSR_ZIMM(val)) \
__asm __volatile("csrwi " #csr ", %0" :: "i" (val)); \
else \
__asm __volatile("csrw " #csr ", %0" :: "r" (val)); \
})
#define csr_set(csr, val) \
({ if (CSR_ZIMM(val)) \
__asm __volatile("csrsi " #csr ", %0" :: "i" (val)); \
else \
__asm __volatile("csrs " #csr ", %0" :: "r" (val)); \
})
#define csr_clear(csr, val) \
({ if (CSR_ZIMM(val)) \
__asm __volatile("csrci " #csr ", %0" :: "i" (val)); \
else \
__asm __volatile("csrc " #csr ", %0" :: "r" (val)); \
})
#define csr_read(csr) \
({ u_long val; \
__asm __volatile("csrr %0, " #csr : "=r" (val)); \
val; \
})
#if __riscv_xlen == 32
#define csr_read64(csr) \
({ uint64_t val; \
uint32_t high, low; \
__asm __volatile("1: " \
"csrr t0, " #csr "h\n" \
"csrr %0, " #csr "\n" \
"csrr %1, " #csr "h\n" \
"bne t0, %1, 1b" \
: "=r" (low), "=r" (high) \
: \
: "t0"); \
val = (low | ((uint64_t)high << 32)); \
val; \
})
#else
#define csr_read64(csr) ((uint64_t)csr_read(csr))
#endif
#endif /* !_MACHINE_RISCVREG_H_ */
Index: head/sys/riscv/riscv/db_trace.c
===================================================================
--- head/sys/riscv/riscv/db_trace.c (revision 367019)
+++ head/sys/riscv/riscv/db_trace.c (revision 367020)
@@ -1,154 +1,154 @@
/*-
* Copyright (c) 2015 The FreeBSD Foundation
* Copyright (c) 2016 Ruslan Bukin
* All rights reserved.
* Copyright (c) 2020 John Baldwin
*
* Portions of this software were developed by Semihalf under
* the sponsorship of the FreeBSD Foundation.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
void
db_md_list_watchpoints()
{
}
int
db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
{
return (0);
}
int
db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
{
return (0);
}
static void
db_stack_trace_cmd(struct unwind_state *frame)
{
const char *name;
db_expr_t offset;
db_expr_t value;
c_db_sym_t sym;
uint64_t pc;
while (1) {
pc = frame->pc;
sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
if (sym == C_DB_SYM_NULL) {
value = 0;
name = "(null)";
} else
db_symbol_values(sym, &name, &value);
db_printf("%s() at ", name);
db_printsym(frame->pc, DB_STGY_PROC);
db_printf("\n");
if (strcmp(name, "cpu_exception_handler_supervisor") == 0 ||
strcmp(name, "cpu_exception_handler_user") == 0) {
struct trapframe *tf;
tf = (struct trapframe *)(uintptr_t)frame->sp;
- if (tf->tf_scause & EXCP_INTR)
+ if ((tf->tf_scause & SCAUSE_INTR) != 0)
db_printf("--- interrupt %ld\n",
- tf->tf_scause & EXCP_MASK);
+ tf->tf_scause & SCAUSE_CODE);
else
db_printf("--- exception %ld, tval = %#lx\n",
- tf->tf_scause & EXCP_MASK,
+ tf->tf_scause & SCAUSE_CODE,
tf->tf_stval);
frame->sp = tf->tf_sp;
frame->fp = tf->tf_s[0];
frame->pc = tf->tf_sepc;
if (!INKERNEL(frame->fp))
break;
continue;
}
if (strcmp(name, "fork_trampoline") == 0)
break;
if (unwind_frame(frame) < 0)
break;
}
}
int
db_trace_thread(struct thread *thr, int count)
{
struct unwind_state frame;
struct pcb *ctx;
ctx = kdb_thr_ctx(thr);
frame.sp = ctx->pcb_sp;
frame.fp = ctx->pcb_s[0];
frame.pc = ctx->pcb_ra;
db_stack_trace_cmd(&frame);
return (0);
}
void
db_trace_self(void)
{
struct unwind_state frame;
uintptr_t sp;
__asm __volatile("mv %0, sp" : "=&r" (sp));
frame.sp = sp;
frame.fp = (uintptr_t)__builtin_frame_address(0);
frame.pc = (uintptr_t)db_trace_self;
db_stack_trace_cmd(&frame);
}
Index: head/sys/riscv/riscv/intr_machdep.c
===================================================================
--- head/sys/riscv/riscv/intr_machdep.c (revision 367019)
+++ head/sys/riscv/riscv/intr_machdep.c (revision 367020)
@@ -1,274 +1,274 @@
/*-
* Copyright (c) 2015-2017 Ruslan Bukin
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef SMP
#include
#endif
void intr_irq_handler(struct trapframe *tf);
struct intc_irqsrc {
struct intr_irqsrc isrc;
u_int irq;
};
struct intc_irqsrc isrcs[INTC_NIRQS];
static void
riscv_mask_irq(void *source)
{
int irq;
irq = (int)(uintptr_t)source;
switch (irq) {
case IRQ_TIMER_SUPERVISOR:
csr_clear(sie, SIE_STIE);
break;
case IRQ_SOFTWARE_USER:
csr_clear(sie, SIE_USIE);
break;
case IRQ_SOFTWARE_SUPERVISOR:
csr_clear(sie, SIE_SSIE);
break;
default:
panic("Unknown irq %d\n", irq);
}
}
static void
riscv_unmask_irq(void *source)
{
int irq;
irq = (int)(uintptr_t)source;
switch (irq) {
case IRQ_TIMER_SUPERVISOR:
csr_set(sie, SIE_STIE);
break;
case IRQ_SOFTWARE_USER:
csr_set(sie, SIE_USIE);
break;
case IRQ_SOFTWARE_SUPERVISOR:
csr_set(sie, SIE_SSIE);
break;
default:
panic("Unknown irq %d\n", irq);
}
}
int
riscv_setup_intr(const char *name, driver_filter_t *filt,
void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
{
struct intr_irqsrc *isrc;
int error;
if (irq < 0 || irq >= INTC_NIRQS)
panic("%s: unknown intr %d", __func__, irq);
isrc = &isrcs[irq].isrc;
if (isrc->isrc_event == NULL) {
error = intr_event_create(&isrc->isrc_event, isrc, 0, irq,
riscv_mask_irq, riscv_unmask_irq, NULL, NULL, "int%d", irq);
if (error)
return (error);
riscv_unmask_irq((void*)(uintptr_t)irq);
}
error = intr_event_add_handler(isrc->isrc_event, name,
filt, handler, arg, intr_priority(flags), flags, cookiep);
if (error) {
printf("Failed to setup intr: %d\n", irq);
return (error);
}
return (0);
}
int
riscv_teardown_intr(void *ih)
{
/* TODO */
return (0);
}
void
riscv_cpu_intr(struct trapframe *frame)
{
struct intr_irqsrc *isrc;
int active_irq;
- KASSERT(frame->tf_scause & EXCP_INTR,
+ KASSERT((frame->tf_scause & SCAUSE_INTR) != 0,
("riscv_cpu_intr: wrong frame passed"));
- active_irq = frame->tf_scause & EXCP_MASK;
+ active_irq = frame->tf_scause & SCAUSE_CODE;
switch (active_irq) {
case IRQ_SOFTWARE_USER:
case IRQ_SOFTWARE_SUPERVISOR:
case IRQ_TIMER_SUPERVISOR:
critical_enter();
isrc = &isrcs[active_irq].isrc;
if (intr_isrc_dispatch(isrc, frame) != 0)
printf("stray interrupt %d\n", active_irq);
critical_exit();
break;
case IRQ_EXTERNAL_SUPERVISOR:
intr_irq_handler(frame);
break;
}
}
#ifdef SMP
void
riscv_setup_ipihandler(driver_filter_t *filt)
{
riscv_setup_intr("ipi", filt, NULL, NULL, IRQ_SOFTWARE_SUPERVISOR,
INTR_TYPE_MISC, NULL);
}
void
riscv_unmask_ipi(void)
{
csr_set(sie, SIE_SSIE);
}
/* Sending IPI */
static void
ipi_send(struct pcpu *pc, int ipi)
{
u_long mask;
CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, pc->pc_cpuid, ipi);
atomic_set_32(&pc->pc_pending_ipis, ipi);
mask = (1 << pc->pc_hart);
sbi_send_ipi(&mask);
CTR1(KTR_SMP, "%s: sent", __func__);
}
void
ipi_all_but_self(u_int ipi)
{
cpuset_t other_cpus;
other_cpus = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &other_cpus);
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
ipi_selected(other_cpus, ipi);
}
void
ipi_cpu(int cpu, u_int ipi)
{
cpuset_t cpus;
CPU_ZERO(&cpus);
CPU_SET(cpu, &cpus);
ipi_send(cpuid_to_pcpu[cpu], ipi);
}
void
ipi_selected(cpuset_t cpus, u_int ipi)
{
struct pcpu *pc;
u_long mask;
CTR1(KTR_SMP, "ipi_selected: ipi: %x", ipi);
mask = 0;
STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (CPU_ISSET(pc->pc_cpuid, &cpus)) {
CTR3(KTR_SMP, "%s: pc: %p, ipi: %x\n", __func__, pc,
ipi);
atomic_set_32(&pc->pc_pending_ipis, ipi);
mask |= (1 << pc->pc_hart);
}
}
sbi_send_ipi(&mask);
}
#endif
/* Interrupt machdep initialization routine. */
static void
intc_init(void *dummy __unused)
{
int error;
int i;
for (i = 0; i < INTC_NIRQS; i++) {
isrcs[i].irq = i;
error = intr_isrc_register(&isrcs[i].isrc, NULL,
0, "intc,%u", i);
if (error != 0)
printf("Can't register interrupt %d\n", i);
}
}
SYSINIT(intc_init, SI_SUB_INTR, SI_ORDER_MIDDLE, intc_init, NULL);
Index: head/sys/riscv/riscv/trap.c
===================================================================
--- head/sys/riscv/riscv/trap.c (revision 367019)
+++ head/sys/riscv/riscv/trap.c (revision 367020)
@@ -1,389 +1,389 @@
/*-
* Copyright (c) 2015-2018 Ruslan Bukin
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef KDB
#include
#endif
#include
#include
#include
#include
#include
#include
#ifdef FPE
#include
#endif
#include
#include
#include
#include
#include
#ifdef KDTRACE_HOOKS
#include
#endif
int (*dtrace_invop_jump_addr)(struct trapframe *);
extern register_t fsu_intr_fault;
/* Called from exception.S */
void do_trap_supervisor(struct trapframe *);
void do_trap_user(struct trapframe *);
static __inline void
call_trapsignal(struct thread *td, int sig, int code, void *addr, int trapno)
{
ksiginfo_t ksi;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = sig;
ksi.ksi_code = code;
ksi.ksi_addr = addr;
ksi.ksi_trapno = trapno;
trapsignal(td, &ksi);
}
int
cpu_fetch_syscall_args(struct thread *td)
{
struct proc *p;
register_t *ap, *dst_ap;
struct syscall_args *sa;
p = td->td_proc;
sa = &td->td_sa;
ap = &td->td_frame->tf_a[0];
dst_ap = &sa->args[0];
sa->code = td->td_frame->tf_t[0];
if (__predict_false(sa->code == SYS_syscall || sa->code == SYS___syscall)) {
sa->code = *ap++;
} else {
*dst_ap++ = *ap++;
}
if (__predict_false(sa->code >= p->p_sysent->sv_size))
sa->callp = &p->p_sysent->sv_table[0];
else
sa->callp = &p->p_sysent->sv_table[sa->code];
KASSERT(sa->callp->sy_narg <= nitems(sa->args),
("Syscall %d takes too many arguments", sa->code));
memcpy(dst_ap, ap, (NARGREG - 1) * sizeof(register_t));
td->td_retval[0] = 0;
td->td_retval[1] = 0;
return (0);
}
#include "../../kern/subr_syscall.c"
static void
dump_regs(struct trapframe *frame)
{
int n;
int i;
n = nitems(frame->tf_t);
for (i = 0; i < n; i++)
printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]);
n = nitems(frame->tf_s);
for (i = 0; i < n; i++)
printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]);
n = nitems(frame->tf_a);
for (i = 0; i < n; i++)
printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]);
printf("ra == 0x%016lx\n", frame->tf_ra);
printf("sp == 0x%016lx\n", frame->tf_sp);
printf("gp == 0x%016lx\n", frame->tf_gp);
printf("tp == 0x%016lx\n", frame->tf_tp);
printf("sepc == 0x%016lx\n", frame->tf_sepc);
printf("sstatus == 0x%016lx\n", frame->tf_sstatus);
}
static void
ecall_handler(void)
{
struct thread *td;
td = curthread;
syscallenter(td);
syscallret(td);
}
static void
page_fault_handler(struct trapframe *frame, int usermode)
{
struct vm_map *map;
uint64_t stval;
struct thread *td;
struct pcb *pcb;
vm_prot_t ftype;
vm_offset_t va;
struct proc *p;
int error, sig, ucode;
#ifdef KDB
if (kdb_active) {
kdb_reenter();
return;
}
#endif
td = curthread;
p = td->td_proc;
pcb = td->td_pcb;
stval = frame->tf_stval;
if (td->td_critnest != 0 || td->td_intr_nesting_level != 0 ||
WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
"Kernel page fault") != 0)
goto fatal;
if (usermode) {
map = &td->td_proc->p_vmspace->vm_map;
} else {
/*
* Enable interrupts for the duration of the page fault. For
* user faults this was done already in do_trap_user().
*/
intr_enable();
if (stval >= VM_MAX_USER_ADDRESS) {
map = kernel_map;
} else {
if (pcb->pcb_onfault == 0)
goto fatal;
map = &td->td_proc->p_vmspace->vm_map;
}
}
va = trunc_page(stval);
- if (frame->tf_scause == EXCP_STORE_PAGE_FAULT) {
+ if (frame->tf_scause == SCAUSE_STORE_PAGE_FAULT) {
ftype = VM_PROT_WRITE;
- } else if (frame->tf_scause == EXCP_INST_PAGE_FAULT) {
+ } else if (frame->tf_scause == SCAUSE_INST_PAGE_FAULT) {
ftype = VM_PROT_EXECUTE;
} else {
ftype = VM_PROT_READ;
}
if (pmap_fault_fixup(map->pmap, va, ftype))
goto done;
error = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, &sig, &ucode);
if (error != KERN_SUCCESS) {
if (usermode) {
call_trapsignal(td, sig, ucode, (void *)stval,
- frame->tf_scause & EXCP_MASK);
+ frame->tf_scause & SCAUSE_CODE);
} else {
if (pcb->pcb_onfault != 0) {
frame->tf_a[0] = error;
frame->tf_sepc = pcb->pcb_onfault;
return;
}
goto fatal;
}
}
done:
if (usermode)
userret(td, frame);
return;
fatal:
dump_regs(frame);
panic("Fatal page fault at %#lx: %#016lx", frame->tf_sepc, stval);
}
void
do_trap_supervisor(struct trapframe *frame)
{
uint64_t exception;
/* Ensure we came from supervisor mode, interrupts disabled */
KASSERT((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) ==
SSTATUS_SPP, ("Came from S mode with interrupts enabled"));
- exception = frame->tf_scause & EXCP_MASK;
- if (frame->tf_scause & EXCP_INTR) {
+ exception = frame->tf_scause & SCAUSE_CODE;
+ if ((frame->tf_scause & SCAUSE_INTR) != 0) {
/* Interrupt */
riscv_cpu_intr(frame);
return;
}
#ifdef KDTRACE_HOOKS
if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, exception))
return;
#endif
CTR3(KTR_TRAP, "do_trap_supervisor: curthread: %p, sepc: %lx, frame: %p",
curthread, frame->tf_sepc, frame);
switch (exception) {
- case EXCP_FAULT_LOAD:
- case EXCP_FAULT_STORE:
- case EXCP_FAULT_FETCH:
+ case SCAUSE_LOAD_ACCESS_FAULT:
+ case SCAUSE_STORE_ACCESS_FAULT:
+ case SCAUSE_INST_ACCESS_FAULT:
dump_regs(frame);
panic("Memory access exception at 0x%016lx\n", frame->tf_sepc);
break;
- case EXCP_STORE_PAGE_FAULT:
- case EXCP_LOAD_PAGE_FAULT:
- case EXCP_INST_PAGE_FAULT:
+ case SCAUSE_STORE_PAGE_FAULT:
+ case SCAUSE_LOAD_PAGE_FAULT:
+ case SCAUSE_INST_PAGE_FAULT:
page_fault_handler(frame, 0);
break;
- case EXCP_BREAKPOINT:
+ case SCAUSE_BREAKPOINT:
#ifdef KDTRACE_HOOKS
if (dtrace_invop_jump_addr != NULL &&
dtrace_invop_jump_addr(frame) == 0)
break;
#endif
#ifdef KDB
kdb_trap(exception, 0, frame);
#else
dump_regs(frame);
panic("No debugger in kernel.\n");
#endif
break;
- case EXCP_ILLEGAL_INSTRUCTION:
+ case SCAUSE_ILLEGAL_INSTRUCTION:
dump_regs(frame);
panic("Illegal instruction at 0x%016lx\n", frame->tf_sepc);
break;
default:
dump_regs(frame);
panic("Unknown kernel exception %lx trap value %lx\n",
exception, frame->tf_stval);
}
}
void
do_trap_user(struct trapframe *frame)
{
uint64_t exception;
struct thread *td;
struct pcb *pcb;
td = curthread;
pcb = td->td_pcb;
KASSERT(td->td_frame == frame,
("%s: td_frame %p != frame %p", __func__, td->td_frame, frame));
/* Ensure we came from usermode, interrupts disabled */
KASSERT((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == 0,
("Came from U mode with interrupts enabled"));
- exception = frame->tf_scause & EXCP_MASK;
- if (frame->tf_scause & EXCP_INTR) {
+ exception = frame->tf_scause & SCAUSE_CODE;
+ if ((frame->tf_scause & SCAUSE_INTR) != 0) {
/* Interrupt */
riscv_cpu_intr(frame);
return;
}
intr_enable();
CTR3(KTR_TRAP, "do_trap_user: curthread: %p, sepc: %lx, frame: %p",
curthread, frame->tf_sepc, frame);
switch (exception) {
- case EXCP_FAULT_LOAD:
- case EXCP_FAULT_STORE:
- case EXCP_FAULT_FETCH:
+ case SCAUSE_LOAD_ACCESS_FAULT:
+ case SCAUSE_STORE_ACCESS_FAULT:
+ case SCAUSE_INST_ACCESS_FAULT:
call_trapsignal(td, SIGBUS, BUS_ADRERR, (void *)frame->tf_sepc,
exception);
userret(td, frame);
break;
- case EXCP_STORE_PAGE_FAULT:
- case EXCP_LOAD_PAGE_FAULT:
- case EXCP_INST_PAGE_FAULT:
+ case SCAUSE_STORE_PAGE_FAULT:
+ case SCAUSE_LOAD_PAGE_FAULT:
+ case SCAUSE_INST_PAGE_FAULT:
page_fault_handler(frame, 1);
break;
- case EXCP_USER_ECALL:
+ case SCAUSE_ECALL_USER:
frame->tf_sepc += 4; /* Next instruction */
ecall_handler();
break;
- case EXCP_ILLEGAL_INSTRUCTION:
+ case SCAUSE_ILLEGAL_INSTRUCTION:
#ifdef FPE
if ((pcb->pcb_fpflags & PCB_FP_STARTED) == 0) {
/*
* May be a FPE trap. Enable FPE usage
* for this thread and try again.
*/
fpe_state_clear();
frame->tf_sstatus &= ~SSTATUS_FS_MASK;
frame->tf_sstatus |= SSTATUS_FS_CLEAN;
pcb->pcb_fpflags |= PCB_FP_STARTED;
break;
}
#endif
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc,
exception);
userret(td, frame);
break;
- case EXCP_BREAKPOINT:
+ case SCAUSE_BREAKPOINT:
call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_sepc,
exception);
userret(td, frame);
break;
default:
dump_regs(frame);
panic("Unknown userland exception %lx, trap value %lx\n",
exception, frame->tf_stval);
}
}