On 11/2/25 5:23 PM, Mukesh Kumar Chaurasiya wrote:
Adding support for the generic irq entry/exit handling for PowerPC. The
goal is to bring PowerPC in line with other architectures that already
use the common irq entry infrastructure, reducing duplicated code and
making it easier to share future changes in entry/exit paths.
This is slightly tested of ppc64le and ppc32.
The performance benchmarks from perf bench basic syscall are below:
| Metric | W/O Generic Framework | With Generic Framework | Change |
| ---------- | --------------------- | ---------------------- | ------ |
| Total time | 0.939 [sec] | 0.938 [sec] | ~0% |
| usecs/op | 0.093900 | 0.093882 | ~0% |
| ops/sec | 1,06,49,615 | 1,06,51,725 | ~0% |
Thats very close to performance earlier with arch specific handling.
Tests done:
- Build and boot on ppc64le pseries.
- Build and boot on ppc64le powernv8 powernv9 powernv10.
- Build and boot on ppc32.
- Performance benchmark done with perf syscall basic on pseries.
Hi Mukesh.
The context tracking is not correct.
too many warning when booted with nohz_full=<>
Did some fiddling, but no luck still in avoiding the warnings.
Below helps to boot into atleast (less warning in comparison)
diff --git a/arch/powerpc/include/asm/entry-common.h
b/arch/powerpc/include/asm/entry-common.h
index 466cfafc10ad..a66cafc94b5e 100644
--- a/arch/powerpc/include/asm/entry-common.h
+++ b/arch/powerpc/include/asm/entry-common.h
@@ -217,20 +217,11 @@ static inline void arch_interrupt_enter_prepare(struct
pt_regs *regs)
if (user_mode(regs)) {
kuap_lock();
- CT_WARN_ON(ct_state() != CT_STATE_USER);
- user_exit_irqoff();
account_cpu_user_entry();
account_stolen_time();
} else {
kuap_save_and_lock(regs);
- /*
- * CT_WARN_ON comes here via program_check_exception,
- * so avoid recursion.
- */
- if (TRAP(regs) != INTERRUPT_PROGRAM)
- CT_WARN_ON(ct_state() != CT_STATE_KERNEL &&
- ct_state() != CT_STATE_IDLE);
INT_SOFT_MASK_BUG_ON(regs, is_implicit_soft_masked(regs));
INT_SOFT_MASK_BUG_ON(regs, regs_irqs_disabled(regs) &&
search_kernel_restart_table(regs->nip));
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index ce59431f977c..c7cf9a3f1202 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -118,16 +118,18 @@ notrace unsigned long syscall_exit_prepare(unsigned long
r3,
regs->exit_flags |= _TIF_RESTOREALL;
}
-again:
+ local_irq_disable();
+
+ user_exit_irqoff();
syscall_exit_to_user_mode(regs);
- user_enter_irqoff();
- if (!prep_irq_for_enabled_exit(true)) {
- user_exit_irqoff();
- local_irq_enable();
- local_irq_disable();
- goto again;
- }
+again:
+ if (!prep_irq_for_enabled_exit(true)) {
+ local_irq_enable();
+ local_irq_disable();
+ goto again;
+ }
+
/* Restore user access locks last */
kuap_user_restore(regs);
@@ -155,16 +157,15 @@ notrace unsigned long syscall_exit_restart(unsigned long
r3, struct pt_regs *reg
#ifdef CONFIG_PPC_BOOK3S_64
set_kuap(AMR_KUAP_BLOCKED);
#endif
-again:
+ user_exit_irqoff();
syscall_exit_to_user_mode(regs);
- user_enter_irqoff();
- if (!prep_irq_for_enabled_exit(true)) {
- user_exit_irqoff();
- local_irq_enable();
- local_irq_disable();
- goto again;
- }
+again:
+ if (!prep_irq_for_enabled_exit(true)) {
+ local_irq_enable();
+ local_irq_disable();
+ goto again;
+ }
regs->exit_result |= regs->exit_flags;
@@ -178,7 +179,6 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
BUG_ON(regs_is_unrecoverable(regs));
BUG_ON(regs_irqs_disabled(regs));
- CT_WARN_ON(ct_state() == CT_STATE_USER);
/*
* We don't need to restore AMR on the way back to userspace for KUAP.
@@ -188,17 +188,17 @@ notrace unsigned long interrupt_exit_user_prepare(struct
pt_regs *regs)
local_irq_disable();
regs->exit_flags = 0;
-again:
+
+ user_exit_irqoff();
irqentry_exit_to_user_mode(regs);
check_return_regs_valid(regs);
- user_enter_irqoff();
- if (!prep_irq_for_enabled_exit(true)) {
- user_exit_irqoff();
- local_irq_enable();
- local_irq_disable();
- goto again;
- }
+again:
+ if (!prep_irq_for_enabled_exit(true)) {
+ local_irq_enable();
+ local_irq_disable();
+ goto again;
+ }
/* Restore user access locks last */
kuap_user_restore(regs);
@@ -222,20 +222,6 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct
pt_regs *regs)
if (regs_is_unrecoverable(regs))
unrecoverable_exception(regs);
- /*
- * CT_WARN_ON comes here via program_check_exception, so avoid
- * recursion.
- *
- * Skip the assertion on PMIs on 64e to work around a problem caused
- * by NMI PMIs incorrectly taking this interrupt return path, it's
- * possible for this to hit after interrupt exit to user switches
- * context to user. See also the comment in the performance monitor
- * handler in exceptions-64e.S
- */
- if (!IS_ENABLED(CONFIG_PPC_BOOK3E_64) &&
- TRAP(regs) != INTERRUPT_PROGRAM &&
- TRAP(regs) != INTERRUPT_PERFMON)
- CT_WARN_ON(ct_state() == CT_STATE_USER);
kuap = kuap_get_and_assert_locked();
@@ -316,7 +302,6 @@ notrace unsigned long interrupt_exit_user_restart(struct pt_regs *regs)
#endif
trace_hardirqs_off();
- user_exit_irqoff();
account_cpu_user_entry();
BUG_ON(!user_mode(regs));
diff --git a/arch/powerpc/kernel/syscall.c b/arch/powerpc/kernel/syscall.c
index df1c9a8d62bc..e041b187b1b7 100644
--- a/arch/powerpc/kernel/syscall.c
+++ b/arch/powerpc/kernel/syscall.c
@@ -20,6 +20,9 @@ notrace long system_call_exception(struct pt_regs *regs,
unsigned long r0)
syscall_fn f;
add_random_kstack_offset();
+
+ local_irq_disable();
+ user_enter_irqoff();
r0 = syscall_enter_from_user_mode(regs, r0);
if (unlikely(r0 >= NR_syscalls)) {