BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Yunhui Cui" <cuiyunhui@bytedance.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH v4 2/3] riscv: introduce percpu.h into include/asm
Date: Tue, 05 May 2026 07:26:34 +0000	[thread overview]
Message-ID: <20260505072635.27923C2BCB4@smtp.kernel.org> (raw)
In-Reply-To: <20260505062026.91724-3-cuiyunhui@bytedance.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] The 8-bit and 16-bit `this_cpu_add` fallback logic fails to mask arithmetic overflow, corrupting adjacent percpu variables.
- [High] The 32-bit and 64-bit `this_cpu_and` macros incorrectly perform an AND-NOT operation instead of a bitwise AND.
- [High] Missing early-clobber modifiers (`=&r`) on output operands in `PERCPU_8_16_RET_OP` allow destructive register overlapping.
--

commit f4a490dc0b24e17cbd874e03d02e506d017e61b6
Author: Yunhui Cui <cuiyunhui@bytedance.com>

riscv: introduce percpu.h into include/asm

This commit introduces a RISC-V percpu header to implement direct this_cpu
operations. It provides macros for 8, 16, 32, and 64-bit read, write, and
atomic memory operations.

> diff --git a/arch/riscv/include/asm/percpu.h b/arch/riscv/include/asm/percpu.h
> new file mode 100644
> index 0000000000000..3b26fe45e70f4
> --- /dev/null
> +++ b/arch/riscv/include/asm/percpu.h

[ ... ]

> +#define PERCPU_8_16_OP(name, amo_insn, sz, sfx, val_type, new_val_expr, asm_op)			\
> +static inline void __percpu_##name##_amo_case_##sz(void *ptr, unsigned long val)		\
> +{												\
> +	if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) &&						\
> +		riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA)) {				\
> +		asm volatile ("amo" #amo_insn #sfx " zero, %[val], %[ptr]"			\
> +			: [ptr] "+A"(*(val_type *)ptr)						\
> +			: [val] "r"((val_type)((new_val_expr) & PERCPU_8_16_GET_MASK(sz)))	\
> +			: "memory");								\
> +	} else {										\
> +		u32 *ptr32 = PERCPU_8_16_GET_PTR32(ptr);					\
> +		const unsigned long shift = PERCPU_8_16_GET_SHIFT(ptr);				\
> +		const u32 mask = PERCPU_8_16_GET_MASK(sz) << shift;				\
> +		const val_type val_trunc = (val_type)((new_val_expr)				\
> +					   & PERCPU_8_16_GET_MASK(sz));				\
> +		u32 retx, rc;									\
> +		val_type new_val_type;								\
> +												\
> +		asm volatile (									\
> +			"0: lr.w %0, %2\n"							\
> +			"and %3, %0, %4\n"							\
> +			"srl %3, %3, %5\n"							\
> +			#asm_op " %3, %3, %6\n"							\

Is it possible for an 8-bit or 16-bit addition to overflow here? If there are
carry bits outside the subword boundary, they aren't masked out before the
result is shifted left.

Could this silent overflow spill into and corrupt adjacent per-CPU variables?

> +			"sll %3, %3, %5\n"							\
> +			"and %1, %0, %7\n"							\
> +			"or %1, %1, %3\n"							\
> +			"sc.w %1, %1, %2\n"							\
> +			"bnez %1, 0b\n"								\
> +			: "=&r"(retx), "=&r"(rc), "+A"(*ptr32), "=&r"(new_val_type)		\
> +			: "r"(mask), "r"(shift), "r"(val_trunc), "r"(~mask)			\
> +			: "memory");								\
> +		}										\
> +}

[ ... ]

> +#define PERCPU_8_16_RET_OP(name, amo_insn, sz, sfx, val_type, new_val_expr)			\
> +static inline val_type __percpu_##name##_return_amo_case_##sz(void *ptr, unsigned long val)	\
> +{												\
> +	if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) &&						\
> +		riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA)) {				\

[ ... ]

> +	} else {										\
> +		u32 *ptr32 = PERCPU_8_16_GET_PTR32(ptr);					\
> +		const unsigned long shift = PERCPU_8_16_GET_SHIFT(ptr);				\
> +		const u32 mask = (PERCPU_8_16_GET_MASK(sz) << shift);				\
> +		const u32 inv_mask = ~mask;							\
> +		const val_type val_trunc = (val_type)((new_val_expr)				\
> +					   & PERCPU_8_16_GET_MASK(sz));				\
> +		u32 old, new, tmp;								\
> +												\
> +		asm volatile (									\
> +			"0: lr.w %0, %3\n"							\
> +			"and %1, %0, %4\n"							\
> +			"srl %1, %1, %5\n"							\
> +			"add %1, %1, %6\n"							\
> +			"and %1, %1, %7\n"							\
> +			"sll %1, %1, %5\n"							\
> +			"and %2, %0, %8\n"							\
> +			"or %2, %2, %1\n"							\
> +			"sc.w %2, %2, %3\n"							\
> +			"bnez %2, 0b\n"								\
> +			: "=r"(old), "=r"(tmp), "=&r"(new), "+A"(*ptr32)			\

Should the old and tmp output operands use the early-clobber modifier (=&r)?

Since they are written to early in the instruction sequence before inputs
like mask (%4), shift (%5), or val_trunc (%6) are consumed, could the compiler
allocate them to the same physical registers, leading to clobbered inputs?

> +			: "r"(mask), "r"(shift), "r"(val_trunc), "r"(PERCPU_8_16_GET_MASK(sz)), \
> +			"r"(inv_mask)								\
> +			: "memory");								\
> +		return (val_type)(tmp >> shift);						\
> +	}											\
> +}

[ ... ]

> +#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))
> +
> +#ifdef CONFIG_64BIT
> +#define this_cpu_and_8(pcp, val)	_pcp_protect(__percpu_andnot_amo_case_64, pcp, ~(val))
> +#endif

Since the underlying __percpu_andnot_amo_case_32 and 64 macros directly use the
amoand instruction on the value passed, does negating val here with ~(val)
cause the hardware to perform an AND-NOT operation (pcp &= ~val) instead of a
bitwise AND (pcp &= val)?

> +
> +#define this_cpu_or_1(pcp, val)	_pcp_protect(__percpu_or_amo_case_8, pcp, val)

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260505062026.91724-1-cuiyunhui@bytedance.com?part=2

  parent reply	other threads:[~2026-05-05  7:26 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-05  6:20 [PATCH v4 0/3] riscv: improve percpu helpers and PIO mapping Yunhui Cui
2026-05-05  6:20 ` [PATCH v4 1/3] riscv: io: avoid null-pointer arithmetic in PIO helpers Yunhui Cui
2026-05-05  6:33   ` Arnd Bergmann
2026-05-05  7:20   ` bot+bpf-ci
2026-05-05  6:20 ` [PATCH v4 2/3] riscv: introduce percpu.h into include/asm Yunhui Cui
2026-05-05  7:05   ` bot+bpf-ci
2026-05-05  7:26   ` sashiko-bot [this message]
2026-05-05  6:20 ` [PATCH v4 3/3] riscv: store percpu offset into thread_info Yunhui Cui
2026-05-05  7:20   ` bot+bpf-ci
2026-05-05  8:11   ` sashiko-bot

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=20260505072635.27923C2BCB4@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=cuiyunhui@bytedance.com \
    --cc=sashiko@lists.linux.dev \
    /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