On 26.01.2026 12:43, Oleksii Kurochko wrote:
> Provide additional context when an unexpected exception occurs by dumping
> the relevant Supervisor, Virtual Supervisor (VS), and Hypervisor CSRs,
> along with the general-purpose registers associated with the trap.
> 
> Dumping VS-mode CSRs in addition to host CSRs is beneficial when analysing
> VS-mode traps. VSCAUSE, VSEPC, VSTVAL, and related VS state are required to
> properly diagnose unexpected guest traps and potential hypervisor
> misconfiguration.
> For example, on an illegal-instruction exception the hardware may record
> the faulting instruction in VSTVAL. If VSTVAL is zero, VSEPC should always
> be inspected, and can be used together with objdump to identify the
> faulting instruction. Dumping VSCAUSE is also useful when the guest does
> not report it, or when the hypervisor redirects a trap to the guest using
> VSCAUSE, VSTATUS, and VSTVEC, allowing verification that a subsequent trap
> is not caused by incorrect VS state.
> 
> Signed-off-by: Oleksii Kurochko <[email protected]>

Acked-by: Jan Beulich <[email protected]>

I still have a question though, which can be addressed incrementally.

> --- a/xen/arch/riscv/traps.c
> +++ b/xen/arch/riscv/traps.c
> @@ -99,12 +99,70 @@ static const char *decode_cause(unsigned long cause)
>      return decode_trap_cause(cause);
>  }
>  
> +static void dump_general_regs(const struct cpu_user_regs *regs)
> +{
> +#define X(regs, name, delim) \
> +    printk("%-4s: %016lx" delim, #name, (regs)->name)
> +
> +    X(regs, ra, " "); X(regs, sp, "\n");
> +    X(regs, gp, " "); X(regs, tp, "\n");
> +    X(regs, t0, " "); X(regs, t1, "\n");
> +    X(regs, t2, " "); X(regs, s0, "\n");
> +    X(regs, s1, " "); X(regs, a0, "\n");
> +    X(regs, a1, " "); X(regs, a2, "\n");
> +    X(regs, a3, " "); X(regs, a4, "\n");
> +    X(regs, a5, " "); X(regs, a6, "\n");
> +    X(regs, a7, " "); X(regs, s2, "\n");
> +    X(regs, s3, " "); X(regs, s4, "\n");
> +    X(regs, s5, " "); X(regs, s6, "\n");
> +    X(regs, s7, " "); X(regs, s8, "\n");
> +    X(regs, s9, " "); X(regs, s10, "\n");
> +    X(regs, s11, " "); X(regs, t3, "\n");
> +    X(regs, t4, " "); X(regs, t5, "\n");
> +    X(regs, t6, " "); X(regs, sepc, "\n");

Does this sepc value differ from ...

> +static void dump_csrs(unsigned long cause)
> +{
> +#define X(name, csr, fmt, ...) \
> +    v = csr_read(csr); \
> +    printk("%-10s: %016lx" fmt, #name, v, ##__VA_ARGS__)
> +
> +    unsigned long v;
> +
> +    X(htval, CSR_HTVAL, " ");  X(htinst, CSR_HTINST, "\n");
> +    X(hedeleg, CSR_HEDELEG, " "); X(hideleg, CSR_HIDELEG, "\n");
> +    X(hstatus, CSR_HSTATUS, " [%s%s%s%s%s%s ]\n",
> +      (v & HSTATUS_VTSR) ? " VTSR" : "",
> +      (v & HSTATUS_VTVM) ? " VTVM" : "",
> +      (v & HSTATUS_HU)   ? " HU"   : "",
> +      (v & HSTATUS_SPVP) ? " SPVP" : "",
> +      (v & HSTATUS_SPV)  ? " SPV"  : "",
> +      (v & HSTATUS_GVA)  ? " GVA"  : "");
> +    X(hgatp, CSR_HGATP, "\n");
> +    X(hstateen0, CSR_HSTATEEN0, "\n");
> +    X(stvec, CSR_STVEC, " "); X(vstvec, CSR_VSTVEC, "\n");
> +    X(sepc, CSR_SEPC, " "); X(vsepc, CSR_VSEPC, "\n");

... the one logged here? Nothing changes the register between entry
into the hypervisor and coming here?

Jan

Reply via email to