From: Shrikanth Hegde <sshegde@linux.ibm.com>
To: maddy@linux.ibm.com, linuxppc-dev@lists.ozlabs.org
Cc: sshegde@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com,
christophe.leroy@csgroup.eu, linux-kernel@vger.kernel.org,
ritesh.list@gmail.com, peterz@infradead.org, boqun@kernel.org,
will@kernel.org, jhladky@redhat.com, paulmck@kernel.org
Subject: [RFC 1/3] powerpc64: move preempt count to paca
Date: Fri, 2 Oct 2026 22:16:17 +0530 [thread overview]
Message-ID: <20261002164619.1455143-2-sshegde@linux.ibm.com> (raw)
In-Reply-To: <20261002164619.1455143-1-sshegde@linux.ibm.com>
PowerPC uses generic implementation of preempt as of now.
That means preempt count in embedded in thread_info.
preempt_count = current_thread_info->preempt_count.
Current is first obtained from PACA. So this involves multiple
cachelines/pointers access. But preempt count is a per cpu storage
attribute indicating whether preemption can happen on
this CPU. per cpu storage has been used in other archs such
x86 already.
Powerpc64 architecture using PACA instead seems to be a more natural
fit. r13 is local paca pointer and it is always cacheline hot.
So getting preempt_count from paca means avoiding two deferrences.
It is worth doing that since preempt count is very high frequency
operation involved in various kernel primitives.
Given that after 7.0 powerpc has only preemptible kernels, makes it
even more relevant.
No functional change is intended.
Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
---
arch/powerpc/include/asm/paca.h | 1 +
arch/powerpc/include/asm/preempt.h | 103 +++++++++++++++++++++++++
arch/powerpc/include/asm/thread_info.h | 14 +++-
arch/powerpc/kernel/paca.c | 1 +
arch/powerpc/kexec/core_64.c | 2 +-
5 files changed, 117 insertions(+), 4 deletions(-)
create mode 100644 arch/powerpc/include/asm/preempt.h
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 1d58da946739..0aa729c2faf5 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -164,6 +164,7 @@ struct paca_struct {
u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */
u64 saved_msr; /* MSR saved here by enter_rtas */
u64 exit_save_r1; /* Syscall/interrupt R1 save */
+ int preempt_count;
#ifdef CONFIG_PPC_BOOK3E_64
u16 trap_save; /* Used when bad stack is encountered */
#endif
diff --git a/arch/powerpc/include/asm/preempt.h b/arch/powerpc/include/asm/preempt.h
new file mode 100644
index 000000000000..e2785d5a13e0
--- /dev/null
+++ b/arch/powerpc/include/asm/preempt.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * PPC64 stores preempt count in PACA.
+ * PPC32 stores preempt count in thread_info.
+ */
+
+#ifndef __ASM_POWERPC_PREEMPT_H
+#define __ASM_POWERPC_PREEMPT_H
+
+#ifdef CONFIG_PPC64
+#include <linux/thread_info.h>
+#include <asm/paca.h>
+
+#define PREEMPT_ENABLED (0)
+
+static __always_inline int preempt_count(void)
+{
+ return READ_ONCE(local_paca->preempt_count);
+}
+
+static __always_inline void preempt_count_set(int pc)
+{
+ WRITE_ONCE(local_paca->preempt_count, pc);
+}
+
+#define init_task_preempt_count(p) do { } while (0)
+#define init_idle_preempt_count(p, cpu) do { } while (0)
+
+static inline void set_preempt_need_resched(void)
+{
+}
+
+static inline void clear_preempt_need_resched(void)
+{
+}
+
+static inline bool test_preempt_need_resched(void)
+{
+ return false;
+}
+
+static __always_inline void __preempt_count_add(int val)
+{
+ int pc = READ_ONCE(local_paca->preempt_count);
+
+ pc += val;
+ WRITE_ONCE(local_paca->preempt_count, pc);
+}
+
+static __always_inline void __preempt_count_sub(int val)
+{
+ int pc = READ_ONCE(local_paca->preempt_count);
+
+ pc -= val;
+ WRITE_ONCE(local_paca->preempt_count, pc);
+}
+
+static inline int __preempt_count_add_return(int val)
+{
+ int pc = READ_ONCE(local_paca->preempt_count);
+
+ pc += val;
+ WRITE_ONCE(local_paca->preempt_count, pc);
+ return pc;
+}
+
+static inline int __preempt_count_sub_return(int val)
+{
+ int pc = READ_ONCE(local_paca->preempt_count);
+
+ pc -= val;
+ WRITE_ONCE(local_paca->preempt_count, pc);
+ return pc;
+}
+
+static inline bool __preempt_count_dec_and_test(void)
+{
+ int pc = READ_ONCE(local_paca->preempt_count);
+
+ WRITE_ONCE(local_paca->preempt_count, --pc);
+ return !pc && tif_need_resched();
+}
+
+static inline bool should_resched(int preempt_offset)
+{
+ int pc = READ_ONCE(local_paca->preempt_count);
+
+ return unlikely(pc == preempt_offset && tif_need_resched());
+}
+
+#ifdef CONFIG_PREEMPTION
+void preempt_schedule(void);
+void preempt_schedule_notrace(void);
+
+#define __preempt_schedule() preempt_schedule()
+#define __preempt_schedule_notrace() preempt_schedule_notrace()
+#endif /* CONFIG_PREEMPTION */
+
+#else /* !CONFIG_PPC64 */
+#include <asm-generic/preempt.h>
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 1e069a2e7ce8..89fd63442f7a 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -52,8 +52,9 @@
* low level task data.
*/
struct thread_info {
- int preempt_count; /* 0 => preemptable,
- <0 => BUG */
+#ifndef CONFIG_PPC64
+ int preempt_count;
+#endif
#ifdef CONFIG_SMP
unsigned int cpu;
#endif
@@ -74,12 +75,19 @@ struct thread_info {
unsigned long flags ____cacheline_aligned_in_smp;
};
+#ifdef CONFIG_PPC64
+#define INIT_THREAD_INFO_PREEMPT_COUNT
+#else
+#define INIT_THREAD_INFO_PREEMPT_COUNT \
+ .preempt_count = INIT_PREEMPT_COUNT,
+#endif
+
/*
* macros/functions for gaining access to the thread information structure
*/
#define INIT_THREAD_INFO(tsk) \
{ \
- .preempt_count = INIT_PREEMPT_COUNT, \
+ INIT_THREAD_INFO_PREEMPT_COUNT \
.flags = 0, \
}
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 7502066c3c53..f19d057c37b3 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -200,6 +200,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
new_paca->hw_cpu_id = 0xffff;
new_paca->kexec_state = KEXEC_STATE_NONE;
new_paca->__current = &init_task;
+ new_paca->preempt_count = PREEMPT_DISABLED;
new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
#ifdef CONFIG_PPC_64S_HASH_MMU
new_paca->slb_shadow_ptr = NULL;
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index 58c13a59b93b..f3954695e0b5 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -352,7 +352,7 @@ void default_machine_kexec(struct kimage *image)
* XXX: the task struct will likely be invalid once we do the copy!
*/
current_thread_info()->flags = 0;
- current_thread_info()->preempt_count = HARDIRQ_OFFSET;
+ WRITE_ONCE(local_paca->preempt_count, HARDIRQ_OFFSET);
/* We need a static PACA, too; copy this CPU's PACA over and switch to
* it. Also poison per_cpu_offset and NULL lppaca to catch anyone using
--
2.52.0
next prev parent reply other threads:[~2026-10-02 16:47 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-02 16:46 [RFC 0/3] powerpc64: Preempt count optimizations Shrikanth Hegde
2026-10-02 16:46 ` Shrikanth Hegde [this message]
2026-10-02 16:46 ` [RFC 2/3] powerpc64/preempt: Add need_resched bit inside preempt_count Shrikanth Hegde
2026-10-02 16:46 ` [RFC 3/3] powerpc64/Kconfig: Enable HAS_SEPARATE_PREEMPT_RESCHED_BITS Shrikanth Hegde
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261002164619.1455143-2-sshegde@linux.ibm.com \
--to=sshegde@linux.ibm.com \
--cc=boqun@kernel.org \
--cc=christophe.leroy@csgroup.eu \
--cc=jhladky@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maddy@linux.ibm.com \
--cc=mpe@ellerman.id.au \
--cc=npiggin@gmail.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=ritesh.list@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®