linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Alexandre Ghiti <alex@ghiti.fr>
To: Yunhui Cui <cuiyunhui@bytedance.com>,
	yury.norov@gmail.com, linux@rasmusvillemoes.dk,
	paul.walmsley@sifive.com, palmer@dabbelt.com,
	aou@eecs.berkeley.edu, linux-riscv@lists.infradead.org,
	linux-kernel@vger.kernel.org, dennis@kernel.org, tj@kernel.org,
	cl@gentwo.org, linux-mm@kvack.org
Subject: Re: [PATCH RFC 2/2] riscv: introduce percpu.h into include/asm
Date: Thu, 17 Jul 2025 15:05:44 +0200	[thread overview]
Message-ID: <b0583098-204a-4ad1-b173-4bd00a358d61@ghiti.fr> (raw)
In-Reply-To: <c9ba6163-6703-441b-915c-d784044f862f@ghiti.fr>

On 7/17/25 15:04, Alexandre Ghiti wrote:
> Hi Yunhui,
>
> On 6/18/25 05:43, Yunhui Cui wrote:
>> Current percpu operations rely on generic implementations, where
>> raw_local_irq_save() introduces substantial overhead. Optimization
>> is achieved through atomic operations and preemption disabling.
>>
>> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
>> ---
>>   arch/riscv/include/asm/percpu.h | 138 ++++++++++++++++++++++++++++++++
>>   1 file changed, 138 insertions(+)
>>   create mode 100644 arch/riscv/include/asm/percpu.h
>>
>> diff --git a/arch/riscv/include/asm/percpu.h 
>> b/arch/riscv/include/asm/percpu.h
>> new file mode 100644
>> index 0000000000000..423c0d01f874c
>> --- /dev/null
>> +++ b/arch/riscv/include/asm/percpu.h
>> @@ -0,0 +1,138 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +
>> +#ifndef __ASM_PERCPU_H
>> +#define __ASM_PERCPU_H
>> +
>> +#include <linux/preempt.h>
>> +
>> +#define PERCPU_RW_OPS(sz)                        \
>> +static inline unsigned long __percpu_read_##sz(void *ptr)        \
>> +{                                    \
>> +    return READ_ONCE(*(u##sz *)ptr);                \
>> +}                                    \
>> +                                    \
>> +static inline void __percpu_write_##sz(void *ptr, unsigned long 
>> val)    \
>> +{                                    \
>> +    WRITE_ONCE(*(u##sz *)ptr, (u##sz)val);                \
>> +}
>> +
>> +#define __PERCPU_AMO_OP_CASE(sfx, name, sz, amo_insn)            \
>> +static inline void                            \
>> +__percpu_##name##_amo_case_##sz(void *ptr, unsigned long val)        \
>> +{                                    \
>> +    asm volatile (                            \
>> +    "amo" #amo_insn #sfx " zero, %[val], %[ptr]"            \
>> +    : [ptr] "+A" (*(u##sz *)ptr)                    \
>> +    : [val] "r" ((u##sz)(val))                    \
>> +    : "memory");                            \
>> +}
>> +
>> +#define __PERCPU_AMO_RET_OP_CASE(sfx, name, sz, amo_insn)        \
>> +static inline u##sz                            \
>> +__percpu_##name##_return_amo_case_##sz(void *ptr, unsigned long 
>> val)    \
>> +{                                    \
>> +    register u##sz ret;                        \
>> +                                    \
>> +    asm volatile (                            \
>> +    "amo" #amo_insn #sfx " %[ret], %[val], %[ptr]"            \
>> +    : [ptr] "+A" (*(u##sz *)ptr), [ret] "=r" (ret)            \
>> +    : [val] "r" ((u##sz)(val))                    \
>> +    : "memory");                            \
>> +                                    \
>> +    return ret + val;                        \
>> +}
>> +
>> +#define PERCPU_OP(name, amo_insn)                    \
>> +    __PERCPU_AMO_OP_CASE(.b, name, 8, amo_insn)            \
>> +    __PERCPU_AMO_OP_CASE(.h, name, 16, amo_insn)            \
>> +    __PERCPU_AMO_OP_CASE(.w, name, 32, amo_insn)            \
>> +    __PERCPU_AMO_OP_CASE(.d, name, 64, amo_insn)            \
>> +
>> +#define PERCPU_RET_OP(name, amo_insn)                    \
>> +    __PERCPU_AMO_RET_OP_CASE(.b, name, 8, amo_insn) \
>> +    __PERCPU_AMO_RET_OP_CASE(.h, name, 16, amo_insn)        \
>> +    __PERCPU_AMO_RET_OP_CASE(.w, name, 32, amo_insn)        \
>> +    __PERCPU_AMO_RET_OP_CASE(.d, name, 64, amo_insn)
>> +
>> +PERCPU_RW_OPS(8)
>> +PERCPU_RW_OPS(16)
>> +PERCPU_RW_OPS(32)
>> +PERCPU_RW_OPS(64)
>> +
>> +PERCPU_OP(add, add)
>> +PERCPU_OP(andnot, and)
>> +PERCPU_OP(or, or)
>> +PERCPU_RET_OP(add, add)
>> +
>> +#undef PERCPU_RW_OPS
>> +#undef __PERCPU_AMO_OP_CASE
>> +#undef __PERCPU_AMO_RET_OP_CASE
>> +#undef PERCPU_OP
>> +#undef PERCPU_RET_OP
>> +
>> +#define _pcp_protect(op, pcp, ...)                    \
>> +({                                    \
>> +    preempt_disable_notrace();                    \
>> +    op(raw_cpu_ptr(&(pcp)), __VA_ARGS__);                \
>> +    preempt_enable_notrace();                    \
>> +})
>> +
>> +#define _pcp_protect_return(op, pcp, args...)                \
>> +({                                    \
>> +    typeof(pcp) __retval;                        \
>> +    preempt_disable_notrace();                    \
>> +    __retval = (typeof(pcp))op(raw_cpu_ptr(&(pcp)), ##args);    \
>> +    preempt_enable_notrace();                    \
>> +    __retval;                            \
>> +})
>> +
>> +#define this_cpu_read_1(pcp) _pcp_protect_return(__percpu_read_8, pcp)
>> +#define this_cpu_read_2(pcp) _pcp_protect_return(__percpu_read_16, pcp)
>> +#define this_cpu_read_4(pcp) _pcp_protect_return(__percpu_read_32, pcp)
>> +#define this_cpu_read_8(pcp) _pcp_protect_return(__percpu_read_64, pcp)
>> +
>> +#define this_cpu_write_1(pcp, val) _pcp_protect(__percpu_write_8, 
>> pcp, (unsigned long)val)
>> +#define this_cpu_write_2(pcp, val) _pcp_protect(__percpu_write_16, 
>> pcp, (unsigned long)val)
>> +#define this_cpu_write_4(pcp, val) _pcp_protect(__percpu_write_32, 
>> pcp, (unsigned long)val)
>> +#define this_cpu_write_8(pcp, val) _pcp_protect(__percpu_write_64, 
>> pcp, (unsigned long)val)
>> +
>> +#define this_cpu_add_1(pcp, val) 
>> _pcp_protect(__percpu_add_amo_case_8, pcp, val)
>> +#define this_cpu_add_2(pcp, val) 
>> _pcp_protect(__percpu_add_amo_case_16, pcp, val)
>> +#define this_cpu_add_4(pcp, val) 
>> _pcp_protect(__percpu_add_amo_case_32, pcp, val)
>> +#define this_cpu_add_8(pcp, val) 
>> _pcp_protect(__percpu_add_amo_case_64, pcp, val)
>> +
>> +#define this_cpu_add_return_1(pcp, val)        \
>> +_pcp_protect_return(__percpu_add_return_amo_case_8, pcp, val)
>> +
>> +#define this_cpu_add_return_2(pcp, val)        \
>> +_pcp_protect_return(__percpu_add_return_amo_case_16, pcp, val)
>> +
>> +#define this_cpu_add_return_4(pcp, val)        \
>> +_pcp_protect_return(__percpu_add_return_amo_case_32, pcp, val)
>> +
>> +#define this_cpu_add_return_8(pcp, val)        \
>> +_pcp_protect_return(__percpu_add_return_amo_case_64, pcp, val)
>> +
>> +#define this_cpu_and_1(pcp, val) 
>> _pcp_protect(__percpu_andnot_amo_case_8, pcp, ~val)
>> +#define this_cpu_and_2(pcp, val) 
>> _pcp_protect(__percpu_andnot_amo_case_16, pcp, ~val)
>> +#define this_cpu_and_4(pcp, val) 
>> _pcp_protect(__percpu_andnot_amo_case_32, pcp, ~val)
>> +#define this_cpu_and_8(pcp, val) 
>> _pcp_protect(__percpu_andnot_amo_case_64, pcp, ~val)
>
>
> Why do we define __percpu_andnot based on amoand, and use 
> __percpu_andnot with ~val here? Can't we just define __percpu_and?
>
>
>> +
>> +#define this_cpu_or_1(pcp, val) _pcp_protect(__percpu_or_amo_case_8, 
>> pcp, val)
>> +#define this_cpu_or_2(pcp, val) 
>> _pcp_protect(__percpu_or_amo_case_16, pcp, val)
>> +#define this_cpu_or_4(pcp, val) 
>> _pcp_protect(__percpu_or_amo_case_32, pcp, val)
>> +#define this_cpu_or_8(pcp, val) 
>> _pcp_protect(__percpu_or_amo_case_64, pcp, val)
>> +
>> +#define this_cpu_xchg_1(pcp, val) _pcp_protect_return(xchg_relaxed, 
>> pcp, val)
>> +#define this_cpu_xchg_2(pcp, val) _pcp_protect_return(xchg_relaxed, 
>> pcp, val)
>> +#define this_cpu_xchg_4(pcp, val) _pcp_protect_return(xchg_relaxed, 
>> pcp, val)
>> +#define this_cpu_xchg_8(pcp, val) _pcp_protect_return(xchg_relaxed, 
>> pcp, val)
>> +
>> +#define this_cpu_cmpxchg_1(pcp, o, n) 
>> _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
>> +#define this_cpu_cmpxchg_2(pcp, o, n) 
>> _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
>> +#define this_cpu_cmpxchg_4(pcp, o, n) 
>> _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
>> +#define this_cpu_cmpxchg_8(pcp, o, n) 
>> _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
>> +
>> +#include <asm-generic/percpu.h>
>> +
>> +#endif /* __ASM_PERCPU_H */
>
>
> It all looks good to me, just one thing, can you also implement 
> this_cpu_cmpxchg64/128()?
>

One last thing sorry, can you add a cover letter too?

Thanks!

Alex


> And since this is almost a copy/paste from arm64, either mention it at 
> the top of the file or (better) merge both implementations somewhere 
> to avoid redefining existing code :) But up to you.
>
> Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
>
> Thanks,
>
> Alex
>
>
>


  reply	other threads:[~2025-07-17 13:05 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-18  3:43 [PATCH RFC 1/2] riscv: remove irqflags.h inclusion in asm/bitops.h Yunhui Cui
2025-06-18  3:43 ` [PATCH RFC 2/2] riscv: introduce percpu.h into include/asm Yunhui Cui
2025-07-17 13:04   ` Alexandre Ghiti
2025-07-17 13:05     ` Alexandre Ghiti [this message]
2025-07-18  6:40       ` [External] " yunhui cui
2025-07-18 14:22         ` Alexandre Ghiti
2025-07-18 14:33           ` yunhui cui
2025-08-07 14:54             ` Alexandre Ghiti
2025-08-19 12:45               ` yunhui cui
2025-06-21 14:33 ` [PATCH RFC 1/2] riscv: remove irqflags.h inclusion in asm/bitops.h Yury Norov

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=b0583098-204a-4ad1-b173-4bd00a358d61@ghiti.fr \
    --to=alex@ghiti.fr \
    --cc=aou@eecs.berkeley.edu \
    --cc=cl@gentwo.org \
    --cc=cuiyunhui@bytedance.com \
    --cc=dennis@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=tj@kernel.org \
    --cc=yury.norov@gmail.com \
    /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