diff --git a/xen/arch/riscv/Kconfig b/xen/arch/riscv/Kconfig index b4b354a778..f531e96657 100644 --- a/xen/arch/riscv/Kconfig +++ b/xen/arch/riscv/Kconfig @@ -1,6 +1,7 @@ config RISCV def_bool y select FUNCTION_ALIGNMENT_16B + select GENERIC_BUG_FRAME config RISCV_64 def_bool y diff --git a/xen/arch/riscv/include/asm/bug.h b/xen/arch/riscv/include/asm/bug.h index f5ff96140f..e3d41f411a 100644 --- a/xen/arch/riscv/include/asm/bug.h +++ b/xen/arch/riscv/include/asm/bug.h @@ -9,7 +9,7 @@ #ifndef __ASSEMBLY__ -#define BUG_INSTR "ebreak" +#define BUG_INSTR "unimp" /* * The base instruction set has a fixed length of 32-bit naturally aligned @@ -18,15 +18,13 @@ * There are extensions of variable length ( where each instruction can be * any number of 16-bit parcels in length ). * - * Compressed ISA is used now where the instruction length is 16 bit and - * 'ebreak' instruction, in this case, can be either 16 or 32 bit ( + * Compressed ISA is used now where the instruction length is 16 bit and + * 'unimp' instruction, in this case, can be either 16 or 32 bit ( * depending on if compressed ISA is used or not ) */ #define INSN_LENGTH_MASK _UL(0x3) #define INSN_LENGTH_32 _UL(0x3) -#define BUG_INSN_32 _UL(0x00100073) /* ebreak */ -#define BUG_INSN_16 _UL(0x9002) /* c.ebreak */ #define COMPRESSED_INSN_MASK _UL(0xffff) #define GET_INSN_LENGTH(insn) \ diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 7149504ebc..d55a4a827b 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -5,6 +5,8 @@ * RISC-V Trap handlers */ +#include +#include #include #include #include @@ -106,7 +108,29 @@ static void do_unexpected_trap(const struct cpu_user_regs *regs) void do_trap(struct cpu_user_regs *cpu_regs) { - do_unexpected_trap(cpu_regs); + register_t pc = cpu_regs->sepc; + unsigned long cause = csr_read(CSR_SCAUSE); + + switch ( cause ) + { + case CAUSE_ILLEGAL_INSTRUCTION: + if ( do_bug_frame(cpu_regs, pc) >= 0 ) + { + if ( !(is_kernel_text(pc) || is_kernel_inittext(pc)) ) + { + printk("Something wrong with PC: %#lx\n", pc); + die(); + } + + cpu_regs->sepc += GET_INSN_LENGTH(*(uint16_t *)pc); + + break; + } + fallthrough; + default: + do_unexpected_trap(cpu_regs); + break; + } } void vcpu_show_execution_state(struct vcpu *v) diff --git a/xen/common/bug.c b/xen/common/bug.c index b7c5d8fd4d..75cb35fcfa 100644 --- a/xen/common/bug.c +++ b/xen/common/bug.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include