From: Mark Rutland <mark.rutland@arm.com>
To: Heiko Carstens <hca@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>,
Sven Schnelle <svens@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Mete Durlu <meted@linux.ibm.com>,
Peter Zijlstra <peterz@infradead.org>,
Juergen Christ <jchrist@linux.ibm.com>,
Ilya Leoshkevich <iii@linux.ibm.com>,
linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org
Subject: Re: [PATCH v2 12/12] s390/percpu: Rework to simplify percpu_entry() and percpu_exit()
Date: Fri, 18 Sep 2026 11:40:21 +0100 [thread overview]
Message-ID: <aq0VFSS_81QTKjcj@J2N7QTR9R3> (raw)
In-Reply-To: <20260918084842.2333237-13-hca@linux.ibm.com>
On Fri, Sep 18, 2026 at 10:48:42AM +0200, Heiko Carstens wrote:
> The percpu code section functionality uses a rather complex method to
> figure out if the register, which contains the address of the current
> cpu's percpu variable, needs to be adjusted.
>
> If an interrupt happens within a percpu code section (indicated by a
> lowcore field), the instruction at the interrupted location is
> checked. If it is not a specific AG instruction, the register needs to
> be updated. This mechanism needs to take kprobes into account, and
> enforces a specific instruction ordering.
>
> Mark Rutland provided with a different solution for arm64 [1] which
> comes without such limitations, but requires to use one more
> instruction, and two more registers. Given that this simplifies
> percpu_entry() and percpu_exit() it seems to be worth to go that
> route.
>
> Change s390 to implement a similar approach. This requires to encode
> three register numbers into the "percpu_register" field, which is used
> to indicate if a percpu code section is executed.
>
> The used mviy instruction can write only one byte, which allows to
> encode only two register numbers. Use a register pair for the inline
> assemblies, and only encode the even register number of the register
> pair to work around this.
Neat trick!
I have one minor comment below, but this looks good to me regardless.
> -static __always_inline void percpu_exit(struct pt_regs *regs, bool needs_fixup)
> +static __always_inline void percpu_exit(struct pt_regs *regs)
> {
> + unsigned char regval, regpcp, regoff, regptr;
> struct lowcore *lc = get_lowcore();
> - unsigned char reg;
>
> - if (user_mode(regs))
> + if (!regs->percpu_register)
> return;
> - reg = regs->percpu_register;
> - lc->percpu_register = reg;
> - if (likely(!needs_fixup))
> - return;
> - /* Check if process has been migrated to a different CPU. */
> + regval = regs->percpu_register;
> + lc->percpu_register = regval;
> + /* Migrated to a different CPU? */
> if (regs->cpu == lc->cpu_nr)
> return;
> - /* Fixup percpu base register */
> - regs->gprs[reg] -= __per_cpu_offset[regs->cpu];
> - regs->gprs[reg] += lc->percpu_offset;
> + regpcp = FIELD_GET(PCPU_REG_PCP, regval);
> + regoff = FIELD_GET(PCPU_REG_OFF, regval);
> + regptr = regoff + 1;
> + /*
> + * Update register 'regoff' which contains the current CPU's percpu
> + * offset, and recalculate and update current CPU's percpu variable
> + * address contained in register 'regptr'.
> + */
> + regs->gprs[regoff] = lc->percpu_offset;
> + regs->gprs[regptr] = regs->gprs[regpcp] + regs->gprs[regoff];
> }
> +#define PCPU_REG_PCP_SHIFT 0
> +#define PCPU_REG_PCP GENMASK(3, 0)
> +#define PCPU_REG_OFF_SHIFT 4
> +#define PCPU_REG_OFF GENMASK(7, 4)
> +
> #define __PCPU_MVIY(lcreg, imm) \
> ALTERNATIVE(" mviy " lcreg "(%%r0)," imm "\n", \
> " mviy " lcreg "+" LC_ALT_ADDR "(%%r0)," imm "\n", \
> ALT_FEATURE(MFEATURE_LOWCORE))
>
> -#define __PCPU_AG(reg, lcoff) \
> - ALTERNATIVE(" ag " reg ", " lcoff "(%%r0)\n", \
> - " ag " reg ", " lcoff "+" LC_ALT_ADDR "(%%r0)\n", \
> +#define __PCPU_MVIY_REGS(lcreg, regpcp, regoff) \
> + DEFINE_GR_NUM \
> + "_GR_NUM .Lregpcp, " regpcp "\n" \
> + "_GR_NUM .Lregoff, " regoff "\n" \
> + UNDEF_GR_NUM \
> + ".if .Lregpcp == .Lregoff\n" \
> + " .error \"Registers must not be identical\"\n" \
> + ".endif\n" \
> + ".set .Lregval, ((.Lregpcp << " __stringify(PCPU_REG_PCP_SHIFT) ") |" \
> + " (.Lregoff << " __stringify(PCPU_REG_OFF_SHIFT) "))\n" \
> + __PCPU_MVIY(lcreg, ".Lregval")
> +
> +#define __PCPU_LG(regoff, lcoff) \
> + ALTERNATIVE("lg " regoff ", " lcoff "(%%r0)\n", \
> + "lg " regoff ", " lcoff "+" LC_ALT_ADDR "(%%r0)\n", \
> ALT_FEATURE(MFEATURE_LOWCORE))
>
> -#define __PCPU_BEGIN(lcreg, lcoff, reg) \
> - DEFINE_GR_NUM \
> - "_GR_NUM .Lreg, " reg "\n" \
> - UNDEF_GR_NUM \
> - __PCPU_MVIY(lcreg, ".Lreg") \
> - __PCPU_AG(reg, lcoff)
> +#define __PCPU_AGRK(regptr, regpcp, regoff) \
> + " agrk " regptr "," regpcp "," regoff "\n"
> +
> +#define __PCPU_BEGIN(lcreg, lcoff, regpcp, regoff, regptr) \
> + __PCPU_MVIY_REGS(lcreg, regpcp, regoff) \
> + __PCPU_LG(regoff, lcoff) \
> + __PCPU_AGRK(regptr, regpcp, regoff)
Since percpu_exit() relies on regptr being regoff + 1, maybe it's worth
having a check here to verify that? Perhaps in __PCPU_MVIY_REGS() with
the uniqueness check.
Hopefully that never goes wrong, but catching a violation at build time
might save some future pain.
Mark.
next prev parent reply other threads:[~2026-09-18 10:40 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 8:48 [PATCH v2 00/12] s390: More this_cpu_*() changes Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 01/12] s390/percpu: Fix comment typo Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 02/12] s390/percpu: Add sanity check to GEN_MVIY macro Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 03/12] s390/lowcore: Remove _AC() from LOWCORE_ALT_ADDRESS Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 04/12] s390/percpu: Let MVIY_PERCPU() calculate alternative displacement Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 05/12] s390/percpu/lowcore: Add and use LC_PERCPU lowcore offset defines Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 06/12] s390/percpu: Rename inline assembly symbolic names Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 07/12] s390/percpu: Use __PCPU_BEGIN() and __PCPU_END() for inline assemblies Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 08/12] s390/percpu: Use percpu code section for this_cpu_cmpxchg128() Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 09/12] s390/percpu: Use percpu code section for this_cpu_xchg() Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 10/12] s390/percpu: Use percpu code section for this_cpu_cmpxchg() Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 11/12] s390: Add CC_HAS_ASM_M_FORMAT_FLAG config option Heiko Carstens
2026-09-18 8:48 ` [PATCH v2 12/12] s390/percpu: Rework to simplify percpu_entry() and percpu_exit() Heiko Carstens
2026-09-18 9:53 ` Heiko Carstens
2026-09-18 10:40 ` Mark Rutland [this message]
2026-09-18 11:02 ` Heiko Carstens
2026-09-18 10:31 ` [PATCH v2 00/12] s390: More this_cpu_*() changes Mark Rutland
2026-09-18 10:59 ` Heiko Carstens
2026-09-18 11:24 ` Mark Rutland
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=aq0VFSS_81QTKjcj@J2N7QTR9R3 \
--to=mark.rutland@arm.com \
--cc=agordeev@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=iii@linux.ibm.com \
--cc=jchrist@linux.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=meted@linux.ibm.com \
--cc=peterz@infradead.org \
--cc=svens@linux.ibm.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
all inboxes | Powered by JetHome®