diff mbox series

[v1,08/14] xen/riscv: introduce decode_cause() stuff

Message ID c798832ec19cb94c0a27e8cff8f5bd6d1aa6ae7e.1674226563.git.oleksii.kurochko@gmail.com (mailing list archive)
State Superseded
Headers show
Series RISCV basic exception handling implementation | expand

Commit Message

Oleksii Kurochko Jan. 20, 2023, 2:59 p.m. UTC
The patch introduces stuff needed to decode a reason of an
exception.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
 xen/arch/riscv/traps.c | 88 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

Comments

Alistair Francis Jan. 22, 2023, 11:38 p.m. UTC | #1
On Sat, Jan 21, 2023 at 1:00 AM Oleksii Kurochko
<oleksii.kurochko@gmail.com> wrote:
>
> The patch introduces stuff needed to decode a reason of an
> exception.
>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  xen/arch/riscv/traps.c | 88 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 88 insertions(+)
>
> diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
> index 3201b851ef..dd64f053a5 100644
> --- a/xen/arch/riscv/traps.c
> +++ b/xen/arch/riscv/traps.c
> @@ -4,8 +4,96 @@
>   *
>   * RISC-V Trap handlers
>   */
> +#include <asm/csr.h>
> +#include <asm/early_printk.h>
>  #include <asm/processor.h>
>  #include <asm/traps.h>
> +#include <xen/errno.h>
> +
> +const char *decode_trap_cause(unsigned long cause)
> +{
> +    switch ( cause )
> +    {
> +    case CAUSE_MISALIGNED_FETCH:
> +        return "Instruction Address Misaligned";
> +    case CAUSE_FETCH_ACCESS:
> +        return "Instruction Access Fault";
> +    case CAUSE_ILLEGAL_INSTRUCTION:
> +        return "Illegal Instruction";
> +    case CAUSE_BREAKPOINT:
> +        return "Breakpoint";
> +    case CAUSE_MISALIGNED_LOAD:
> +        return "Load Address Misaligned";
> +    case CAUSE_LOAD_ACCESS:
> +        return "Load Access Fault";
> +    case CAUSE_MISALIGNED_STORE:
> +        return "Store/AMO Address Misaligned";
> +    case CAUSE_STORE_ACCESS:
> +        return "Store/AMO Access Fault";
> +    case CAUSE_USER_ECALL:
> +        return "Environment Call from U-Mode";
> +    case CAUSE_SUPERVISOR_ECALL:
> +        return "Environment Call from S-Mode";
> +    case CAUSE_MACHINE_ECALL:
> +        return "Environment Call from M-Mode";
> +    case CAUSE_FETCH_PAGE_FAULT:
> +        return "Instruction Page Fault";
> +    case CAUSE_LOAD_PAGE_FAULT:
> +        return "Load Page Fault";
> +    case CAUSE_STORE_PAGE_FAULT:
> +        return "Store/AMO Page Fault";
> +    case CAUSE_FETCH_GUEST_PAGE_FAULT:
> +        return "Instruction Guest Page Fault";
> +    case CAUSE_LOAD_GUEST_PAGE_FAULT:
> +        return "Load Guest Page Fault";
> +    case CAUSE_VIRTUAL_INST_FAULT:
> +        return "Virtualized Instruction Fault";
> +    case CAUSE_STORE_GUEST_PAGE_FAULT:
> +        return "Guest Store/AMO Page Fault";
> +    default:
> +        return "UNKNOWN";
> +    }
> +}
> +
> +const char *decode_reserved_interrupt_cause(unsigned long irq_cause)
> +{
> +    switch ( irq_cause )
> +    {
> +    case IRQ_M_SOFT:
> +        return "M-mode Software Interrupt";
> +    case IRQ_M_TIMER:
> +        return "M-mode TIMER Interrupt";
> +    case IRQ_M_EXT:
> +        return "M-mode TIMER Interrupt";
> +    default:
> +        return "UNKNOWN IRQ type";
> +    }
> +}
> +
> +const char *decode_interrupt_cause(unsigned long cause)
> +{
> +    unsigned long irq_cause = cause & ~CAUSE_IRQ_FLAG;
> +
> +    switch ( irq_cause )
> +    {
> +    case IRQ_S_SOFT:
> +        return "Supervisor Software Interrupt";
> +    case IRQ_S_TIMER:
> +        return "Supervisor Timer Interrupt";
> +    case IRQ_S_EXT:
> +        return "Supervisor External Interrupt";
> +    default:
> +        return decode_reserved_interrupt_cause(irq_cause);
> +    }
> +}
> +
> +const char *decode_cause(unsigned long cause)
> +{
> +    if ( cause & CAUSE_IRQ_FLAG )
> +        return decode_interrupt_cause(cause);
> +
> +    return decode_trap_cause(cause);
> +}
>
>  void __handle_exception(struct cpu_user_regs *cpu_regs)
>  {
> --
> 2.39.0
>
>
Andrew Cooper Jan. 23, 2023, 12:09 p.m. UTC | #2
On 20/01/2023 2:59 pm, Oleksii Kurochko wrote:
> diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
> index 3201b851ef..dd64f053a5 100644
> --- a/xen/arch/riscv/traps.c
> +++ b/xen/arch/riscv/traps.c
> @@ -4,8 +4,96 @@
>   *
>   * RISC-V Trap handlers
>   */
> +#include <asm/csr.h>
> +#include <asm/early_printk.h>
>  #include <asm/processor.h>
>  #include <asm/traps.h>
> +#include <xen/errno.h>
> +
> +const char *decode_trap_cause(unsigned long cause)

These should be static as you've not put a declaration in a header
file.  But as it stands, you'll then get a compiler warning on
decode_cause() as it's not used.

I would merge this patch with the following patch, as the following
patch is very related to this, and then you can get everything nicely
static without unused warnings.

> +{
> +    switch ( cause )
> +    {
> +    case CAUSE_MISALIGNED_FETCH:
> +        return "Instruction Address Misaligned";
> +    case CAUSE_FETCH_ACCESS:
> +        return "Instruction Access Fault";
> +    case CAUSE_ILLEGAL_INSTRUCTION:
> +        return "Illegal Instruction";
> +    case CAUSE_BREAKPOINT:
> +        return "Breakpoint";
> +    case CAUSE_MISALIGNED_LOAD:
> +        return "Load Address Misaligned";
> +    case CAUSE_LOAD_ACCESS:
> +        return "Load Access Fault";
> +    case CAUSE_MISALIGNED_STORE:
> +        return "Store/AMO Address Misaligned";
> +    case CAUSE_STORE_ACCESS:
> +        return "Store/AMO Access Fault";
> +    case CAUSE_USER_ECALL:
> +        return "Environment Call from U-Mode";
> +    case CAUSE_SUPERVISOR_ECALL:
> +        return "Environment Call from S-Mode";
> +    case CAUSE_MACHINE_ECALL:
> +        return "Environment Call from M-Mode";
> +    case CAUSE_FETCH_PAGE_FAULT:
> +        return "Instruction Page Fault";
> +    case CAUSE_LOAD_PAGE_FAULT:
> +        return "Load Page Fault";
> +    case CAUSE_STORE_PAGE_FAULT:
> +        return "Store/AMO Page Fault";
> +    case CAUSE_FETCH_GUEST_PAGE_FAULT:
> +        return "Instruction Guest Page Fault";
> +    case CAUSE_LOAD_GUEST_PAGE_FAULT:
> +        return "Load Guest Page Fault";
> +    case CAUSE_VIRTUAL_INST_FAULT:
> +        return "Virtualized Instruction Fault";
> +    case CAUSE_STORE_GUEST_PAGE_FAULT:
> +        return "Guest Store/AMO Page Fault";
> +    default:
> +        return "UNKNOWN";

This style tends to lead to poor code generation.  You probably want:

const char *decode_trap_cause(unsigned long cause)
{
    static const char *const trap_causes[] = {
        [CAUSE_MISALIGNED_FETCH] = "Instruction Address Misaligned",
        ...
        [CAUSE_STORE_GUEST_PAGE_FAULT] = "Guest Store/AMO Page Fault",
    };

    if ( cause < ARRAY_SIZE(trap_causes) && trap_causes[cause] )
        return trap_causes[cause];
    return "UNKNOWN";
}

(note the trailing comma on the final entry, which is there to simply
future diffs)

However, given the hope to get snprintf() wired up, you actually want to
to adjust this to:

    if ( cause < ARRAY_SIZE(trap_causes) )
        return trap_causes[cause];
    return NULL;

And render the raw cause number for the unknown case, because that is
far more useful for whomever is debugging.

~Andrew
diff mbox series

Patch

diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c
index 3201b851ef..dd64f053a5 100644
--- a/xen/arch/riscv/traps.c
+++ b/xen/arch/riscv/traps.c
@@ -4,8 +4,96 @@ 
  *
  * RISC-V Trap handlers
  */
+#include <asm/csr.h>
+#include <asm/early_printk.h>
 #include <asm/processor.h>
 #include <asm/traps.h>
+#include <xen/errno.h>
+
+const char *decode_trap_cause(unsigned long cause)
+{
+    switch ( cause )
+    {
+    case CAUSE_MISALIGNED_FETCH:
+        return "Instruction Address Misaligned";
+    case CAUSE_FETCH_ACCESS:
+        return "Instruction Access Fault";
+    case CAUSE_ILLEGAL_INSTRUCTION:
+        return "Illegal Instruction";
+    case CAUSE_BREAKPOINT:
+        return "Breakpoint";
+    case CAUSE_MISALIGNED_LOAD:
+        return "Load Address Misaligned";
+    case CAUSE_LOAD_ACCESS:
+        return "Load Access Fault";
+    case CAUSE_MISALIGNED_STORE:
+        return "Store/AMO Address Misaligned";
+    case CAUSE_STORE_ACCESS:
+        return "Store/AMO Access Fault";
+    case CAUSE_USER_ECALL:
+        return "Environment Call from U-Mode";
+    case CAUSE_SUPERVISOR_ECALL:
+        return "Environment Call from S-Mode";
+    case CAUSE_MACHINE_ECALL:
+        return "Environment Call from M-Mode";
+    case CAUSE_FETCH_PAGE_FAULT:
+        return "Instruction Page Fault";
+    case CAUSE_LOAD_PAGE_FAULT:
+        return "Load Page Fault";
+    case CAUSE_STORE_PAGE_FAULT:
+        return "Store/AMO Page Fault";
+    case CAUSE_FETCH_GUEST_PAGE_FAULT:
+        return "Instruction Guest Page Fault";
+    case CAUSE_LOAD_GUEST_PAGE_FAULT:
+        return "Load Guest Page Fault";
+    case CAUSE_VIRTUAL_INST_FAULT:
+        return "Virtualized Instruction Fault";
+    case CAUSE_STORE_GUEST_PAGE_FAULT:
+        return "Guest Store/AMO Page Fault";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+const char *decode_reserved_interrupt_cause(unsigned long irq_cause)
+{
+    switch ( irq_cause )
+    {
+    case IRQ_M_SOFT:
+        return "M-mode Software Interrupt";
+    case IRQ_M_TIMER:
+        return "M-mode TIMER Interrupt";
+    case IRQ_M_EXT:
+        return "M-mode TIMER Interrupt";
+    default:
+        return "UNKNOWN IRQ type";
+    }
+}
+
+const char *decode_interrupt_cause(unsigned long cause)
+{
+    unsigned long irq_cause = cause & ~CAUSE_IRQ_FLAG;
+
+    switch ( irq_cause )
+    {
+    case IRQ_S_SOFT:
+        return "Supervisor Software Interrupt";
+    case IRQ_S_TIMER:
+        return "Supervisor Timer Interrupt";
+    case IRQ_S_EXT:
+        return "Supervisor External Interrupt";
+    default:
+        return decode_reserved_interrupt_cause(irq_cause);
+    }
+}
+
+const char *decode_cause(unsigned long cause)
+{
+    if ( cause & CAUSE_IRQ_FLAG )
+        return decode_interrupt_cause(cause);
+
+    return decode_trap_cause(cause);
+}
 
 void __handle_exception(struct cpu_user_regs *cpu_regs)
 {