diff --git a/CHANGELOG.md b/CHANGELOG.md index 26f3f86d..03df6f5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +* PC translation alerts show only when unhandled in simulated code (see #106, @rosenbergm) + ### Added ### Changed diff --git a/src/device/cpu/riscv_rv32ima/cpu.c b/src/device/cpu/riscv_rv32ima/cpu.c index f34a41b8..bdd0fbe6 100644 --- a/src/device/cpu/riscv_rv32ima/cpu.c +++ b/src/device/cpu/riscv_rv32ima/cpu.c @@ -98,6 +98,8 @@ void rv32_cpu_init(rv32_cpu_t *cpu, unsigned int procno) cpu->priv_mode = rv_mmode; + cpu->pending_fetch_fault = false; + /* Breakpoints */ list_init(&cpu->bps); } @@ -725,10 +727,8 @@ static rv_exc_t execute(rv32_cpu_t *cpu) rv_exc_t ex = rv_convert_addr(cpu, cpu->pc, &phys, false, true, true); if (ex != rv_exc_none) { - alert("Fetching from unconvertable address!"); - if (machine_trace) { - // rv32_idump(cpu, cpu->pc, (rv_instr_t) 0U); - } + cpu->pending_fetch_fault = true; + cpu->pending_fetch_fault_pc = cpu->pc; return ex; } diff --git a/src/device/cpu/riscv_rv32ima/cpu.h b/src/device/cpu/riscv_rv32ima/cpu.h index 417b4737..3dbd464c 100644 --- a/src/device/cpu/riscv_rv32ima/cpu.h +++ b/src/device/cpu/riscv_rv32ima/cpu.h @@ -60,6 +60,9 @@ typedef struct rv32_cpu { /** breakpoints **/ list_t bps; + bool pending_fetch_fault; + uint32_t pending_fetch_fault_pc; + } rv32_cpu_t; /** Basic CPU routines */ diff --git a/src/device/cpu/riscv_rv64ima/cpu.c b/src/device/cpu/riscv_rv64ima/cpu.c index e2566fc2..ced7766d 100644 --- a/src/device/cpu/riscv_rv64ima/cpu.c +++ b/src/device/cpu/riscv_rv64ima/cpu.c @@ -96,6 +96,8 @@ void rv64_cpu_init(rv64_cpu_t *cpu, unsigned int procno) rv64_tlb_init(&cpu->tlb, DEFAULT_RV64_TLB_SIZE); + cpu->pending_fetch_fault = false; + cpu->priv_mode = rv_mmode; } @@ -792,10 +794,9 @@ static rv_exc_t execute(rv64_cpu_t *cpu) rv_exc_t ex = rv_convert_addr(cpu, cpu->pc, &phys, false, true, true); if (ex != rv_exc_none) { - alert("Fetching from unconvertable address!"); - // if (machine_trace) { - // rv64_idump(cpu, cpu->pc, (rv_instr_t) 0U); - // } + cpu->pending_fetch_fault = true; + cpu->pending_fetch_fault_pc = cpu->pc; + return ex; } diff --git a/src/device/cpu/riscv_rv64ima/cpu.h b/src/device/cpu/riscv_rv64ima/cpu.h index 5d178d3e..9f71971c 100644 --- a/src/device/cpu/riscv_rv64ima/cpu.h +++ b/src/device/cpu/riscv_rv64ima/cpu.h @@ -56,6 +56,9 @@ typedef struct rv64_cpu { /** Translation Lookaside Buffer used for caching translated addresses */ rv64_tlb_t tlb; + bool pending_fetch_fault; + uint64_t pending_fetch_fault_pc; + } rv64_cpu_t; /** Basic CPU routines */ diff --git a/src/device/cpu/riscv_rv_ima/instructions/system.c b/src/device/cpu/riscv_rv_ima/instructions/system.c index c6700252..af1415bf 100644 --- a/src/device/cpu/riscv_rv_ima/instructions/system.c +++ b/src/device/cpu/riscv_rv_ima/instructions/system.c @@ -129,6 +129,21 @@ static rv_exc_t rv_sret_instr(rv_cpu_t *cpu, rv_instr_t instr) } cpu->pc_next = cpu->csr.sepc; + + if (cpu->pending_fetch_fault) { + if (cpu->csr.sepc == cpu->pending_fetch_fault_pc) { + ptr36_t phys; + if (rv_convert_addr(cpu, cpu->csr.sepc, &phys, false, true, false) != rv_exc_none) { + alert("Exception handler returned to 0x%" RV_PRIXLEN ", but code at that address is not mapped!", (uxlen_t) cpu->pending_fetch_fault_pc); + + /* if (machine_trace) { + rv_idump(cpu, cpu->csr.sepc, (rv_instr_t) 0U); + } */ + } + } + cpu->pending_fetch_fault = false; + } + return rv_exc_none; } @@ -169,6 +184,21 @@ static rv_exc_t rv_mret_instr(rv_cpu_t *cpu, rv_instr_t instr) } cpu->pc_next = cpu->csr.mepc; + + if (cpu->pending_fetch_fault) { + if (cpu->csr.mepc == cpu->pending_fetch_fault_pc) { + ptr36_t phys; + if (rv_convert_addr(cpu, cpu->csr.mepc, &phys, false, true, false) != rv_exc_none) { + alert("Exception handler returned to 0x%" RV_PRIXLEN ", but code at that address is not mapped!", (uxlen_t) cpu->pending_fetch_fault_pc); + + /* if (machine_trace) { + rv_idump(cpu, cpu->csr.mepc, (rv_instr_t) 0U); + } */ + } + } + cpu->pending_fetch_fault = false; + } + return rv_exc_none; } diff --git a/src/device/cpu/riscv_rv_ima/types.h b/src/device/cpu/riscv_rv_ima/types.h index 4b012d8c..fc8ddd66 100644 --- a/src/device/cpu/riscv_rv_ima/types.h +++ b/src/device/cpu/riscv_rv_ima/types.h @@ -28,12 +28,14 @@ typedef uint64_t virt_t; typedef int64_t xlen_t; typedef __int128 bigxlen_t; typedef unsigned __int128 ubigxlen_t; +#define RV_PRIXLEN "016lx" #elif XLEN == 32 typedef uint32_t uxlen_t; typedef uint32_t virt_t; typedef int32_t xlen_t; typedef int64_t bigxlen_t; typedef uint64_t ubigxlen_t; +#define RV_PRIXLEN "08x" #else #error "XLEN is not set to 32 or 64 bits" #endif