powerpc: interrupt handler wrapper functions
authorNicholas Piggin <npiggin@gmail.com>
Sat, 30 Jan 2021 13:08:36 +0000 (23:08 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 8 Feb 2021 13:02:11 +0000 (00:02 +1100)
Add wrapper functions (derived from x86 macros) for interrupt handler
functions. This allows interrupt entry code to be written in C.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210130130852.2952424-27-npiggin@gmail.com
arch/powerpc/include/asm/interrupt.h [new file with mode: 0644]

diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
new file mode 100644 (file)
index 0000000..5e2526a
--- /dev/null
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _ASM_POWERPC_INTERRUPT_H
+#define _ASM_POWERPC_INTERRUPT_H
+
+#include <linux/context_tracking.h>
+#include <asm/ftrace.h>
+
+/**
+ * DECLARE_INTERRUPT_HANDLER_RAW - Declare raw interrupt handler function
+ * @func:      Function name of the entry point
+ * @returns:   Returns a value back to asm caller
+ */
+#define DECLARE_INTERRUPT_HANDLER_RAW(func)                            \
+       __visible long func(struct pt_regs *regs)
+
+/**
+ * DEFINE_INTERRUPT_HANDLER_RAW - Define raw interrupt handler function
+ * @func:      Function name of the entry point
+ * @returns:   Returns a value back to asm caller
+ *
+ * @func is called from ASM entry code.
+ *
+ * This is a plain function which does no tracing, reconciling, etc.
+ * The macro is written so it acts as function definition. Append the
+ * body with a pair of curly brackets.
+ *
+ * raw interrupt handlers must not enable or disable interrupts, or
+ * schedule, tracing and instrumentation (ftrace, lockdep, etc) would
+ * not be advisable either, although may be possible in a pinch, the
+ * trace will look odd at least.
+ *
+ * A raw handler may call one of the other interrupt handler functions
+ * to be converted into that interrupt context without these restrictions.
+ *
+ * On PPC64, _RAW handlers may return with fast_interrupt_return.
+ *
+ * Specific handlers may have additional restrictions.
+ */
+#define DEFINE_INTERRUPT_HANDLER_RAW(func)                             \
+static __always_inline long ____##func(struct pt_regs *regs);          \
+                                                                       \
+__visible noinstr long func(struct pt_regs *regs)                      \
+{                                                                      \
+       long ret;                                                       \
+                                                                       \
+       ret = ____##func (regs);                                        \
+                                                                       \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static __always_inline long ____##func(struct pt_regs *regs)
+
+/**
+ * DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function
+ * @func:      Function name of the entry point
+ */
+#define DECLARE_INTERRUPT_HANDLER(func)                                        \
+       __visible void func(struct pt_regs *regs)
+
+/**
+ * DEFINE_INTERRUPT_HANDLER - Define synchronous interrupt handler function
+ * @func:      Function name of the entry point
+ *
+ * @func is called from ASM entry code.
+ *
+ * The macro is written so it acts as function definition. Append the
+ * body with a pair of curly brackets.
+ */
+#define DEFINE_INTERRUPT_HANDLER(func)                                 \
+static __always_inline void ____##func(struct pt_regs *regs);          \
+                                                                       \
+__visible noinstr void func(struct pt_regs *regs)                      \
+{                                                                      \
+       ____##func (regs);                                              \
+}                                                                      \
+                                                                       \
+static __always_inline void ____##func(struct pt_regs *regs)
+
+/**
+ * DECLARE_INTERRUPT_HANDLER_RET - Declare synchronous interrupt handler function
+ * @func:      Function name of the entry point
+ * @returns:   Returns a value back to asm caller
+ */
+#define DECLARE_INTERRUPT_HANDLER_RET(func)                            \
+       __visible long func(struct pt_regs *regs)
+
+/**
+ * DEFINE_INTERRUPT_HANDLER_RET - Define synchronous interrupt handler function
+ * @func:      Function name of the entry point
+ * @returns:   Returns a value back to asm caller
+ *
+ * @func is called from ASM entry code.
+ *
+ * The macro is written so it acts as function definition. Append the
+ * body with a pair of curly brackets.
+ */
+#define DEFINE_INTERRUPT_HANDLER_RET(func)                             \
+static __always_inline long ____##func(struct pt_regs *regs);          \
+                                                                       \
+__visible noinstr long func(struct pt_regs *regs)                      \
+{                                                                      \
+       long ret;                                                       \
+                                                                       \
+       ret = ____##func (regs);                                        \
+                                                                       \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static __always_inline long ____##func(struct pt_regs *regs)
+
+/**
+ * DECLARE_INTERRUPT_HANDLER_ASYNC - Declare asynchronous interrupt handler function
+ * @func:      Function name of the entry point
+ */
+#define DECLARE_INTERRUPT_HANDLER_ASYNC(func)                          \
+       __visible void func(struct pt_regs *regs)
+
+/**
+ * DEFINE_INTERRUPT_HANDLER_ASYNC - Define asynchronous interrupt handler function
+ * @func:      Function name of the entry point
+ *
+ * @func is called from ASM entry code.
+ *
+ * The macro is written so it acts as function definition. Append the
+ * body with a pair of curly brackets.
+ */
+#define DEFINE_INTERRUPT_HANDLER_ASYNC(func)                           \
+static __always_inline void ____##func(struct pt_regs *regs);          \
+                                                                       \
+__visible noinstr void func(struct pt_regs *regs)                      \
+{                                                                      \
+       ____##func (regs);                                              \
+}                                                                      \
+                                                                       \
+static __always_inline void ____##func(struct pt_regs *regs)
+
+/**
+ * DECLARE_INTERRUPT_HANDLER_NMI - Declare NMI interrupt handler function
+ * @func:      Function name of the entry point
+ * @returns:   Returns a value back to asm caller
+ */
+#define DECLARE_INTERRUPT_HANDLER_NMI(func)                            \
+       __visible long func(struct pt_regs *regs)
+
+/**
+ * DEFINE_INTERRUPT_HANDLER_NMI - Define NMI interrupt handler function
+ * @func:      Function name of the entry point
+ * @returns:   Returns a value back to asm caller
+ *
+ * @func is called from ASM entry code.
+ *
+ * The macro is written so it acts as function definition. Append the
+ * body with a pair of curly brackets.
+ */
+#define DEFINE_INTERRUPT_HANDLER_NMI(func)                             \
+static __always_inline long ____##func(struct pt_regs *regs);          \
+                                                                       \
+__visible noinstr long func(struct pt_regs *regs)                      \
+{                                                                      \
+       long ret;                                                       \
+                                                                       \
+       ret = ____##func (regs);                                        \
+                                                                       \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static __always_inline long ____##func(struct pt_regs *regs)
+
+#endif /* _ASM_POWERPC_INTERRUPT_H */