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

Ryan Roberts <[email protected]>
Newsgroups org.infradead.lists.linux-arm-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
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.

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.