Re: [PATCH v2 14/20] arm64: percpu: Implement preemptible read/write ops

David Laight <[email protected]>
Newsgroups org.kernel.vger.stable,org.infradead.lists.linux-arm-kernel
Message-ID <20260805130848.6d533293@pumpkin>
On Wed, 5 Aug 2026 10:24:04 +0100
Ryan Roberts <[email protected]> wrote:

> On 04/08/2026 18:04, Mark Rutland wrote:
> > Use the PCPU GPR infrastructure to implement preemptible this_cpu_read()
> > and this_cpu_write().
> > 
> > This change means that this_cpu_read() will always use a plain LDR, even
> > in LTO configurations where READ_ONCE() will use LDA[P]R. Using plain
> > LDR is preferable, given that the rationale for using LDA[P]R in
> > READ_ONCE() was to retain address dependencies against values written by
> > other CPUs, which isn't expected usage for this_cpu_read(). Using plain
> > LDR will enforce fewer ordering constraints.
> > 
> > Test case:
> > 
> > | void outline_this_cpu_write_u64(u64 __percpu *p, u64 v)
> > | {
> > | 	this_cpu_write(*p, v);
> > | }
> > 
> > Generated code before this patch (v7.2-rc4):
> > 
> > | <outline_this_cpu_write_u64>:
> > |        paciasp
> > |        stp     x29, x30, [sp, #-16]!
> > |        mrs     x2, sp_el0
> > |        mov     x29, sp
> > |        ldr     w3, [x2, #8]
> > |        add     w3, w3, #0x1
> > |        str     w3, [x2, #8]
> > |        mrs     x3, tpidr_el1
> > |        str     x1, [x0, x3]
> > |        ldr     x0, [x2, #8]
> > |        sub     x0, x0, #0x1
> > |        str     w0, [x2, #8]
> > |        cbz     x0, 1f
> > |        ldr     x0, [x2, #8]
> > |        cbnz    x0, 2f
> > | 1:     bl      preempt_schedule_notrace
> > | 2:     ldp     x29, x30, [sp], #16
> > |        autiasp
> > |        ret
> > 
> > Generated code after this patch:
> > 
> > | <outline_this_cpu_write_u64>:
> > |        mrs     x2, sp_el0
> > |        mov     w3, #0x7c60
> > |        strh    w3, [x2, #20]
> > |        mrs     x3, tpidr_el1
> > |        str     x1, [x0, x3]
> > |        strh    wzr, [x2, #20]
> > |        ret
> > 
> > Signed-off-by: Mark Rutland <[email protected]>
> > Cc: Ada Couprie Diaz <[email protected]>
> > Cc: Ard Biesheuvel <[email protected]>
> > Cc: Catalin Marinas <[email protected]>
> > Cc: James Morse <[email protected]>
> > Cc: Jinjie Ruan <[email protected]>
> > Cc: Marc Zyngier <[email protected]>
> > Cc: Peter Zijlstra <[email protected]>
> > Cc: Vladimir Murzin <[email protected]>
> > Cc: Will Deacon <[email protected]>
> > Cc: Yang Shi <[email protected]>
> > ---  
> FYI I'm seeing build warnings caused by this patch (with ftrace enabled - based 
> on the warnings, I'm guessing that's the key bit), using:
> 
> aarch64-linux-gnu-gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
> 
> I haven't investigated the cause.

It'll be the earlier patch that changed the casts.
The code is doing:
		this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
			       FTRACE_PID_IGNORE);
where the constant is -1.
I suspect the warning messages are coming from the switch case that are
optimised away because the size if wrong (ftrace_ignore_pid seems to
be a pid number to ignore and is 32 bits.

That does seem a long-winded way to access per-cpu data.
To make any sense the code must be running with preemption disabled and
be caching info in per-cpu memory.
In which case it can just access it directly.
OTOH it could save the 'global' address of the per-cpu data and then access
it using the pointer so that access would be a normal one.

	David

> 
> Thanks,
> Ryan
> 
> ---8<---
> In file included from linux/arch/arm64/include/asm/spectre.h:17,                                                                                                                                                                       
>                  from linux/arch/arm64/include/asm/processor.h:47,
>                  from linux/include/linux/sched.h:13,
>                  from linux/include/linux/ratelimit.h:6,
>                  from linux/include/linux/dev_printk.h:16,
>                  from linux/include/linux/device.h:15,
>                  from linux/include/linux/node.h:18,
>                  from linux/include/linux/cpu.h:17,
>                  from linux/include/linux/stop_machine.h:5,
>                  from linux/kernel/trace/ftrace.c:17:
> linux/kernel/trace/ftrace.c: In function 'ftrace_filter_pid_sched_switch_probe':
> linux/arch/arm64/include/asm/percpu.h:295:42: warning: conversion from 'long unsigned int' to 'u8' {aka 'unsigned char'} changes value from '18446744073709551615' to '255' [-Woverflow]                                               
>   295 |         _pcp_wrap(__percpu_write_8, pcp, (unsigned long)(val))
>       |                                          ^~~~~~~~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:277:20: note: in definition of macro '_pcp_wrap'
>   277 |         op(&(pcp), __VA_ARGS__);                                        \
>       |                    ^~~~~~~~~~~
> linux/include/linux/percpu-defs.h:369:25: note: in expansion of macro 'this_cpu_write_1'
>   369 |                 case 1: stem##1(variable, __VA_ARGS__);break;           \
>       |                         ^~~~
> linux/include/linux/percpu-defs.h:500:41: note: in expansion of macro '__pcpu_size_call'
>   500 | #define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
>       |                                         ^~~~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c:8628:17: note: in expansion of macro 'this_cpu_write'
>  8628 |                 this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
>       |                 ^~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:297:43: warning: conversion from 'long unsigned int' to 'u16' {aka 'short unsigned int'} changes value from '18446744073709551615' to '65535' [-Woverflow]
>   297 |         _pcp_wrap(__percpu_write_16, pcp, (unsigned long)(val))
>       |                                           ^~~~~~~~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:277:20: note: in definition of macro '_pcp_wrap'
>   277 |         op(&(pcp), __VA_ARGS__);                                        \
>       |                    ^~~~~~~~~~~
> linux/include/linux/percpu-defs.h:370:25: note: in expansion of macro 'this_cpu_write_2'
>   370 |                 case 2: stem##2(variable, __VA_ARGS__);break;           \
>       |                         ^~~~
> linux/include/linux/percpu-defs.h:500:41: note: in expansion of macro '__pcpu_size_call'
>   500 | #define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
>       |                                         ^~~~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c:8628:17: note: in expansion of macro 'this_cpu_write'
>  8628 |                 this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
>       |                 ^~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:299:43: warning: conversion from 'long unsigned int' to 'u32' {aka 'unsigned int'} changes value from '18446744073709551615' to '4294967295' [-Woverflow]
>   299 |         _pcp_wrap(__percpu_write_32, pcp, (unsigned long)(val))
>       |                                           ^~~~~~~~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:277:20: note: in definition of macro '_pcp_wrap'
>   277 |         op(&(pcp), __VA_ARGS__);                                        \
>       |                    ^~~~~~~~~~~
> linux/include/linux/percpu-defs.h:371:25: note: in expansion of macro 'this_cpu_write_4'
>   371 |                 case 4: stem##4(variable, __VA_ARGS__);break;           \
>       |                         ^~~~
> linux/include/linux/percpu-defs.h:500:41: note: in expansion of macro '__pcpu_size_call'
>   500 | #define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
>       |                                         ^~~~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c:8628:17: note: in expansion of macro 'this_cpu_write'
>  8628 |                 this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
>       |                 ^~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c: In function 'ignore_task_cpu':
> linux/arch/arm64/include/asm/percpu.h:295:42: warning: conversion from 'long unsigned int' to 'u8' {aka 'unsigned char'} changes value from '18446744073709551615' to '255' [-Woverflow]
>   295 |         _pcp_wrap(__percpu_write_8, pcp, (unsigned long)(val))
>       |                                          ^~~~~~~~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:277:20: note: in definition of macro '_pcp_wrap'
>   277 |         op(&(pcp), __VA_ARGS__);                                        \
>       |                    ^~~~~~~~~~~
> linux/include/linux/percpu-defs.h:369:25: note: in expansion of macro 'this_cpu_write_1'
>   369 |                 case 1: stem##1(variable, __VA_ARGS__);break;           \
>       |                         ^~~~
> linux/include/linux/percpu-defs.h:500:41: note: in expansion of macro '__pcpu_size_call'
>   500 | #define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
>       |                                         ^~~~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c:8898:17: note: in expansion of macro 'this_cpu_write'
>  8898 |                 this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
>       |                 ^~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:297:43: warning: conversion from 'long unsigned int' to 'u16' {aka 'short unsigned int'} changes value from '18446744073709551615' to '65535' [-Woverflow]
>   297 |         _pcp_wrap(__percpu_write_16, pcp, (unsigned long)(val))
>       |                                           ^~~~~~~~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:277:20: note: in definition of macro '_pcp_wrap'
>   277 |         op(&(pcp), __VA_ARGS__);                                        \
>       |                    ^~~~~~~~~~~
> linux/include/linux/percpu-defs.h:370:25: note: in expansion of macro 'this_cpu_write_2'
>   370 |                 case 2: stem##2(variable, __VA_ARGS__);break;           \
>       |                         ^~~~
> linux/include/linux/percpu-defs.h:500:41: note: in expansion of macro '__pcpu_size_call'
>   500 | #define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
>       |                                         ^~~~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c:8898:17: note: in expansion of macro 'this_cpu_write'
>  8898 |                 this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
>       |                 ^~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:299:43: warning: conversion from 'long unsigned int' to 'u32' {aka 'unsigned int'} changes value from '18446744073709551615' to '4294967295' [-Woverflow]
>   299 |         _pcp_wrap(__percpu_write_32, pcp, (unsigned long)(val))
>       |                                           ^~~~~~~~~~~~~~~~~~~~
> linux/arch/arm64/include/asm/percpu.h:277:20: note: in definition of macro '_pcp_wrap'
>   277 |         op(&(pcp), __VA_ARGS__);                                        \
>       |                    ^~~~~~~~~~~
> linux/include/linux/percpu-defs.h:371:25: note: in expansion of macro 'this_cpu_write_4'
>   371 |                 case 4: stem##4(variable, __VA_ARGS__);break;           \
>       |                         ^~~~
> linux/include/linux/percpu-defs.h:500:41: note: in expansion of macro '__pcpu_size_call'
>   500 | #define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
>       |                                         ^~~~~~~~~~~~~~~~
> linux/kernel/trace/ftrace.c:8898:17: note: in expansion of macro 'this_cpu_write'
>  8898 |                 this_cpu_write(tr->array_buffer.data->ftrace_ignore_pid,
>       |                 ^~~~~~~~~~~~~~
> ---8<---
> 
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.