summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2021-06-19 06:50:36 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2021-06-24 08:53:47 +0200
commit6f60b81ff0dc155161606b057952eadab71806e6 (patch)
tree127c537f5109fd8f57d9845c9cdef5a6520b7e59
parent0e885ce81d0e5aca3c73a96a5d8004047035f28a (diff)
downloadbarebox-6f60b81ff0dc155161606b057952eadab71806e6.tar.gz
barebox-6f60b81ff0dc155161606b057952eadab71806e6.tar.xz
RISC-V: add exception support
Add S- and M-Mode support for dumping registers when catching unexpected CPU exceptions. Load access faults when data_abort_mask is active will be skipped over. This allows outputting xxx when doing md /dev/mem for non-accessible space. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20210619045055.779-11-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/riscv/Kconfig5
-rw-r--r--arch/riscv/boot/start.c3
-rw-r--r--arch/riscv/boot/uncompress.c3
-rw-r--r--arch/riscv/cpu/Makefile3
-rw-r--r--arch/riscv/cpu/interrupts.c130
-rw-r--r--arch/riscv/cpu/mtrap.S30
-rw-r--r--arch/riscv/cpu/strap.S30
-rw-r--r--arch/riscv/include/asm/asm-offsets.h1
-rw-r--r--arch/riscv/include/asm/irq.h107
-rw-r--r--arch/riscv/include/asm/ptrace.h143
-rw-r--r--arch/riscv/include/asm/unwind.h9
-rw-r--r--arch/riscv/lib/asm-offsets.c46
12 files changed, 510 insertions, 0 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index bbafdea1b9..a814a1a45b 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -77,6 +77,11 @@ config RISCV_OPTIMZED_STRING_FUNCTIONS
These functions work faster than the normal versions but increase
your binary size.
+config RISCV_EXCEPTIONS
+ bool "enable exception handling support"
+ default y
+ select ARCH_HAS_DATA_ABORT_MASK
+
config HAS_NMON
bool
diff --git a/arch/riscv/boot/start.c b/arch/riscv/boot/start.c
index 82bd02d0a0..72ab93cb76 100644
--- a/arch/riscv/boot/start.c
+++ b/arch/riscv/boot/start.c
@@ -16,6 +16,7 @@
#include <uncompress.h>
#include <malloc.h>
#include <compressed-dtb.h>
+#include <asm/irq.h>
#include <debug_ll.h>
@@ -122,6 +123,8 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize,
barrier();
+ irq_init_vector(__riscv_mode(flags));
+
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
riscv_endmem = endmem;
diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c
index 35a91e8cb6..c6c20b38e3 100644
--- a/arch/riscv/boot/uncompress.c
+++ b/arch/riscv/boot/uncompress.c
@@ -14,6 +14,7 @@
#include <asm-generic/memory_layout.h>
#include <asm/sections.h>
#include <asm/unaligned.h>
+#include <asm/irq.h>
#include <debug_ll.h>
@@ -32,6 +33,8 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
void *pg_start, *pg_end;
unsigned long pc = get_pc();
+ irq_init_vector(__riscv_mode(flags));
+
/* piggy data is not relocated, so determine the bounds now */
pg_start = input_data + get_runtime_offset();
pg_end = input_data_end + get_runtime_offset();
diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile
index 9ce77ad869..717baaaaa7 100644
--- a/arch/riscv/cpu/Makefile
+++ b/arch/riscv/cpu/Makefile
@@ -2,3 +2,6 @@
obj-y += core.o time.o
obj-$(CONFIG_HAS_DMA) += dma.o
+obj-pbl-$(CONFIG_RISCV_M_MODE) += mtrap.o
+obj-pbl-$(CONFIG_RISCV_S_MODE) += strap.o
+obj-pbl-y += interrupts.o
diff --git a/arch/riscv/cpu/interrupts.c b/arch/riscv/cpu/interrupts.c
new file mode 100644
index 0000000000..df6d3e6e01
--- /dev/null
+++ b/arch/riscv/cpu/interrupts.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2016-17 Microsemi Corporation.
+ * Padmarao Begari, Microsemi Corporation <padmarao.begari@microsemi.com>
+ *
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ *
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/irq.h>
+#include <asm/csr.h>
+#include <abort.h>
+#include <pbl.h>
+
+#define MCAUSE32_INT 0x80000000
+#define MCAUSE64_INT 0x8000000000000000
+
+#ifdef CONFIG_64BIT
+# define MCAUSE_INT MCAUSE64_INT
+#else
+# define MCAUSE_INT MCAUSE32_INT
+#endif
+
+static void show_regs(const struct pt_regs *regs)
+{
+ printf("\nsp: " REG_FMT " gp: " REG_FMT " tp: " REG_FMT "\n",
+ regs->sp, regs->gp, regs->tp);
+ printf("t0: " REG_FMT " t1: " REG_FMT " t2: " REG_FMT "\n",
+ regs->t0, regs->t1, regs->t2);
+ printf("s0: " REG_FMT " s1: " REG_FMT " a0: " REG_FMT "\n",
+ regs->s0, regs->s1, regs->a0);
+ printf("a1: " REG_FMT " a2: " REG_FMT " a3: " REG_FMT "\n",
+ regs->a1, regs->a2, regs->a3);
+ printf("a4: " REG_FMT " a5: " REG_FMT " a6: " REG_FMT "\n",
+ regs->a4, regs->a5, regs->a6);
+ printf("a7: " REG_FMT " s2: " REG_FMT " s3: " REG_FMT "\n",
+ regs->a7, regs->s2, regs->s3);
+ printf("s4: " REG_FMT " s5: " REG_FMT " s6: " REG_FMT "\n",
+ regs->s4, regs->s5, regs->s6);
+ printf("s7: " REG_FMT " s8: " REG_FMT " s9: " REG_FMT "\n",
+ regs->s7, regs->s8, regs->s9);
+ printf("s10: " REG_FMT " s11: " REG_FMT " t3: " REG_FMT "\n",
+ regs->s10, regs->s11, regs->t3);
+ printf("t4: " REG_FMT " t5: " REG_FMT " t6: " REG_FMT "\n",
+ regs->t4, regs->t5, regs->t6);
+}
+
+static void report_trap(const struct pt_regs *regs)
+{
+ static const char * const exception_code[] = {
+ [0] = "Instruction address misaligned",
+ [1] = "Instruction access fault",
+ [2] = "Illegal instruction",
+ [3] = "Breakpoint",
+ [4] = "Load address misaligned",
+ [5] = "Load access fault",
+ [6] = "Store/AMO address misaligned",
+ [7] = "Store/AMO access fault",
+ [8] = "Environment call from U-mode",
+ [9] = "Environment call from S-mode",
+ [10] = "Reserved",
+ [11] = "Environment call from M-mode",
+ [12] = "Instruction page fault",
+ [13] = "Load page fault",
+ [14] = "Reserved",
+ [15] = "Store/AMO page fault",
+
+ };
+
+ printf("Unhandled exception: %ld", regs->cause);
+
+ if (regs->cause < ARRAY_SIZE(exception_code))
+ printf(" \"%s\"\n", exception_code[regs->cause]);
+
+ printf("E [<" REG_FMT ">] ra: [<" REG_FMT ">] tval: " REG_FMT "\n",
+ regs->epc, regs->ra, regs->badaddr);
+
+ show_regs(regs);
+}
+
+
+
+#ifdef __PBL__
+
+static inline bool skip_data_abort(struct pt_regs *regs)
+{
+ return false;
+}
+
+#else
+
+static volatile bool riscv_data_abort_occurred;
+static volatile bool riscv_ignore_data_abort;
+
+void data_abort_mask(void)
+{
+ riscv_data_abort_occurred = false;
+ riscv_ignore_data_abort = true;
+}
+
+int data_abort_unmask(void)
+{
+ riscv_ignore_data_abort = false;
+ return riscv_data_abort_occurred;
+}
+
+static inline bool skip_data_abort(struct pt_regs *regs)
+{
+ return regs->cause == EXC_LOAD_ACCESS && riscv_ignore_data_abort;
+}
+
+#endif
+
+unsigned long handle_trap(struct pt_regs *regs)
+{
+ if (skip_data_abort(regs))
+ goto skip;
+
+ report_trap(regs);
+ hang();
+
+skip:
+ return regs->epc + 4;
+}
+
diff --git a/arch/riscv/cpu/mtrap.S b/arch/riscv/cpu/mtrap.S
new file mode 100644
index 0000000000..e4aba7d694
--- /dev/null
+++ b/arch/riscv/cpu/mtrap.S
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 FORTH-ICS/CARV
+ * Nick Kossifidis <mick@ics.forth.gr>
+ */
+
+#include <asm/asm.h>
+#include <asm/irq.h>
+#include <linux/linkage.h>
+
+.section .text.mtrap_entry
+ENTRY(mtrap_entry)
+ addi sp, sp, -PT_SIZE_ON_STACK
+ pt_regs_push sp
+ csrr t1, mstatus
+ csrr t2, mepc
+ csrr t3, mtval
+ csrr t4, mcause
+
+ REG_S t1, PT_STATUS(sp)
+ REG_S t2, PT_EPC(sp)
+ REG_S t3, PT_BADADDR(sp)
+ REG_S t4, PT_CAUSE(sp)
+ mv a0, sp
+ jal handle_trap
+ csrw mepc, a0
+ pt_regs_pop sp
+ addi sp, sp, PT_SIZE_ON_STACK
+ mret
+ENDPROC(mtrap_entry)
diff --git a/arch/riscv/cpu/strap.S b/arch/riscv/cpu/strap.S
new file mode 100644
index 0000000000..c1d684c194
--- /dev/null
+++ b/arch/riscv/cpu/strap.S
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 FORTH-ICS/CARV
+ * Nick Kossifidis <mick@ics.forth.gr>
+ */
+
+#include <asm/asm.h>
+#include <asm/irq.h>
+#include <linux/linkage.h>
+
+.section .text.strap_entry
+ENTRY(strap_entry)
+ addi sp, sp, -PT_SIZE_ON_STACK
+ pt_regs_push sp
+ csrr t1, sstatus
+ csrr t2, sepc
+ csrr t3, stval
+ csrr t4, scause
+
+ REG_S t1, PT_STATUS(sp)
+ REG_S t2, PT_EPC(sp)
+ REG_S t3, PT_BADADDR(sp)
+ REG_S t4, PT_CAUSE(sp)
+ mv a0, sp
+ jal handle_trap
+ csrw sepc, a0
+ pt_regs_pop sp
+ addi sp, sp, PT_SIZE_ON_STACK
+ sret
+ENDPROC(strap_entry)
diff --git a/arch/riscv/include/asm/asm-offsets.h b/arch/riscv/include/asm/asm-offsets.h
new file mode 100644
index 0000000000..d370ee36a1
--- /dev/null
+++ b/arch/riscv/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
new file mode 100644
index 0000000000..fde7589baa
--- /dev/null
+++ b/arch/riscv/include/asm/irq.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef RISCV_ASM_IRQ_H__
+#define RISCV_ASM_IRQ_H__
+
+#include <asm/csr.h>
+#include <asm/system.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/barebox-riscv.h>
+void strap_entry(void);
+void mtrap_entry(void);
+unsigned long handle_trap(struct pt_regs *regs);
+
+static inline void irq_init_vector(enum riscv_mode mode)
+{
+ switch (mode) {
+#ifdef CONFIG_RISCV_EXCEPTIONS
+ case RISCV_S_MODE:
+ asm volatile ("csrw stvec, %0; csrw sie, zero" : :
+ "r"(strap_entry + get_runtime_offset()));
+ break;
+ case RISCV_M_MODE:
+ asm volatile ("csrw mtvec, %0; csrw mie, zero" : :
+ "r"(mtrap_entry + get_runtime_offset()));
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+#else
+
+.macro pt_regs_push ptr
+ REG_S ra, PT_RA(\ptr) /* x1 */
+ REG_S sp, PT_SP(\ptr) /* x2 */
+ REG_S gp, PT_GP(\ptr) /* x3 */
+ REG_S tp, PT_TP(\ptr) /* x4 */
+ REG_S t0, PT_T0(\ptr) /* x5 */
+ REG_S t1, PT_T1(\ptr) /* x6 */
+ REG_S t2, PT_T2(\ptr) /* x7 */
+ REG_S s0, PT_S0(\ptr) /* x8/fp */
+ REG_S s1, PT_S1(\ptr) /* x9 */
+ REG_S a0, PT_A0(\ptr) /* x10 */
+ REG_S a1, PT_A1(\ptr) /* x11 */
+ REG_S a2, PT_A2(\ptr) /* x12 */
+ REG_S a3, PT_A3(\ptr) /* x13 */
+ REG_S a4, PT_A4(\ptr) /* x14 */
+ REG_S a5, PT_A5(\ptr) /* x15 */
+ REG_S a6, PT_A6(\ptr) /* x16 */
+ REG_S a7, PT_A7(\ptr) /* x17 */
+ REG_S s2, PT_S2(\ptr) /* x18 */
+ REG_S s3, PT_S3(\ptr) /* x19 */
+ REG_S s4, PT_S4(\ptr) /* x20 */
+ REG_S s5, PT_S5(\ptr) /* x21 */
+ REG_S s6, PT_S6(\ptr) /* x22 */
+ REG_S s7, PT_S7(\ptr) /* x23 */
+ REG_S s8, PT_S8(\ptr) /* x24 */
+ REG_S s9, PT_S9(\ptr) /* x25 */
+ REG_S s10, PT_S10(\ptr) /* x26 */
+ REG_S s11, PT_S11(\ptr) /* x27 */
+ REG_S t3, PT_T3(\ptr) /* x28 */
+ REG_S t4, PT_T4(\ptr) /* x29 */
+ REG_S t5, PT_T5(\ptr) /* x30 */
+ REG_S t6, PT_T6(\ptr) /* x31 */
+.endm
+
+.macro pt_regs_pop ptr
+ REG_L ra, PT_RA(\ptr) /* x1 */
+ REG_L sp, PT_SP(\ptr) /* x2 */
+ REG_L gp, PT_GP(\ptr) /* x3 */
+ REG_L tp, PT_TP(\ptr) /* x4 */
+ REG_L t0, PT_T0(\ptr) /* x5 */
+ REG_L t1, PT_T1(\ptr) /* x6 */
+ REG_L t2, PT_T2(\ptr) /* x7 */
+ REG_L s0, PT_S0(\ptr) /* x8/fp */
+ REG_L s1, PT_S1(\ptr) /* x9 */
+ REG_L a0, PT_A0(\ptr) /* x10 */
+ REG_L a1, PT_A1(\ptr) /* x11 */
+ REG_L a2, PT_A2(\ptr) /* x12 */
+ REG_L a3, PT_A3(\ptr) /* x13 */
+ REG_L a4, PT_A4(\ptr) /* x14 */
+ REG_L a5, PT_A5(\ptr) /* x15 */
+ REG_L a6, PT_A6(\ptr) /* x16 */
+ REG_L a7, PT_A7(\ptr) /* x17 */
+ REG_L s2, PT_S2(\ptr) /* x18 */
+ REG_L s3, PT_S3(\ptr) /* x19 */
+ REG_L s4, PT_S4(\ptr) /* x20 */
+ REG_L s5, PT_S5(\ptr) /* x21 */
+ REG_L s6, PT_S6(\ptr) /* x22 */
+ REG_L s7, PT_S7(\ptr) /* x23 */
+ REG_L s8, PT_S8(\ptr) /* x24 */
+ REG_L s9, PT_S9(\ptr) /* x25 */
+ REG_L s10, PT_S10(\ptr) /* x26 */
+ REG_L s11, PT_S11(\ptr) /* x27 */
+ REG_L t3, PT_T3(\ptr) /* x28 */
+ REG_L t4, PT_T4(\ptr) /* x29 */
+ REG_L t5, PT_T5(\ptr) /* x30 */
+ REG_L t6, PT_T6(\ptr) /* x31 */
+.endm
+
+#endif
+
+#endif
diff --git a/arch/riscv/include/asm/ptrace.h b/arch/riscv/include/asm/ptrace.h
new file mode 100644
index 0000000000..b5e792f666
--- /dev/null
+++ b/arch/riscv/include/asm/ptrace.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ */
+
+#ifndef _ASM_RISCV_PTRACE_H
+#define _ASM_RISCV_PTRACE_H
+
+#include <asm/csr.h>
+#include <linux/compiler.h>
+
+#ifndef __ASSEMBLY__
+
+struct pt_regs {
+ unsigned long epc;
+ unsigned long ra;
+ unsigned long sp;
+ unsigned long gp;
+ unsigned long tp;
+ unsigned long t0;
+ unsigned long t1;
+ unsigned long t2;
+ unsigned long s0;
+ unsigned long s1;
+ unsigned long a0;
+ unsigned long a1;
+ unsigned long a2;
+ unsigned long a3;
+ unsigned long a4;
+ unsigned long a5;
+ unsigned long a6;
+ unsigned long a7;
+ unsigned long s2;
+ unsigned long s3;
+ unsigned long s4;
+ unsigned long s5;
+ unsigned long s6;
+ unsigned long s7;
+ unsigned long s8;
+ unsigned long s9;
+ unsigned long s10;
+ unsigned long s11;
+ unsigned long t3;
+ unsigned long t4;
+ unsigned long t5;
+ unsigned long t6;
+ /* Supervisor/Machine CSRs */
+ unsigned long status;
+ unsigned long badaddr;
+ unsigned long cause;
+};
+
+#ifdef CONFIG_64BIT
+#define REG_FMT "%016lx"
+#else
+#define REG_FMT "%08lx"
+#endif
+
+#define user_mode(regs) (((regs)->status & SR_PP) == 0)
+
+#define MAX_REG_OFFSET offsetof(struct pt_regs, cause)
+
+/* Helpers for working with the instruction pointer */
+static inline unsigned long instruction_pointer(struct pt_regs *regs)
+{
+ return regs->epc;
+}
+static inline void instruction_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->epc = val;
+}
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* Helpers for working with the user stack pointer */
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ return regs->sp;
+}
+static inline void user_stack_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->sp = val;
+}
+
+/* Valid only for Kernel mode traps. */
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+ return regs->sp;
+}
+
+/* Helpers for working with the frame pointer */
+static inline unsigned long frame_pointer(struct pt_regs *regs)
+{
+ return regs->s0;
+}
+static inline void frame_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->s0 = val;
+}
+
+static inline unsigned long regs_return_value(struct pt_regs *regs)
+{
+ return regs->a0;
+}
+
+static inline void regs_set_return_value(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->a0 = val;
+}
+
+extern int regs_query_register_offset(const char *name);
+extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
+ unsigned int n);
+
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+ unsigned long frame_pointer);
+int do_syscall_trace_enter(struct pt_regs *regs);
+void do_syscall_trace_exit(struct pt_regs *regs);
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs: pt_regs from which register value is gotten
+ * @offset: offset of the register.
+ *
+ * regs_get_register returns the value of a register whose offset from @regs.
+ * The @offset is the offset of the register in struct pt_regs.
+ * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+ unsigned int offset)
+{
+ if (unlikely(offset > MAX_REG_OFFSET))
+ return 0;
+
+ return *(unsigned long *)((unsigned long)regs + offset);
+}
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_RISCV_PTRACE_H */
diff --git a/arch/riscv/include/asm/unwind.h b/arch/riscv/include/asm/unwind.h
new file mode 100644
index 0000000000..9e5c8b5420
--- /dev/null
+++ b/arch/riscv/include/asm/unwind.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef RISCV_ASM_UNWIND_H__
+#define RISCV_ASM_UNWIND_H__
+
+struct pt_regs;
+
+void unwind_backtrace(struct pt_regs *regs);
+
+#endif
diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c
index 22f382b71e..4b869690f1 100644
--- a/arch/riscv/lib/asm-offsets.c
+++ b/arch/riscv/lib/asm-offsets.c
@@ -5,8 +5,54 @@
*/
#include <linux/kbuild.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+
+#define STACK_ALIGN 16
int main(void)
{
+ DEFINE(PT_SIZE, sizeof(struct pt_regs));
+ OFFSET(PT_EPC, pt_regs, epc);
+ OFFSET(PT_RA, pt_regs, ra);
+ OFFSET(PT_FP, pt_regs, s0);
+ OFFSET(PT_S0, pt_regs, s0);
+ OFFSET(PT_S1, pt_regs, s1);
+ OFFSET(PT_S2, pt_regs, s2);
+ OFFSET(PT_S3, pt_regs, s3);
+ OFFSET(PT_S4, pt_regs, s4);
+ OFFSET(PT_S5, pt_regs, s5);
+ OFFSET(PT_S6, pt_regs, s6);
+ OFFSET(PT_S7, pt_regs, s7);
+ OFFSET(PT_S8, pt_regs, s8);
+ OFFSET(PT_S9, pt_regs, s9);
+ OFFSET(PT_S10, pt_regs, s10);
+ OFFSET(PT_S11, pt_regs, s11);
+ OFFSET(PT_SP, pt_regs, sp);
+ OFFSET(PT_TP, pt_regs, tp);
+ OFFSET(PT_A0, pt_regs, a0);
+ OFFSET(PT_A1, pt_regs, a1);
+ OFFSET(PT_A2, pt_regs, a2);
+ OFFSET(PT_A3, pt_regs, a3);
+ OFFSET(PT_A4, pt_regs, a4);
+ OFFSET(PT_A5, pt_regs, a5);
+ OFFSET(PT_A6, pt_regs, a6);
+ OFFSET(PT_A7, pt_regs, a7);
+ OFFSET(PT_T0, pt_regs, t0);
+ OFFSET(PT_T1, pt_regs, t1);
+ OFFSET(PT_T2, pt_regs, t2);
+ OFFSET(PT_T3, pt_regs, t3);
+ OFFSET(PT_T4, pt_regs, t4);
+ OFFSET(PT_T5, pt_regs, t5);
+ OFFSET(PT_T6, pt_regs, t6);
+ OFFSET(PT_GP, pt_regs, gp);
+ OFFSET(PT_STATUS, pt_regs, status);
+ OFFSET(PT_BADADDR, pt_regs, badaddr);
+ OFFSET(PT_CAUSE, pt_regs, cause);
+
+ /*
+ * We allocate a pt_regs on the stack. This ensures the alignment is sane.
+ */
+ DEFINE(PT_SIZE_ON_STACK, ALIGN(sizeof(struct pt_regs), STACK_ALIGN));
return 0;
}