[PATCH v2 10/29] RISC-V: add exception support

Ahmad Fatoum a.fatoum at pengutronix.de
Fri Jun 18 21:50:36 PDT 2021


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 at pengutronix.de>
---
 arch/riscv/Kconfig                   |   5 +
 arch/riscv/boot/start.c              |   3 +
 arch/riscv/boot/uncompress.c         |   3 +
 arch/riscv/cpu/Makefile              |   3 +
 arch/riscv/cpu/interrupts.c          | 130 ++++++++++++++++++++++++
 arch/riscv/cpu/mtrap.S               |  30 ++++++
 arch/riscv/cpu/strap.S               |  30 ++++++
 arch/riscv/include/asm/asm-offsets.h |   1 +
 arch/riscv/include/asm/irq.h         | 107 ++++++++++++++++++++
 arch/riscv/include/asm/ptrace.h      | 143 +++++++++++++++++++++++++++
 arch/riscv/include/asm/unwind.h      |   9 ++
 arch/riscv/lib/asm-offsets.c         |  46 +++++++++
 12 files changed, 510 insertions(+)
 create mode 100644 arch/riscv/cpu/interrupts.c
 create mode 100644 arch/riscv/cpu/mtrap.S
 create mode 100644 arch/riscv/cpu/strap.S
 create mode 100644 arch/riscv/include/asm/asm-offsets.h
 create mode 100644 arch/riscv/include/asm/irq.h
 create mode 100644 arch/riscv/include/asm/ptrace.h
 create mode 100644 arch/riscv/include/asm/unwind.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index bbafdea1b959..a814a1a45b1c 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 82bd02d0a0d0..72ab93cb7691 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 35a91e8cb62a..c6c20b38e390 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 9ce77ad869cd..717baaaaa727 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 000000000000..df6d3e6e010b
--- /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 at microsemi.com>
+ *
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick at andestech.com>
+ *
+ * Copyright (C) 2019 Sean Anderson <seanga2 at 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 000000000000..e4aba7d69415
--- /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 at 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 000000000000..c1d684c19425
--- /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 at 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 000000000000..d370ee36a182
--- /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 000000000000..fde7589baa80
--- /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 000000000000..b5e792f6669b
--- /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 000000000000..9e5c8b542094
--- /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 22f382b71e7b..4b869690f198 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;
 }
-- 
2.29.2




More information about the barebox mailing list