[PATCH Dovetail v4 1/8] arm: irq_pipeline: Rename and move fault_entry_{enter,exit}
Florian Bezdeka <[email protected]> Tue, 07 Jul 2026 11:50:17 +0200
| Newsgroups | dev.linux.lists.xenomai |
|---|---|
| Message-ID | <20260707-wip-flo-v7-1-arm-pipelining-fixes-v4-1-057b8af5a2ca@siemens.com> |
Introducing a new header allows us to keep the implementation as static inline function and make it re-usable for other compile units. Moving the implementation into existing headers like asm/dovetail.h or asm/irq_pipeline.h would require us to rewrite those helpers as macros. Prefixing with dovetail_ to keep the Linux namespace clean. Signed-off-by: Florian Bezdeka <[email protected]> --- arch/arm/include/asm/trap_entry.h | 83 ++++++++++++++++++++++++++++++++++++ arch/arm/mm/fault.c | 89 ++++++--------------------------------- 2 files changed, 96 insertions(+), 76 deletions(-) diff --git a/arch/arm/include/asm/trap_entry.h b/arch/arm/include/asm/trap_entry.h new file mode 100644 index 0000000000000000000000000000000000000000..abe5f80cd301a8ca5ddb2ca350b80bf5708f0f79 --- /dev/null +++ b/arch/arm/include/asm/trap_entry.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASMARM_TRAP_ENTRY_H +#define _ASMARM_TRAP_ENTRY_H + +#include <asm/dovetail.h> +#include <asm/trace/exceptions.h> + +#ifdef CONFIG_MMU +#ifdef CONFIG_IRQ_PIPELINE +/* + * We need to synchronize the virtual interrupt state with the hard + * interrupt state we received on entry, then turn hardirqs back on to + * allow code which does not require strict serialization to be + * preempted by an out-of-band activity. + */ +static inline unsigned long dovetail_fault_entry(int exception, + struct pt_regs *regs) +{ + unsigned long flags; + + trace_ARM_trap_entry(exception, regs); + + flags = hard_local_save_flags(); + + /* + * The companion core must demote the current context to + * in-band stage if running oob on entry. + */ + mark_trap_entry(exception, regs); + + if (raw_irqs_disabled_flags(flags)) { + stall_inband(); + trace_hardirqs_off(); + } + + hard_local_irq_enable(); + + return flags; +} + +static inline void dovetail_fault_exit(int exception, struct pt_regs *regs, + unsigned long flags) +{ + WARN_ON_ONCE(irq_pipeline_debug() && hard_irqs_disabled()); + + /* + * We expect kentry_exit_pipelined() to clear the stall bit if + * kentry_enter_pipelined() observed it that way. + */ + mark_trap_exit(exception, regs); + trace_ARM_trap_exit(exception, regs); + hard_local_irq_restore(flags); +} + +#else /* !CONFIG_IRQ_PIPELINE */ + +#define dovetail_fault_entry(__exception, __regs) \ + do { \ + (void)(__exception); \ + (void)(__regs); \ + } while (0) + +#define dovetail_fault_exit(__exception, __regs, __flags) \ + do { \ + (void)(__exception); \ + (void)(__regs); \ + (void)(__flags); \ + } while (0) + +#endif /* !CONFIG_IRQ_PIPELINE */ + +#else /* CONFIG_MMU */ +unsigned long dovetail_fault_entry(int exception, struct pt_regs *regs) +{ + return 0; +} + +static inline void dovetail_fault_exit(int exception, struct pt_regs *regs, + unsigned long combo) +{ } +#endif /* !CONFIG_MMU */ + +#endif diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 49f5d628c4c9a91a3e879af0d541fd76665d78fe..b6b766652b753ef860d16b153685b0d3b582bffa 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -24,6 +24,7 @@ #include <asm/system_info.h> #include <asm/tlbflush.h> #include <asm/dovetail.h> +#include <asm/trap_entry.h> #define CREATE_TRACE_POINTS #include <asm/trace/exceptions.h> @@ -38,61 +39,6 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size) return addr >= TASK_SIZE && ULONG_MAX - addr >= size; } -#ifdef CONFIG_IRQ_PIPELINE -/* - * We need to synchronize the virtual interrupt state with the hard - * interrupt state we received on entry, then turn hardirqs back on to - * allow code which does not require strict serialization to be - * preempted by an out-of-band activity. - */ -static inline -unsigned long fault_entry(int exception, struct pt_regs *regs) -{ - unsigned long flags; - - trace_ARM_trap_entry(exception, regs); - - flags = hard_local_save_flags(); - - /* - * The companion core must demote the current context to - * in-band stage if running oob on entry. - */ - mark_trap_entry(exception, regs); - - if (raw_irqs_disabled_flags(flags)) { - stall_inband(); - trace_hardirqs_off(); - } - - hard_local_irq_enable(); - - return flags; -} - -static inline -void fault_exit(int exception, struct pt_regs *regs, - unsigned long flags) -{ - WARN_ON_ONCE(irq_pipeline_debug() && hard_irqs_disabled()); - - /* - * We expect kentry_exit_pipelined() to clear the stall bit if - * kentry_enter_pipelined() observed it that way. - */ - mark_trap_exit(exception, regs); - trace_ARM_trap_exit(exception, regs); - hard_local_irq_restore(flags); -} - -#else /* !CONFIG_IRQ_PIPELINE */ - -#define fault_entry(__exception, __regs) ({ 0; }) -#define fault_exit(__exception, __regs, __flags) \ - do { (void)(__flags); } while (0) - -#endif /* !CONFIG_IRQ_PIPELINE */ - /* * This is useful to dump out the page tables associated with * 'addr' in mm 'mm'. @@ -165,15 +111,6 @@ void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr) pr_cont("\n"); } #else /* CONFIG_MMU */ -unsigned long fault_entry(int exception, struct pt_regs *regs) -{ - return 0; -} - -static inline void fault_exit(int exception, struct pt_regs *regs, - unsigned long combo) -{ } - void show_pte(const char *lvl, struct mm_struct *mm, unsigned long addr) { } #endif /* CONFIG_MMU */ @@ -278,9 +215,9 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs) * have no context to handle this fault with. */ if (user_mode(regs)) { - irqflags = fault_entry(ARM_TRAP_ACCESS, regs); + irqflags = dovetail_fault_entry(ARM_TRAP_ACCESS, regs); __do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs); - fault_exit(ARM_TRAP_ACCESS, regs, irqflags); + dovetail_fault_exit(ARM_TRAP_ACCESS, regs, irqflags); } else /* * irq_pipeline: kernel faults are either quickly @@ -391,9 +328,9 @@ do_kernel_address_page_fault(struct mm_struct *mm, unsigned long addr, * Note that __do_user_fault() will enable interrupts. */ harden_branch_predictor(); - irqflags = fault_entry(ARM_TRAP_ACCESS, regs); + irqflags = dovetail_fault_entry(ARM_TRAP_ACCESS, regs); __do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs); - fault_exit(ARM_TRAP_ACCESS, regs, irqflags); + dovetail_fault_exit(ARM_TRAP_ACCESS, regs, irqflags); } else { /* * Fault from kernel mode. Enable interrupts if they were @@ -433,7 +370,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (addr >= TASK_SIZE) return do_kernel_address_page_fault(mm, addr, fsr, regs); - irqflags = fault_entry(ARM_TRAP_ACCESS, regs); + irqflags = dovetail_fault_entry(ARM_TRAP_ACCESS, regs); /* Enable interrupts if they were enabled in the parent context. */ if (interrupts_enabled(regs)) @@ -595,7 +532,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) no_context: __do_kernel_fault(mm, addr, fsr, regs); out: - fault_exit(ARM_TRAP_ACCESS, regs, irqflags); + dovetail_fault_exit(ARM_TRAP_ACCESS, regs, irqflags); return 0; } @@ -671,9 +608,9 @@ do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (addr >= TASK_SIZE && user_mode(regs)) harden_branch_predictor(); - irqflags = fault_entry(ARM_TRAP_SECTION, regs); + irqflags = dovetail_fault_entry(ARM_TRAP_SECTION, regs); do_bad_area(addr, fsr, regs); - fault_exit(ARM_TRAP_SECTION, regs, irqflags); + dovetail_fault_exit(ARM_TRAP_SECTION, regs, irqflags); return 0; } #endif /* CONFIG_ARM_LPAE */ @@ -726,7 +663,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) return; - irqflags = fault_entry(ARM_TRAP_DABT, regs); + irqflags = dovetail_fault_entry(ARM_TRAP_DABT, regs); pr_alert("8<--- cut here ---\n"); pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); @@ -734,7 +671,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, fsr, 0); - fault_exit(ARM_TRAP_DABT, regs, irqflags); + dovetail_fault_exit(ARM_TRAP_DABT, regs, irqflags); } void __init @@ -759,14 +696,14 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) return; - irqflags = fault_entry(ARM_TRAP_PABT, regs); + irqflags = dovetail_fault_entry(ARM_TRAP_PABT, regs); pr_alert("8<--- cut here ---\n"); pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", inf->name, ifsr, addr); arm_notify_die("", regs, inf->sig, inf->code, (void __user *)addr, ifsr, 0); - fault_exit(ARM_TRAP_PABT, regs, irqflags); + dovetail_fault_exit(ARM_TRAP_PABT, regs, irqflags); } /* -- 2.55.0