diff --git a/sys/conf/Makefile.riscv b/sys/conf/Makefile.riscv index 27338b470413..8721b53893c1 100644 --- a/sys/conf/Makefile.riscv +++ b/sys/conf/Makefile.riscv @@ -29,7 +29,7 @@ S= ../../.. INCLUDES+= -I$S/contrib/libfdt .if !empty(DDB_ENABLED) -CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer +CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls .endif %BEFORE_DEPEND diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv index cfce99bea3ae..7b1a04056bd2 100644 --- a/sys/conf/files.riscv +++ b/sys/conf/files.riscv @@ -23,6 +23,9 @@ riscv/riscv/clock.c standard riscv/riscv/copyinout.S standard riscv/riscv/copystr.c standard riscv/riscv/cpufunc_asm.S standard +riscv/riscv/db_disasm.c optional ddb +riscv/riscv/db_interface.c optional ddb +riscv/riscv/db_trace.c optional ddb riscv/riscv/devmap.c standard riscv/riscv/dump_machdep.c standard riscv/riscv/elf_machdep.c standard @@ -44,4 +47,5 @@ riscv/riscv/trap.c standard riscv/riscv/timer.c standard riscv/riscv/uio_machdep.c standard riscv/riscv/uma_machdep.c standard +riscv/riscv/unwind.c optional ddb | kdtrace_hooks | stack riscv/riscv/vm_machdep.c standard diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC index d8c6fdb20273..e909fc8e0188 100644 --- a/sys/riscv/conf/GENERIC +++ b/sys/riscv/conf/GENERIC @@ -79,10 +79,10 @@ options SMP # options ROOTDEVNAME=\"ufs:/dev/md0\" # Debugging support. Always need this: -# options KDB # Enable kernel debugger support. -# options KDB_TRACE # Print a stack trace for a panic. +options KDB # Enable kernel debugger support. +options KDB_TRACE # Print a stack trace for a panic. # For full debugger support use (turn off in stable branch): -# options DDB # Support DDB. +options DDB # Support DDB. # options GDB # Support remote GDB. options DEADLKRES # Enable the deadlock resolver options INVARIANTS # Enable calls of extra sanity checking diff --git a/sys/riscv/htif/htif_console.c b/sys/riscv/htif/htif_console.c index 10e43497f8ef..200ad9e94244 100644 --- a/sys/riscv/htif/htif_console.c +++ b/sys/riscv/htif/htif_console.c @@ -267,10 +267,37 @@ riscv_cnungrab(struct consdev *cp) static int riscv_cngetc(struct consdev *cp) { +#if defined(KDB) + uint64_t devcmd; + uint64_t entry; + uint64_t devid; +#endif uint8_t data; int ch; - ch = htif_getc(); + htif_getc(); + +#if defined(KDB) + if (kdb_active) { + entry = machine_command(ECALL_HTIF_GET_ENTRY, 0); + while (entry) { + devid = HTIF_DEV_ID(entry); + devcmd = HTIF_DEV_CMD(entry); + data = HTIF_DEV_DATA(entry); + + if (devid == CONSOLE_DEFAULT_ID && devcmd == 0) { + entry_last->data = data; + entry_last->used = 1; + entry_last = entry_last->next; + } else { + printf("Lost interrupt: devid %d\n", + devid); + } + + entry = machine_command(ECALL_HTIF_GET_ENTRY, 0); + } + } +#endif if (entry_served->used == 1) { data = entry_served->data; diff --git a/sys/riscv/include/db_machdep.h b/sys/riscv/include/db_machdep.h index a9890d9c5bfe..7dfd90299d42 100644 --- a/sys/riscv/include/db_machdep.h +++ b/sys/riscv/include/db_machdep.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -41,7 +41,51 @@ #include #include +#define T_BREAKPOINT (EXCP_INSTR_BREAKPOINT) +#define T_WATCHPOINT (0) + typedef vm_offset_t db_addr_t; typedef long db_expr_t; +#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_sepc) + +#define BKPT_INST (0x00100073) +#define BKPT_SIZE (INSN_SIZE) +#define BKPT_SET(inst) (BKPT_INST) + +#define BKPT_SKIP do { \ + kdb_frame->tf_sepc += BKPT_SIZE; \ +} 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_SMALL_VALUE_MAX (0x7fffffff) +#define DB_SMALL_VALUE_MIN (-0x40001) + +#define DB_ELFSIZE 64 + #endif /* !_MACHINE_DB_MACHDEP_H_ */ diff --git a/sys/riscv/include/riscv_opcode.h b/sys/riscv/include/riscv_opcode.h new file mode 100644 index 000000000000..b346588f01df --- /dev/null +++ b/sys/riscv/include/riscv_opcode.h @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 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_RISCV_OPCODE_H_ +#define _MACHINE_RISCV_OPCODE_H_ + +/* + * Define the instruction formats and opcode values for the + * RISC-V instruction set. + */ +#include + +/* + * Define the instruction formats. + */ +typedef union { + unsigned word; + + struct { + unsigned opcode: 7; + unsigned rd: 5; + unsigned funct3: 3; + unsigned rs1: 5; + unsigned rs2: 5; + unsigned funct7: 7; + } RType; + + struct { + unsigned opcode: 7; + unsigned rd: 5; + unsigned funct3: 3; + unsigned rs1: 5; + unsigned rs2: 6; + unsigned funct7: 6; + } R2Type; + + struct { + unsigned opcode: 7; + unsigned rd: 5; + unsigned funct3: 3; + unsigned rs1: 5; + unsigned imm: 12; + } IType; + + struct { + unsigned opcode: 7; + unsigned imm0_4: 5; + unsigned funct3: 3; + unsigned rs1: 5; + unsigned rs2: 5; + unsigned imm5_11: 7; + } SType; + + struct { + unsigned opcode: 7; + unsigned imm11: 1; + unsigned imm1_4: 4; + unsigned funct3: 3; + unsigned rs1: 5; + unsigned rs2: 5; + unsigned imm5_10: 6; + unsigned imm12: 1; + } SBType; + + struct { + unsigned opcode: 7; + unsigned rd: 5; + unsigned imm12_31: 20; + } UType; + + struct { + unsigned opcode: 7; + unsigned rd: 5; + unsigned imm12_19: 8; + unsigned imm11: 1; + unsigned imm1_10: 10; + unsigned imm20: 1; + } UJType; +} InstFmt; + +#define RISCV_OPCODE(r) (r & 0x7f) + +#endif /* !_MACHINE_RISCV_OPCODE_H_ */ diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h index 76cba49a746b..b411e1824f60 100644 --- a/sys/riscv/include/riscvreg.h +++ b/sys/riscv/include/riscvreg.h @@ -117,9 +117,10 @@ #define SIP_SSIP (1 << 1) #define SIP_STIP (1 << 5) -#define NCSRS 4096 -#define CSR_IPI 0x783 -#define XLEN 8 +#define NCSRS 4096 +#define CSR_IPI 0x783 +#define XLEN 8 +#define INSN_SIZE 4 #define CSR_ZIMM(val) \ (__builtin_constant_p(val) && ((u_long)(val) < 32)) diff --git a/sys/riscv/include/stack.h b/sys/riscv/include/stack.h new file mode 100644 index 000000000000..7f4be068ec27 --- /dev/null +++ b/sys/riscv/include/stack.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 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_STACK_H_ +#define _MACHINE_STACK_H_ + +#define INKERNEL(va) ((va) >= VM_MIN_KERNEL_ADDRESS && \ + (va) <= VM_MAX_KERNEL_ADDRESS) + +struct unwind_state { + uint64_t fp; + uint64_t sp; + uint64_t pc; +}; + +int unwind_frame(struct unwind_state *); + +#endif /* !_MACHINE_STACK_H_ */ diff --git a/sys/riscv/riscv/db_disasm.c b/sys/riscv/riscv/db_disasm.c new file mode 100644 index 000000000000..4be311401e38 --- /dev/null +++ b/sys/riscv/riscv/db_disasm.c @@ -0,0 +1,475 @@ +/*- + * Copyright (c) 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +struct riscv_op { + char *name; + char *type; + char *fmt; + int opcode; + int funct3; + int funct7; /* Or imm, depending on type. */ +}; + +/* + * Keep sorted by opcode, funct3, funct7 so some instructions + * aliases will be supported (e.g. "mv" instruction alias) + * Use same print format as binutils do. + */ +static struct riscv_op riscv_opcodes[] = { + { "lb", "I", "d,o(s)", 3, 0, -1 }, + { "lh", "I", "d,o(s)", 3, 1, -1 }, + { "lw", "I", "d,o(s)", 3, 2, -1 }, + { "ld", "I", "d,o(s)", 3, 3, -1 }, + { "lbu", "I", "d,o(s)", 3, 4, -1 }, + { "lhu", "I", "d,o(s)", 3, 5, -1 }, + { "lwu", "I", "d,o(s)", 3, 6, -1 }, + { "ldu", "I", "d,o(s)", 3, 7, -1 }, + { "fence", "I", "", 15, 0, -1 }, + { "fence.i", "I", "", 15, 1, -1 }, + { "mv", "I", "d,s", 19, 0, 0 }, + { "addi", "I", "d,s,j", 19, 0, -1 }, + { "slli", "R2", "d,s,>", 19, 1, 0 }, + { "slti", "I", "d,s,j", 19, 2, -1 }, + { "sltiu", "I", "d,s,j", 19, 3, -1 }, + { "xori", "I", "d,s,j", 19, 4, -1 }, + { "srli", "R2", "d,s,>", 19, 5, 0 }, + { "srai", "R2", "d,s,>", 19, 5, 0b010000 }, + { "ori", "I", "d,s,j", 19, 6, -1 }, + { "andi", "I", "d,s,j", 19, 7, -1 }, + { "auipc", "U", "d,u", 23, -1, -1 }, + { "sext.w", "I", "d,s", 27, 0, 0 }, + { "addiw", "I", "d,s,j", 27, 0, -1 }, + { "slliw", "R", "d,s,<", 27, 1, 0 }, + { "srliw", "R", "d,s,<", 27, 5, 0 }, + { "sraiw", "R", "d,s,<", 27, 5, 0b0100000 }, + { "sb", "S", "t,q(s)", 35, 0, -1 }, + { "sh", "S", "t,q(s)", 35, 1, -1 }, + { "sw", "S", "t,q(s)", 35, 2, -1 }, + { "sd", "S", "t,q(s)", 35, 3, -1 }, + { "sbu", "S", "t,q(s)", 35, 4, -1 }, + { "shu", "S", "t,q(s)", 35, 5, -1 }, + { "swu", "S", "t,q(s)", 35, 6, -1 }, + { "sdu", "S", "t,q(s)", 35, 7, -1 }, + { "lr.w", "R", "d,t,0(s)", 47, 2, 0b0001000 }, + { "sc.w", "R", "d,t,0(s)", 47, 2, 0b0001100 }, + { "amoswap.w", "R", "d,t,0(s)", 47, 2, 0b0000100 }, + { "amoadd.w", "R", "d,t,0(s)", 47, 2, 0b0000000 }, + { "amoxor.w", "R", "d,t,0(s)", 47, 2, 0b0010000 }, + { "amoand.w", "R", "d,t,0(s)", 47, 2, 0b0110000 }, + { "amoor.w", "R", "d,t,0(s)", 47, 2, 0b0100000 }, + { "amomin.w", "R", "d,t,0(s)", 47, 2, 0b1000000 }, + { "amomax.w", "R", "d,t,0(s)", 47, 2, 0b1010000 }, + { "amominu.w", "R", "d,t,0(s)", 47, 2, 0b1100000 }, + { "amomaxu.w", "R", "d,t,0(s)", 47, 2, 0b1110000 }, + { "lr.w.aq", "R", "d,t,0(s)", 47, 2, 0b0001000 }, + { "sc.w.aq", "R", "d,t,0(s)", 47, 2, 0b0001100 }, + { "amoswap.w.aq","R", "d,t,0(s)", 47, 2, 0b0000110 }, + { "amoadd.w.aq","R", "d,t,0(s)", 47, 2, 0b0000010 }, + { "amoxor.w.aq","R", "d,t,0(s)", 47, 2, 0b0010010 }, + { "amoand.w.aq","R", "d,t,0(s)", 47, 2, 0b0110010 }, + { "amoor.w.aq", "R", "d,t,0(s)", 47, 2, 0b0100010 }, + { "amomin.w.aq","R", "d,t,0(s)", 47, 2, 0b1000010 }, + { "amomax.w.aq","R", "d,t,0(s)", 47, 2, 0b1010010 }, + { "amominu.w.aq","R", "d,t,0(s)", 47, 2, 0b1100010 }, + { "amomaxu.w.aq","R", "d,t,0(s)", 47, 2, 0b1110010 }, + { "amoswap.w.rl","R", "d,t,0(s)", 47, 2, 0b0000110 }, + { "amoadd.w.rl","R", "d,t,0(s)", 47, 2, 0b0000001 }, + { "amoxor.w.rl","R", "d,t,0(s)", 47, 2, 0b0010001 }, + { "amoand.w.rl","R", "d,t,0(s)", 47, 2, 0b0110001 }, + { "amoor.w.rl", "R", "d,t,0(s)", 47, 2, 0b0100001 }, + { "amomin.w.rl","R", "d,t,0(s)", 47, 2, 0b1000001 }, + { "amomax.w.rl","R", "d,t,0(s)", 47, 2, 0b1010001 }, + { "amominu.w.rl","R", "d,t,0(s)", 47, 2, 0b1100001 }, + { "amomaxu.w.rl","R", "d,t,0(s)", 47, 2, 0b1110001 }, + { "amoswap.d", "R", "d,t,0(s)", 47, 3, 0b0000100 }, + { "amoadd.d", "R", "d,t,0(s)", 47, 3, 0b0000000 }, + { "amoxor.d", "R", "d,t,0(s)", 47, 3, 0b0010000 }, + { "amoand.d", "R", "d,t,0(s)", 47, 3, 0b0110000 }, + { "amoor.d", "R", "d,t,0(s)", 47, 3, 0b0100000 }, + { "amomin.d", "R", "d,t,0(s)", 47, 3, 0b1000000 }, + { "amomax.d", "R", "d,t,0(s)", 47, 3, 0b1010000 }, + { "amominu.d", "R", "d,t,0(s)", 47, 3, 0b1100000 }, + { "amomaxu.d", "R", "d,t,0(s)", 47, 3, 0b1110000 }, + { "lr.d.aq", "R", "d,t,0(s)", 47, 3, 0b0001000 }, + { "sc.d.aq", "R", "d,t,0(s)", 47, 3, 0b0001100 }, + { "amoswap.d.aq","R", "d,t,0(s)", 47, 3, 0b0000110 }, + { "amoadd.d.aq","R", "d,t,0(s)", 47, 3, 0b0000010 }, + { "amoxor.d.aq","R", "d,t,0(s)", 47, 3, 0b0010010 }, + { "amoand.d.aq","R", "d,t,0(s)", 47, 3, 0b0110010 }, + { "amoor.d.aq", "R", "d,t,0(s)", 47, 3, 0b0100010 }, + { "amomin.d.aq","R", "d,t,0(s)", 47, 3, 0b1000010 }, + { "amomax.d.aq","R", "d,t,0(s)", 47, 3, 0b1010010 }, + { "amominu.d.aq","R", "d,t,0(s)", 47, 3, 0b1100010 }, + { "amomaxu.d.aq","R", "d,t,0(s)", 47, 3, 0b1110010 }, + { "amoswap.d.rl","R", "d,t,0(s)", 47, 3, 0b0000110 }, + { "amoadd.d.rl","R", "d,t,0(s)", 47, 3, 0b0000001 }, + { "amoxor.d.rl","R", "d,t,0(s)", 47, 3, 0b0010001 }, + { "amoand.d.rl","R", "d,t,0(s)", 47, 3, 0b0110001 }, + { "amoor.d.rl", "R", "d,t,0(s)", 47, 3, 0b0100001 }, + { "amomin.d.rl","R", "d,t,0(s)", 47, 3, 0b1000001 }, + { "amomax.d.rl","R", "d,t,0(s)", 47, 3, 0b1010001 }, + { "amominu.d.rl","R", "d,t,0(s)", 47, 3, 0b1100001 }, + { "amomaxu.d.rl","R", "d,t,0(s)", 47, 3, 0b1110001 }, + { "add", "R", "d,s,t", 51, 0, 0 }, + { "sub", "R", "d,s,t", 51, 0, 0b0100000 }, + { "mul", "R", "d,s,t", 51, 0, 0b0000001 }, + { "sll", "R", "d,s,t", 51, 1, 0 }, + { "slt", "R", "d,s,t", 51, 2, 0 }, + { "sltu", "R", "d,s,t", 51, 3, 0 }, + { "xor", "R", "d,s,t", 51, 4, 0 }, + { "srl", "R", "d,s,t", 51, 5, 0 }, + { "sra", "R", "d,s,t", 51, 5, 0b0100000 }, + { "or", "R", "d,s,t", 51, 6, 0 }, + { "and", "R", "d,s,t", 51, 7, 0 }, + { "lui", "U", "d,u", 55, -1, -1 }, + { "addw", "R", "d,s,t", 59, 0, 0 }, + { "subw", "R", "d,s,t", 59, 0, 0b0100000 }, + { "mulw", "R", "d,s,t", 59, 0, 1 }, + { "sllw", "R", "d,s,t", 59, 1, 0 }, + { "srlw", "R", "d,s,t", 59, 5, 0 }, + { "sraw", "R", "d,s,t", 59, 5, 0b0100000 }, + { "beq", "SB", "s,t,p", 99, 0, -1 }, + { "bne", "SB", "s,t,p", 99, 1, -1 }, + { "blt", "SB", "s,t,p", 99, 4, -1 }, + { "bge", "SB", "s,t,p", 99, 5, -1 }, + { "bltu", "SB", "s,t,p", 99, 6, -1 }, + { "bgeu", "SB", "s,t,p", 99, 7, -1 }, + { "jalr", "I", "d,s,j", 103, 0, -1 }, + { "jal", "UJ", "a", 111, -1, -1 }, + { "eret", "I", "", 115, 0, 0b000100000000 }, + { "sfence.vm", "I", "", 115, 0, 0b000100000001 }, + { "wfi", "I", "", 115, 0, 0b000100000010 }, + { "csrrw", "I", "d,E,s", 115, 1, -1}, + { "csrrs", "I", "d,E,s", 115, 2, -1}, + { "csrrc", "I", "d,E,s", 115, 3, -1}, + { "csrrwi", "I", "d,E,Z", 115, 5, -1}, + { "csrrsi", "I", "d,E,Z", 115, 6, -1}, + { "csrrci", "I", "d,E,Z", 115, 7, -1}, + { NULL, NULL, NULL, 0, 0, 0 } +}; + +struct csr_op { + char *name; + int imm; +}; + +static struct csr_op csr_name[] = { + { "fflags", 0x001 }, + { "frm", 0x002 }, + { "fcsr", 0x003 }, + { "cycle", 0xc00 }, + { "time", 0xc01 }, + { "instret", 0xc02 }, + { "stats", 0x0c0 }, + { "uarch0", 0xcc0 }, + { "uarch1", 0xcc1 }, + { "uarch2", 0xcc2 }, + { "uarch3", 0xcc3 }, + { "uarch4", 0xcc4 }, + { "uarch5", 0xcc5 }, + { "uarch6", 0xcc6 }, + { "uarch7", 0xcc7 }, + { "uarch8", 0xcc8 }, + { "uarch9", 0xcc9 }, + { "uarch10", 0xcca }, + { "uarch11", 0xccb }, + { "uarch12", 0xccc }, + { "uarch13", 0xccd }, + { "uarch14", 0xcce }, + { "uarch15", 0xccf }, + { "sstatus", 0x100 }, + { "stvec", 0x101 }, + { "sie", 0x104 }, + { "sscratch", 0x140 }, + { "sepc", 0x141 }, + { "sip", 0x144 }, + { "sptbr", 0x180 }, + { "sasid", 0x181 }, + { "cyclew", 0x900 }, + { "timew", 0x901 }, + { "instretw", 0x902 }, + { "stime", 0xd01 }, + { "scause", 0xd42 }, + { "sbadaddr", 0xd43 }, + { "stimew", 0xa01 }, + { "mstatus", 0x300 }, + { "mtvec", 0x301 }, + { "mtdeleg", 0x302 }, + { "mie", 0x304 }, + { "mtimecmp", 0x321 }, + { "mscratch", 0x340 }, + { "mepc", 0x341 }, + { "mcause", 0x342 }, + { "mbadaddr", 0x343 }, + { "mip", 0x344 }, + { "mtime", 0x701 }, + { "mcpuid", 0xf00 }, + { "mimpid", 0xf01 }, + { "mhartid", 0xf10 }, + { "mtohost", 0x780 }, + { "mfromhost", 0x781 }, + { "mreset", 0x782 }, + { "send_ipi", 0x783 }, + { "miobase", 0x784 }, + { "cycleh", 0xc80 }, + { "timeh", 0xc81 }, + { "instreth", 0xc82 }, + { "cyclehw", 0x980 }, + { "timehw", 0x981 }, + { "instrethw", 0x982 }, + { "stimeh", 0xd81 }, + { "stimehw", 0xa81 }, + { "mtimecmph", 0x361 }, + { "mtimeh", 0x741 }, + { NULL, 0 } +}; + +static char *reg_name[32] = { + "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", + "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", + "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", + "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6" +}; + +static int32_t +get_imm(InstFmt i, char *type, uint32_t *val) +{ + int imm; + + imm = 0; + + if (strcmp(type, "I") == 0) { + imm = i.IType.imm; + *val = imm; + if (imm & (1 << 11)) + imm |= (0xfffff << 12); /* sign extend */ + + } else if (strcmp(type, "S") == 0) { + imm = i.SType.imm0_4; + imm |= (i.SType.imm5_11 << 5); + *val = imm; + if (imm & (1 << 11)) + imm |= (0xfffff << 12); /* sign extend */ + + } else if (strcmp(type, "U") == 0) { + imm = i.UType.imm12_31; + *val = imm; + + } else if (strcmp(type, "UJ") == 0) { + imm = i.UJType.imm12_19 << 12; + imm |= i.UJType.imm11 << 11; + imm |= i.UJType.imm1_10 << 1; + imm |= i.UJType.imm20 << 20; + *val = imm; + if (imm & (1 << 20)) + imm |= (0xfff << 21); /* sign extend */ + + } else if (strcmp(type, "SB") == 0) { + imm = i.SBType.imm11 << 11; + imm |= i.SBType.imm1_4 << 1; + imm |= i.SBType.imm5_10 << 5; + imm |= i.SBType.imm12 << 12; + *val = imm; + if (imm & (1 << 12)) + imm |= (0xfffff << 12); /* sign extend */ + } + + return (imm); +} + +static int +oprint(struct riscv_op *op, vm_offset_t loc, int rd, + int rs1, int rs2, uint32_t val, vm_offset_t imm) +{ + char *p; + int i; + + p = op->fmt; + + db_printf("%s\t", op->name); + + while (*p) { + if (strncmp("d", p, 1) == 0) + db_printf("%s", reg_name[rd]); + + else if (strncmp("s", p, 1) == 0) + db_printf("%s", reg_name[rs1]); + + else if (strncmp("t", p, 1) == 0) + db_printf("%s", reg_name[rs2]); + + else if (strncmp(">", p, 1) == 0) + db_printf("0x%x", rs2); + + else if (strncmp("E", p, 1) == 0) { + for (i = 0; csr_name[i].name != NULL; i++) + if (csr_name[i].imm == val) + db_printf("%s", + csr_name[i].name); + } else if (strncmp("Z", p, 1) == 0) + db_printf("%d", rs1); + + else if (strncmp("<", p, 1) == 0) + db_printf("0x%x", rs2); + + else if (strncmp("j", p, 1) == 0) + db_printf("%d", imm); + + else if (strncmp("u", p, 1) == 0) + db_printf("0x%x", imm); + + else if (strncmp("a", p, 1) == 0) + db_printf("0x%016lx", imm); + + else if (strncmp("p", p, 1) == 0) + db_printf("0x%016lx", (loc + imm)); + + else if (strlen(p) >= 4) { + if (strncmp("o(s)", p, 4) == 0) + db_printf("%d(%s)", imm, reg_name[rs1]); + else if (strncmp("q(s)", p, 4) == 0) + db_printf("%d(%s)", imm, reg_name[rs1]); + else if (strncmp("0(s)", p, 4) == 0) + db_printf("(%s)", reg_name[rs1]); + } + + while (*p && strncmp(p, ",", 1) != 0) + p++; + + if (*p) { + db_printf(", "); + p++; + } + } + + + return (0); +} + +static int +match_type(InstFmt i, struct riscv_op *op, vm_offset_t loc) +{ + uint32_t val; + int found; + int imm; + + val = 0; + imm = get_imm(i, op->type, &val); + + if (strcmp(op->type, "U") == 0) { + oprint(op, loc, i.UType.rd, 0, 0, val, imm); + return (1); + } + if (strcmp(op->type, "UJ") == 0) { + oprint(op, loc, 0, 0, 0, val, (loc + imm)); + return (1); + } + if ((strcmp(op->type, "I") == 0) && \ + (op->funct3 == i.IType.funct3)) { + found = 0; + if (op->funct7 != -1) { + if (op->funct7 == i.IType.imm) + found = 1; + } else + found = 1; + + if (found) { + oprint(op, loc, i.IType.rd, + i.IType.rs1, 0, val, imm); + return (1); + } + } + if ((strcmp(op->type, "S") == 0) && \ + (op->funct3 == i.SType.funct3)) { + oprint(op, loc, 0, i.SType.rs1, i.SType.rs2, + val, imm); + return (1); + } + if ((strcmp(op->type, "SB") == 0) && \ + (op->funct3 == i.SBType.funct3)) { + oprint(op, loc, 0, i.SBType.rs1, i.SBType.rs2, + val, imm); + return (1); + } + if ((strcmp(op->type, "R2") == 0) && \ + (op->funct3 == i.R2Type.funct3) && \ + (op->funct7 == i.R2Type.funct7)) { + oprint(op, loc, i.R2Type.rd, i.R2Type.rs1, + i.R2Type.rs2, val, imm); + return (1); + } + if ((strcmp(op->type, "R") == 0) && \ + (op->funct3 == i.RType.funct3) && \ + (op->funct7 == i.RType.funct7)) { + oprint(op, loc, i.RType.rd, i.RType.rs1, + val, i.RType.rs2, imm); + return (1); + } + + return (0); +} + +vm_offset_t +db_disasm(vm_offset_t loc, bool altfmt) +{ + struct riscv_op *op; + InstFmt i; + int j; + + i.word = db_get_value(loc, INSN_SIZE, 0); + + /* First match opcode */ + for (j = 0; riscv_opcodes[j].name != NULL; j++) { + op = &riscv_opcodes[j]; + if (op->opcode == i.RType.opcode) { + if (match_type(i, op, loc)) + break; + } + } + + db_printf("\n"); + return(loc + INSN_SIZE); +} diff --git a/sys/riscv/riscv/db_interface.c b/sys/riscv/riscv/db_interface.c new file mode 100644 index 000000000000..b9f391ab7a77 --- /dev/null +++ b/sys/riscv/riscv/db_interface.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of the FreeBSD Foundation. + * + * 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 + +#ifdef KDB +#include +#endif + +#include +#include + +#include +#include +#include +#include + +static int +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) +{ + long *reg; + + if (kdb_frame == NULL) + return (0); + + reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); +} + +#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) +struct db_variable db_regs[] = { + { "ra", DB_OFFSET(tf_ra), db_frame }, + { "sp", DB_OFFSET(tf_sp), db_frame }, + { "gp", DB_OFFSET(tf_gp), db_frame }, + { "tp", DB_OFFSET(tf_tp), db_frame }, + { "t0", DB_OFFSET(tf_t[0]), db_frame }, + { "t1", DB_OFFSET(tf_t[1]), db_frame }, + { "t2", DB_OFFSET(tf_t[2]), db_frame }, + { "t3", DB_OFFSET(tf_t[3]), db_frame }, + { "t4", DB_OFFSET(tf_t[4]), db_frame }, + { "t5", DB_OFFSET(tf_t[5]), db_frame }, + { "t6", DB_OFFSET(tf_t[6]), db_frame }, + { "s0", DB_OFFSET(tf_s[0]), db_frame }, + { "s1", DB_OFFSET(tf_s[1]), db_frame }, + { "s2", DB_OFFSET(tf_s[2]), db_frame }, + { "s3", DB_OFFSET(tf_s[3]), db_frame }, + { "s4", DB_OFFSET(tf_s[4]), db_frame }, + { "s5", DB_OFFSET(tf_s[5]), db_frame }, + { "s6", DB_OFFSET(tf_s[6]), db_frame }, + { "s7", DB_OFFSET(tf_s[7]), db_frame }, + { "s8", DB_OFFSET(tf_s[8]), db_frame }, + { "s9", DB_OFFSET(tf_s[9]), db_frame }, + { "s10", DB_OFFSET(tf_s[10]), db_frame }, + { "s11", DB_OFFSET(tf_s[11]), db_frame }, + { "a0", DB_OFFSET(tf_a[0]), db_frame }, + { "a1", DB_OFFSET(tf_a[1]), db_frame }, + { "a2", DB_OFFSET(tf_a[2]), db_frame }, + { "a3", DB_OFFSET(tf_a[3]), db_frame }, + { "a4", DB_OFFSET(tf_a[4]), db_frame }, + { "a5", DB_OFFSET(tf_a[5]), db_frame }, + { "a6", DB_OFFSET(tf_a[6]), db_frame }, + { "a7", DB_OFFSET(tf_a[7]), db_frame }, + { "sepc", DB_OFFSET(tf_sepc), db_frame }, + { "sstatus", DB_OFFSET(tf_sstatus), db_frame }, + { "sbadaddr", DB_OFFSET(tf_sbadaddr), db_frame }, + { "scause", DB_OFFSET(tf_scause), db_frame }, +}; + +struct db_variable *db_eregs = db_regs + nitems(db_regs); + +void +db_show_mdpcpu(struct pcpu *pc) +{ +} + +/* + * Read bytes from kernel address space for debugger. + */ +int +db_read_bytes(vm_offset_t addr, size_t size, char *data) +{ + jmp_buf jb; + void *prev_jb; + const char *src; + int ret; + + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + + if (ret == 0) { + src = (const char *)addr; + while (size-- > 0) + *data++ = *src++; + } + (void)kdb_jmpbuf(prev_jb); + + return (ret); +} + +/* + * Write bytes to kernel address space for debugger. + */ +int +db_write_bytes(vm_offset_t addr, size_t size, char *data) +{ + jmp_buf jb; + void *prev_jb; + char *dst; + int ret; + + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + dst = (char *)addr; + while (size-- > 0) + *dst++ = *data++; + + fence(); + + /* Clean D-cache and invalidate I-cache */ + cpu_dcache_wb_range(addr, (vm_size_t)size); + cpu_icache_sync_range(addr, (vm_size_t)size); + } + (void)kdb_jmpbuf(prev_jb); + + return (ret); +} diff --git a/sys/riscv/riscv/db_trace.c b/sys/riscv/riscv/db_trace.c new file mode 100644 index 000000000000..6c45e070a981 --- /dev/null +++ b/sys/riscv/riscv/db_trace.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2015 The FreeBSD Foundation + * Copyright (c) 2016 Ruslan Bukin + * All rights reserved. + * + * 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 + +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; + + if (unwind_frame(frame) < 0) + break; + + 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"); + + db_printf("\t pc = 0x%016lx ra = 0x%016lx\n", + pc, frame->pc); + db_printf("\t sp = 0x%016lx fp = 0x%016lx\n", + frame->sp, frame->fp); + db_printf("\n"); + } +} + +int +db_trace_thread(struct thread *thr, int count) +{ + struct unwind_state frame; + struct pcb *ctx; + + if (thr != curthread) { + ctx = kdb_thr_ctx(thr); + + frame.sp = (uint64_t)ctx->pcb_sp; + frame.fp = (uint64_t)ctx->pcb_s[0]; + frame.pc = (uint64_t)ctx->pcb_ra; + db_stack_trace_cmd(&frame); + } else + db_trace_self(); + return (0); +} + +void +db_trace_self(void) +{ + struct unwind_state frame; + uint64_t sp; + + __asm __volatile("mv %0, sp" : "=&r" (sp)); + + frame.sp = sp; + frame.fp = (uint64_t)__builtin_frame_address(0); + frame.pc = (uint64_t)db_trace_self; + db_stack_trace_cmd(&frame); +} diff --git a/sys/riscv/riscv/stack_machdep.c b/sys/riscv/riscv/stack_machdep.c index 2c1a6a315a13..6bb7f1c831a1 100644 --- a/sys/riscv/riscv/stack_machdep.c +++ b/sys/riscv/riscv/stack_machdep.c @@ -42,11 +42,39 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +static void +stack_capture(struct stack *st, struct unwind_state *frame) +{ + + stack_zero(st); + + while (1) { + unwind_frame(frame); + if (!INKERNEL((vm_offset_t)frame->fp) || + !INKERNEL((vm_offset_t)frame->pc)) + break; + if (stack_put(st, frame->pc) == -1) + break; + } +} void stack_save_td(struct stack *st, struct thread *td) { + struct unwind_state frame; + if (TD_IS_SWAPPED(td)) + panic("stack_save_td: swapped"); + if (TD_IS_RUNNING(td)) + panic("stack_save_td: running"); + + frame.sp = td->td_pcb->pcb_sp; + frame.fp = td->td_pcb->pcb_s[0]; + frame.pc = td->td_pcb->pcb_ra; + + stack_capture(st, &frame); } int @@ -59,5 +87,14 @@ stack_save_td_running(struct stack *st, struct thread *td) void stack_save(struct stack *st) { + struct unwind_state frame; + uint64_t sp; + __asm __volatile("mv %0, sp" : "=&r" (sp)); + + frame.sp = sp; + frame.fp = (uint64_t)__builtin_frame_address(0); + frame.pc = (uint64_t)stack_save; + + stack_capture(st, &frame); } diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index d560bc6d5cd4..6327204563f1 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef KDB +#include +#endif #include #include @@ -167,6 +170,13 @@ data_abort(struct trapframe *frame, int lower) int error; int sig; +#ifdef KDB + if (kdb_active) { + kdb_reenter(); + return; + } +#endif + td = curthread; pcb = td->td_pcb; @@ -277,6 +287,7 @@ do_trap_supervisor(struct trapframe *frame) dump_regs(frame); panic("No debugger in kernel.\n"); #endif + break; case EXCP_INSTR_ILLEGAL: dump_regs(frame); panic("Illegal instruction at %x\n", frame->tf_sepc); diff --git a/sys/riscv/riscv/unwind.c b/sys/riscv/riscv/unwind.c new file mode 100644 index 000000000000..18fc1e250c9b --- /dev/null +++ b/sys/riscv/riscv/unwind.c @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 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. + */ + +#include +__FBSDID("$FreeBSD$"); +#include + +#include +#include + +int +unwind_frame(struct unwind_state *frame) +{ + uint64_t fp; + + fp = frame->fp; + + if (!INKERNEL(fp)) + return (-1); + + frame->sp = fp; + frame->fp = *(uint64_t *)(fp - 16); + frame->pc = *(uint64_t *)(fp - 8) - 4; + + return (0); +}