Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 5/5] ARM: multi_v7_defconfig: Correct QCOM_RPMH and QCOM_RPMHPD
From: Linus Walleij @ 2026-04-24  6:59 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Bjorn Andersson,
	Dmitry Baryshkov, Dinh Nguyen, Krzysztof Kozlowski, Arnd Bergmann,
	Drew Fustini, soc, linux-arm-kernel, linux-kernel
In-Reply-To: <20260412-b4-defconfig-multi-v7-v1-5-e76de035c2df@oss.qualcomm.com>

On Sun, Apr 12, 2026 at 7:13 PM Krzysztof Kozlowski
<krzysztof.kozlowski@oss.qualcomm.com> wrote:

> QCOM_RPMH and QCOM_RPMHPD can be build only as modules when
> QCOM_COMMAND_DB is module itself.
>
> Fixes: 1c25ca9bb5c5 ("ARM: multi_v7_defconfig: enable more Qualcomm drivers")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH v5 6/8] amba/serial: amba-pl011: Bring back zx29 UART support
From: Linus Walleij @ 2026-04-24  7:05 UTC (permalink / raw)
  To: Stefan Dösinger
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
	Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
	linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <20260421-send-v5-6-ace038e63515@gmail.com>

On Tue, Apr 21, 2026 at 10:24 PM Stefan Dösinger
<stefandoesinger@gmail.com> wrote:

> This is based on code removed in commit 89d4f98ae90d ("ARM: remove zte
> zx platform"). I did not bring back the zx29-uart .compatible as the
> arm,primecell-periphid does the job.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

I like this.
Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH v18 0/8] ring-buffer: Making persistent ring buffers robust
From: Masami Hiramatsu @ 2026-04-24  7:06 UTC (permalink / raw)
  To: Masami Hiramatsu (Google), Steven Rostedt
  Cc: Steven Rostedt, Catalin Marinas, Will Deacon, Mathieu Desnoyers,
	linux-kernel, linux-trace-kernel, Ian Rogers, linux-arm-kernel
In-Reply-To: <177701351903.2223789.17087009302463188638.stgit@mhiramat.tok.corp.google.com>

Hi Steve,

I added a fix related this series as the 1st one. It can be merged
independently.

Thanks,

On Fri, 24 Apr 2026 15:51:59 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> Hi,
> 
> Here is the 18th version of improvement patches for making persistent
> ring buffers robust to failures.
> The previous version is here:
> 
> https://lore.kernel.org/all/177687458572.932171.10907864814735342737.stgit@mhiramat.tok.corp.google.com/
> 
> This version fixes a newly found bug and some review comments from
> Sashiko[1], also, add 2 cleanups, which includes:
> [1/8] Do not double count the reader_page when verifying persistent
>       ring buffer.
> [2/8] Add Geert's Ack (Thanks!)
> [3/8] Fix to substract BUF_PAGE_HDR_SIZE from meta->subbuf_size
>       to make the limit of commit size.
> [4/8] Reset timestamp of reader_page when the entire cpu_buffer is
>       invalid.
> [5/8] In rb_test_inject_invalid_pages(), changed entry_bytes and
>       idx to unsigned long.
> [7/8] Cleanup persistent ring buffer validation code.
> [8/8] Cleanup buffer_data_page related code.
> 
> [1] https://sashiko.dev/#/patchset/177687458572.932171.10907864814735342737.stgit%40mhiramat.tok.corp.google.com
> 
> Thank you,
> 
> Masami Hiramatsu (Google) (8):
>       ring-buffer: Do not double count the reader_page
>       ring-buffer: Flush and stop persistent ring buffer on panic
>       ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer
>       ring-buffer: Skip invalid sub-buffers when rewinding persistent ring buffer
>       ring-buffer: Add persistent ring buffer invalid-page inject test
>       ring-buffer: Show commit numbers in buffer_meta file
>       ring-buffer: Cleanup persistent ring buffer validation
>       ring-buffer: Cleanup buffer_data_page related code
> 
> 
>  arch/alpha/include/asm/Kbuild        |    1 
>  arch/arc/include/asm/Kbuild          |    1 
>  arch/arm/include/asm/Kbuild          |    1 
>  arch/arm64/include/asm/ring_buffer.h |   10 +
>  arch/csky/include/asm/Kbuild         |    1 
>  arch/hexagon/include/asm/Kbuild      |    1 
>  arch/loongarch/include/asm/Kbuild    |    1 
>  arch/m68k/include/asm/Kbuild         |    1 
>  arch/microblaze/include/asm/Kbuild   |    1 
>  arch/mips/include/asm/Kbuild         |    1 
>  arch/nios2/include/asm/Kbuild        |    1 
>  arch/openrisc/include/asm/Kbuild     |    1 
>  arch/parisc/include/asm/Kbuild       |    1 
>  arch/powerpc/include/asm/Kbuild      |    1 
>  arch/riscv/include/asm/Kbuild        |    1 
>  arch/s390/include/asm/Kbuild         |    1 
>  arch/sh/include/asm/Kbuild           |    1 
>  arch/sparc/include/asm/Kbuild        |    1 
>  arch/um/include/asm/Kbuild           |    1 
>  arch/x86/include/asm/Kbuild          |    1 
>  arch/xtensa/include/asm/Kbuild       |    1 
>  include/asm-generic/ring_buffer.h    |   13 +
>  include/linux/ring_buffer.h          |    1 
>  kernel/trace/Kconfig                 |   34 ++
>  kernel/trace/ring_buffer.c           |  472 +++++++++++++++++++++++-----------
>  kernel/trace/trace.c                 |    4 
>  26 files changed, 395 insertions(+), 159 deletions(-)
>  create mode 100644 arch/arm64/include/asm/ring_buffer.h
>  create mode 100644 include/asm-generic/ring_buffer.h
> 
> 
> base-commit: 6170922f137231b98fc568571befef63e1edff3f
> --
> Masami Hiramatsu (Google) <mhiramat@kernel.org>


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>


^ permalink raw reply

* Re: [PATCH v5 1/8] ARM: zte: Add zx297520v3 platform support
From: Linus Walleij @ 2026-04-24  7:06 UTC (permalink / raw)
  To: Stefan Dösinger
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
	Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
	linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <20260421-send-v5-1-ace038e63515@gmail.com>

On Tue, Apr 21, 2026 at 10:24 PM Stefan Dösinger
<stefandoesinger@gmail.com> wrote:

> This SoC is used in low end LTE-to-WiFi routers, for example some D-Link
> DWR 932 revisions, ZTE K10, ZLT S10 4G, but also models that are branded
> and sold by ISPs themselves. They are widespread in Africa, China,
> Russia and Eastern Europe.
>
> This SoC is a relative of the zx296702 and zx296718 that had some
> upstream support until commit 89d4f98ae90d ("ARM: remove zte zx
> platform"). My eventual goal is to enable OpenWRT to run on these
> devices.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

Didn't I review this already? I don't remember, anyway:
Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH v5 4/8] ARM: zte: Add support for zx29 low level debug
From: Linus Walleij @ 2026-04-24  7:07 UTC (permalink / raw)
  To: Stefan Dösinger
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
	Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
	linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <20260421-send-v5-4-ace038e63515@gmail.com>

On Tue, Apr 21, 2026 at 10:24 PM Stefan Dösinger
<stefandoesinger@gmail.com> wrote:

> This is based on the removed zx29 code. A separate (more complicated)
> patch will re-add the register map to the pl011 serial driver.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH v5 8/8] ARM: defconfig: Add a zx29 defconfig file
From: Linus Walleij @ 2026-04-24  7:13 UTC (permalink / raw)
  To: Stefan Dösinger
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Drew Fustini,
	Greg Kroah-Hartman, Jiri Slaby, linux-doc, linux-kernel,
	linux-arm-kernel, devicetree, soc, linux-serial
In-Reply-To: <20260421-send-v5-8-ace038e63515@gmail.com>

On Tue, Apr 21, 2026 at 10:24 PM Stefan Dösinger
<stefandoesinger@gmail.com> wrote:

> This enables existing drivers that already are (UART) or will be (USB,
> GPIO) necessary to operate this board even if they aren't declared in
> the DTS yet.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

*I* personally (as SoC maintainer) think that having a few more defconfigs
is fine, even helpful.

But I would defer this to the more senior SoC maintainers because I think
their stance is something like:

- We have multi_v7_defconfig for compile testing

- We know that binary gets way to big for your system: it's for build
  testing and perhaps booting in QEMU or systems with many MB of
  RAM, not for actually running it on products.

- You are encouraged to keep your own defconfig out-of-tree.

However I even challenged this myself by adding a defconfig for memory
constrained Broadcoms a while back (NACKed/ignored ;) so if it was all
up to me I would merge this.

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH] KVM: arm64: Wake-up from WFI when iqrchip is in userspace
From: Marc Zyngier @ 2026-04-24  7:24 UTC (permalink / raw)
  To: Yao Yuan
  Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
	Oliver Upton, Zenghui Yu
In-Reply-To: <uhqgyol622go4lm5btbk4jyieb3swhskpkyel4mnksfeki2mo2@ecnjvxwiqcfw>

On Fri, 24 Apr 2026 07:33:02 +0100,
Yao Yuan <yaoyuan@linux.alibaba.com> wrote:
> 
> On Thu, Apr 23, 2026 at 05:36:07PM +0800, Marc Zyngier wrote:
> > It appears that there is nothing in the wake-up path that
> > evaluates whether the in-kernel interrupts are pending unless
> > we have a vgic.
> >
> > This means that the userspace irqchip support has been broken for
> > about four years, and nobody noticed. It was also broken before
> > as we wouldn't wake-up on a PMU interrupt, but hey, who cares...
> >
> > It is probably time to remove the feature altogether, because it
> > was a terrible idea 10 years ago, and it still is.
> >
> > Fixes: b57de4ffd7c6d ("KVM: arm64: Simplify kvm_cpu_has_pending_timer()")
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> >  arch/arm64/kvm/arm.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 176cbe8baad30..8bb2c7422cc8b 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -824,6 +824,10 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
> >  {
> >  	bool irq_lines = *vcpu_hcr(v) & (HCR_VI | HCR_VF | HCR_VSE);
> >
> 
> Hi Marc,
> 
> > +	irq_lines |= (!irqchip_in_kernel(v->kvm) &&
> > +		      (kvm_timer_should_notify_user(v) ||
> > +		       kvm_pmu_should_notify_user(v)));
> 
> How about a new helper like 'kvm_should_notify_us_irqchip()' ?
> We can replace the same part at beginning of kvm_vcpu_exit_request() and
> here w/ unlikely().

I'd rather not introduce a helper, for two reasons:

- this needs to be backported all the way to 5.19, because that's how
  far it has been broken. So keeping it small and localised is far
  better than introducing a helper that will make the backport less
  obvious.

- I have patches to remove the other calls to kvm_*_notify_user() as a
  simplification of this utterly stupid feature.

Finally, and while I agree that this could take an unlikely()
qualifier, a much better course of action would be to have a separate
patch that moves the qualifier to the predicate itself.

Thanks,

	M.

-- 
Jazz isn't dead. It just smells funny.


^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: gpio: add Axiado SGPIO controller
From: Linus Walleij @ 2026-04-24  7:26 UTC (permalink / raw)
  To: Petar Stepanovic
  Cc: Tzu-Hao Wei, Swark Yang, Prasad Bolisetty, Bartosz Golaszewski,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Harshit Shah,
	SriNavmani A, linux-gpio, devicetree, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-1-b5c7e4c2e69b@axiado.com>

Hi Petar,

thanks for your patch!

On Tue, Apr 14, 2026 at 3:49 PM Petar Stepanovic <pstepanovic@axiado.com> wrote:

> Add device tree binding for the Axiado SGPIO controller.
>
> The SGPIO controller provides a serialized interface for
> controlling multiple GPIO signals over a limited number of
> physical lines. It supports configurable data direction and
> interrupt handling.
>
> The binding describes the properties required to instantiate
> the controller and register it as a GPIO provider.
>
> Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>

(...)

> +description: |
> +  The SGPIO controller provides a serialized interface for controlling
> +  multiple GPIO signals over a limited number of physical lines.
> +  It supports configurable data direction and interrupt handling.

This is pretty generic, can you write some details on how this happens?

> +  '#gpio-cells':
> +    const: 2

Are you sure you don't want to use 3 here instead and split the 128
GPIOs into 4 "banks" second cell being the bank number?
<&gpio 2 4>; ?

Maybe this also solves the 512 GPIO by grouping the GPIOs into
8 banks...?

> +  '#interrupt-cells':
> +    const: 2

Same there.

> +  design-variant:
> +    description: SGPIO design variant size in bits (e.g. 128 or 512).
> +    enum: [128, 512]
> +    $ref: /schemas/types.yaml#/definitions/uint32

Just use two different compatible strings and infer the variant from
that string instead.

> +  ngpios:
> +    description: The number of gpios this controller has.
> +    $ref: /schemas/types.yaml#/definitions/uint32

Same here, certainly the 128 variant has 128 gpios and
the 512 has 512 GPIOs? Just use the compatible string
to infer this.

> +  bus-frequency:
> +    description: The SGPIO shift clock frequency in Hz.
> +    $ref: /schemas/types.yaml#/definitions/uint32

Don't you want to use the clock bindings and a clk property
for this?

> +  apb-frequency:
> +    description: The APB bus frequency in Hz.
> +    $ref: /schemas/types.yaml#/definitions/uint32

Dito.

> +  dout-init:
> +    description: Initial values for the dout registers.
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    minItems: 4
> +    maxItems: 4

In:
Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml

you find:

  lines-initial-states:
    $ref: /schemas/types.yaml#/definitions/uint32
    description:
      Bitmask that specifies the initial state of each line.
      When a bit is set to zero, the corresponding line will be initialized to
      the input (pulled-up) state.
      When the  bit is set to one, the line will be initialized to the
      low-level output state.
      If the property is not specified all lines will be initialized to the
      input state.

If this is what you want, use this standard binding instead.

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH 2/3] gpio: axiado: add SGPIO controller support
From: Linus Walleij @ 2026-04-24  7:44 UTC (permalink / raw)
  To: Petar Stepanovic
  Cc: Tzu-Hao Wei, Swark Yang, Prasad Bolisetty, Bartosz Golaszewski,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Harshit Shah,
	SriNavmani A, linux-gpio, devicetree, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.com>

Hi Petar,

thanks for your patch!

On Tue, Apr 14, 2026 at 3:48 PM Petar Stepanovic <pstepanovic@axiado.com> wrote:

> Add support for the Axiado SGPIO controller.
>
> The controller provides a serialized interface for GPIOs with
> configurable direction and interrupt support.
>
> The driver registers the controller as a gpio_chip and uses
> regmap for register access.
>
> Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>

(...)

> +static void ax3000_sgpio_set(struct gpio_chip *chip, unsigned int offset,
> +                            int value)
> +{
> +       struct ax3000_sgpio *sgpio = gpiochip_get_data(chip);
> +       unsigned long flags;
> +       u32 bank = (offset / 2) / 32;
> +       u32 position = (offset / 2) % 32;

This systematic calculation of offsets from bank and position and the
whole bank concept makes me feel that perhaps the bindings are
better off reflecting the bank structure either by defining several banks
using 2 cells or by using a 3-cell binding?

For 3-cell see:
commit bd3ce71078bde4ecbfc60d49c96d1c55de0635cc
"gpiolib: of: Handle threecell GPIO chips"
for some details on how this can help.

Either of these approaches will further probably help you to
use GPIO_GENERIC (gpio-mmio) helper functions with this hardware,

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH v5 8/8] ARM: defconfig: Add a zx29 defconfig file
From: Arnd Bergmann @ 2026-04-24  7:48 UTC (permalink / raw)
  To: Stefan Dösinger, Jonathan Corbet, Shuah Khan, Russell King,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial
In-Reply-To: <20260421-send-v5-8-ace038e63515@gmail.com>

On Tue, Apr 21, 2026, at 22:23, Stefan Dösinger wrote:
> This enables existing drivers that already are (UART) or will be (USB,
> GPIO) necessary to operate this board even if they aren't declared in
> the DTS yet.
>
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

I'll reply to Linus' comment as well, the defconfigs are generally
not in a great shape across many platforms, so we should come up
with some better policies there.

Either way, the patch description above should at least explain
why you think you need your own defconfig, as we don't normally
take those.

Some comments about the contents of this file:

> +++ b/arch/arm/configs/zx29_defconfig
> @@ -0,0 +1,89 @@
> +CONFIG_SYSVIPC=y
> +CONFIG_BLK_DEV_INITRD=y
> +# CONFIG_RD_BZIP2 is not set
> +# CONFIG_RD_LZMA is not set
> +# CONFIG_RD_XZ is not set
> +# CONFIG_RD_LZ4 is not set
> +CONFIG_EXPERT=y

What is the reason for CONFIG_EXPERT here? Can you avoid this?

> +CONFIG_CMDLINE="console=ttyAMA0 earlyprintk root=/dev/ram rw"

A definconfig should normall not rely on earlyprintk, just add
that when you actually need to debug the super-early boot
stages. With "earlycon" it should pick up the right console
from the stdout path and work almost as early.

> +CONFIG_BINFMT_FLAT=y

Are you actually using flat binaries? I wasn't aware that this
is still possible on MMU-enabled kernels.

> +CONFIG_BLK_DEV_RAM=y
> +CONFIG_BLK_DEV_RAM_COUNT=4

The old ramdisk boot is going away in the future, please use
initramfs instead. This should also save a good amount of RAM.

> +CONFIG_DEVTMPFS=y       # FIXME: This is specific to my initrd. Remove 
> before upstream

stale comment?

> +CONFIG_CONFIG_TMPFS=y

Typo?


       Arnd


^ permalink raw reply

* Re: [PATCH v2] crypto: ixp4xx - fix buffer chain unwind on allocation failure
From: Linus Walleij @ 2026-04-24  7:50 UTC (permalink / raw)
  To: Ruoyu Wang
  Cc: Herbert Xu, Corentin Labbe, linux-crypto, Imre Kaloz,
	David S . Miller, linux-arm-kernel, linux-kernel
In-Reply-To: <20260423111956.185761-1-ruoyuw560@gmail.com>

On Thu, Apr 23, 2026 at 1:20 PM Ruoyu Wang <ruoyuw560@gmail.com> wrote:

> chainup_buffers() builds a linked list of buffer descriptors for a
> scatterlist. If dma_pool_alloc() fails while constructing the list, the
> current code sets buf to NULL and later dereferences it unconditionally
> at the end of the function:
>
>   buf->next = NULL;
>   buf->phys_next = 0;
>
> This can lead to a null-pointer dereference on allocation failure.
>
> If the failure happens after part of the descriptor chain has already
> been allocated and DMA-mapped, the partially constructed chain also
> needs to be released.
>
> Fix this by terminating the partially constructed chain on allocation
> failure and letting the callers unwind it via their existing cleanup
> paths. Also fix ablk_perform() to preserve the hook pointers before
> checking for failure, so partially built chains can be freed correctly.
>
> Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>

Essentially I think Corentin & Herbert are better at reviewing this code
but it sure looks good to me!
Acked-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply

* Re: [PATCH v3 0/3] gpio: Add EIO GPIO support
From: Linus Walleij @ 2026-04-24  7:52 UTC (permalink / raw)
  To: Shubhrajyoti Datta
  Cc: linux-kernel, git, shubhrajyoti.datta, Srinivas Neeli,
	Michal Simek, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
	linux-arm-kernel
In-Reply-To: <20260421104358.2496125-1-shubhrajyoti.datta@amd.com>

On Tue, Apr 21, 2026 at 12:44 PM Shubhrajyoti Datta
<shubhrajyoti.datta@amd.com> wrote:

> Add the EIO GPIO support.
> Add the dt description and the compatible to the driver.

The series:
Reviewed-by: Linus Walleij <linusw@kernel.org>

Yours,
Linus Walleij


^ permalink raw reply

* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Dmitry Vyukov @ 2026-04-24  7:56 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Mathias Stearn, Jinjie Ruan, linux-man, Mark Rutland,
	Mathieu Desnoyers, Catalin Marinas, Will Deacon, Boqun Feng,
	Paul E. McKenney, Chris Kennelly, regressions, linux-kernel,
	linux-arm-kernel, Peter Zijlstra, Ingo Molnar, Blake Oler
In-Reply-To: <87a4ut1njh.ffs@tglx>

On Thu, 23 Apr 2026 at 21:31, Thomas Gleixner <tglx@linutronix.de> wrote:
>
> On Thu, Apr 23 2026 at 12:51, Mathias Stearn wrote:
> > On Thu, Apr 23, 2026 at 12:39 PM Thomas Gleixner <tglx@linutronix.de> wrote:
> >> The kernel clears rseq_cs reliably when user space was interrupted and:
> >>
> >>     the task was preempted
> >> or
> >>     the return from interrupt delivers a signal
> >>
> >> If the task invoked a syscall then there is absolutely no reason to do
> >> either of this because syscalls from within a critical section are a
> >> bug and catched when enabling rseq debugging.
> >>
> >> The original code did this along with unconditionally updating CPU/MMCID
> >> which resulted in ~15% performance regression on a syscall heavy
> >> database benchmark once glibc started to register rseq.
> >
> > Just to be clear TCMalloc does not need either rseq_cs to be cleared
> > or cpu_id_start to be written to on syscalls because it doesn't do
> > syscalls from critical sections. It will actually benefit (slightly)
> > from not updating cpu_id_start on syscalls.
>
> I know that it does not do syscalls from within critical sections, but
> it relies on cpu_id_start being unconditionally updated in one way or
> the other.
>
> > It is specifically in the cases where an rseq would need to be aborted
> > (preemption, signals, migration, and membarrier IPI with the rseq
> > flag) that TCMalloc relies on cpu_id_start being written. It does rely
> > on that write even when not inside the critical section, because it
> > effectively uses that to detect if there were any would-cause-abort
> > events in between two critical sections. But since it leaves the
> > rseq_cs pointer non-null between critical sections, so you dont need
> > to add _any_ overhead for programs that never make use of rseq after
> > registration, or add any overhead to syscalls even for those who do.
>
> Well. According to the comment in the tcmalloc code:
>
> // Calculation of the address of the current CPU slabs region is needed for
> // allocation/deallocation fast paths, but is quite expensive. Due to variable
> // shift and experimental support for "virtual CPUs", the calculation involves
> // several additional loads and dependent calculations. Pseudo-code for the
> // address calculation is as follows:
> //
> //   cpu_offset = TcmallocSlab.virtual_cpu_id_offset_;
> //   cpu = *(&__rseq_abi + virtual_cpu_id_offset_);
> //   slabs_and_shift = TcmallocSlab.slabs_and_shift_;
> //   shift = slabs_and_shift & kShiftMask;
> //   shifted_cpu = cpu << shift;
> //   slabs = slabs_and_shift & kSlabsMask;
> //   slabs += shifted_cpu;
> //
> // To remove this calculation from fast paths, we cache the slabs address
> // for the current CPU in thread local storage. However, when a thread is
> // rescheduled to another CPU, we somehow need to understand that the cached
>
>                   ^^^^^^^^^^^
>
> // address is not valid anymore. To achieve this, we overlap the top 4 bytes
> // of the cached address with __rseq_abi.cpu_id_start. When a thread is
> // rescheduled the kernel overwrites cpu_id_start with the current CPU number,
> // which gives us the signal that the cached address is not valid anymore.
>
> The kernel still as of today (the arm64 bug aside) updates the
> cpu_id_start and cpu_id fields in rseq when a task is rescheduled to
> another CPU.
>
> So if the code only requires to know when it got rescheduled to another
> CPU then it still should work, no?

This was my first thought too:
https://lore.kernel.org/lkml/CACT4Y+a9GnOh3wHKSRwzoKF6_OSksQ8qehnHfpCgkQSt_OOmYg@mail.gmail.com/
The only problem is with membarrier (it used to force write to
__rseq_abi.cpu_id_start for all threads, but now it does not).
Otherwise the caching scheme works.

I have a tentative fix for tcmalloc:
https://github.com/dvyukov/tcmalloc/commit/58d0eca91503f539b26d20b6f55fb2f6f8bc0c37

The crux is as follows.
Tcmalloc needs to make all threads stop using old cached slab
pointers. The stopping procedure is now:

slab->stopped = true;
membarrier();

and all rseq critical sections now check the stopped flag in the
cached slab pointer. If it's set, the thread does not proceed to use
the slab.




> But it does not, which makes it clear that it relies on this
> undocumented behaviour of the kernel to rewrite rseq::cpu_id_start
> unconditionally. I'm not yet convinced that it relies on it only when
> interrupted between two subsequent critical sections. We'll see.
>
> ....
>
> Now we come to the best part of this comment:
>
> // Note: this makes __rseq_abi.cpu_id_start unusable for its original purpose.
>
> So any code sequence which ends up in:
>
>    x = tcmalloc();
>    dostuff(x)
>      evaluate(rseq::cpu_id_start, rseq::cpu_id)
>
> is doomed. This might be acceptable for Google internal usage where they
> control the full stack and can prevent anyone else to utilize rseq, but
> in an open ecosystem that's obviously a non-starter.
>
> And they definitely forgot to add this to the comment:
>
> // Never enable CONFIG_RSEQ_DEBUG in the kernel when you use tcmalloc as
> // it will expose the blatant ABI abuse and therefore will kill your
> // application.
>
> If your assumption that the rewrite is only required when rseq::rseq_cs
> is non NULL and user space was interrupted is correct, then the obvious
> no-brainer would have been to add:
>
>         __u64   rseq_usr_data;
>
> to struct rseq and clear that unconditionally when rseq::rseq_cs is
> cleared.
>
> But that would have been too simple, would work independent of endianess
> and not in the way of anybody else.
>
> But I know that's incompatible with the features first, correctness
> later and we own the world anyway mindset.
>
> Just for giggles I asked Google Gemini about the implications of
> tmalloc's rseq abuse. The answer is pretty clear:
>
>    "In short, TCMalloc treats RSEQ as a private optimization rather than
>     a shared system resource, which compromises the stability and
>     extensibility of any application that needs RSEQ for anything other
>     than memory allocation."
>
> It's also very clear about the wilful ignorance of the tcmalloc people:
>
>    "In summary, the developers have known for at least 6 years that the
>     implementation was non-standard and conflicting with other rseq
>     usage. The github issue which requested glibc compatibility was
>     opened in 2022 and has been unresolved since then."
>
> Thanks,
>
>         tglx


^ permalink raw reply

* Re: [PATCH] watchdog: ixp4xx: fix reference leak on platform_device_register() failure
From: Guangshuo Li @ 2026-04-24  8:00 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Guenter Roeck, Imre Kaloz, Daniel Lezcano, Thomas Gleixner,
	linux-arm-kernel, linux-kernel, stable
In-Reply-To: <CAD++jLkv=5rJhGv6t9H-oP9k5MY8s-fH1=gHVC88ctbiaMPC7A@mail.gmail.com>

Hi Linus, Guenter,

Thanks for reviewing and discussing this.

On Mon, 20 Apr 2026 at 05:34, Linus Walleij <linusw@kernel.org> wrote:
>
> On Sun, Apr 19, 2026 at 11:08 PM Guenter Roeck <linux@roeck-us.net> wrote:
> > On 4/19/26 13:22, Linus Walleij wrote:
>
> > > Hi Guangshuo,
> > >
> > > thanks for your patch!
> > >
> > > On Mon, Apr 13, 2026 at 5:47 PM Guangshuo Li <lgs201920130244@gmail.com> wrote:
> > >
> > >> ixp4xx_timer_probe() directly returns the result of
> > >> platform_device_register(&ixp4xx_watchdog_device). When registration
> > >> fails, the embedded struct device in ixp4xx_watchdog_device has already
> > >> been initialized by device_initialize(), but the failure path does not
> > >> drop the device reference, leading to a reference leak.
> > > (...)
> > >
> > >> -       return platform_device_register(&ixp4xx_watchdog_device);
> > >> +       ret = platform_device_register(&ixp4xx_watchdog_device);
> > >> +       if (ret)
> > >> +               platform_device_put(&ixp4xx_watchdog_device);
> > >
> > > If the problem in the description is indeed there, it seems the bug
> > > is inside platform_device_register(), surely a function returning an
> > > error code is supposed to clean up any resources it takes before
> > > returning an error. It seems wrong to try to fix this in all the
> > > consumers.
> > >
> >
> >  From platform_device_register():
> >
> > /**
> >   * platform_device_register - add a platform-level device
> >   * @pdev: platform device we're adding
> >   *
> >   * NOTE: _Never_ directly free @pdev after calling this function, even if it
> >   * returned an error! Always use platform_device_put() to give up the
> >   * reference initialised in this function instead.
> >   */
> >
> > Not that any code actually does that as far as I can see, but isn't
> > the above doing exactly what the comment suggests ?
>
> Yeah and Johan Hovold wrote that comment and he usually knows
> what he's doing so let's go with this then, I'm convinced!
>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
>
> Yours,
> Linus Walleij

After further checking, this patch is not appropriate for this driver.
ixp4xx_watchdog_device is a static platform_device, and it does not have
a dev.release callback. Calling platform_device_put() on the
platform_device_register() failure path can therefore trigger the missing
release callback warning.

So please disregard this patch. I will drop it and will also go back and
check the other patches I sent for the same pattern, and send follow-ups
where they should be ignored or reverted.

Sorry for the confusion, and thanks again for the review.

Best regards,
Guangshuo Li


^ permalink raw reply

* Re: [PATCH v10 3/6] mfd: max77759: add register bitmasks and modify irq configs for charger
From: Lee Jones @ 2026-04-24  8:26 UTC (permalink / raw)
  To: amitsd
  Cc: André Draszik, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Greg Kroah-Hartman, Jagan Sridharan, Mark Brown,
	Matti Vaittinen, Andrew Morton, Sebastian Reichel,
	Heikki Krogerus, Peter Griffin, Tudor Ambarus, Alim Akhtar,
	linux-kernel, devicetree, linux-usb, linux-pm, linux-arm-kernel,
	linux-samsung-soc, RD Babiera, Kyle Tso
In-Reply-To: <20260331-max77759-charger-v10-3-76f59233c369@google.com>

On Tue, 31 Mar 2026, Amit Sunil Dhamne via B4 Relay wrote:

> From: Amit Sunil Dhamne <amitsd@google.com>
> 
> Add register bitmasks for charger function.
> In addition split the charger IRQs further such that each bit represents
> an IRQ downstream of charger regmap irq chip. In addition populate the
> ack_base to offload irq ack to the regmap irq chip framework.

Please reword this commit messages.

Using 'In addition' twice in such close proximity reads a little awkwardly.

> Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
> Reviewed-by: André Draszik <andre.draszik@linaro.org>
> ---
>  drivers/mfd/max77759.c       |  95 ++++++++++++++++++++++---
>  include/linux/mfd/max77759.h | 166 +++++++++++++++++++++++++++++++++++--------
>  2 files changed, 222 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/mfd/max77759.c b/drivers/mfd/max77759.c
> index a7efe233ec8c..9fa6027a92c4 100644
> --- a/drivers/mfd/max77759.c
> +++ b/drivers/mfd/max77759.c
> @@ -201,8 +201,24 @@ static const struct regmap_config max77759_regmap_config_charger = {
>   *         - SYSUVLO_INT
>   *         - FSHIP_NOT_RD
>   *     - CHGR_INT: charger
> - *       - CHG_INT
> - *       - CHG_INT2
> + *       - INT1
> + *         - AICL
> + *         - CHGIN
> + *         - WCIN
> + *         - CHG
> + *         - BAT
> + *         - INLIM
> + *         - THM2
> + *         - BYP
> + *       - INT2
> + *         - INSEL
> + *         - SYS_UVLO1
> + *         - SYS_UVLO2
> + *         - BAT_OILO
> + *         - CHG_STA_CC
> + *         - CHG_STA_CV
> + *         - CHG_STA_TO
> + *         - CHG_STA_DONE
>   */
>  enum {
>  	MAX77759_INT_MAXQ,
> @@ -228,8 +244,22 @@ enum {
>  };
>  
>  enum {
> -	MAX77759_CHARGER_INT_1,
> -	MAX77759_CHARGER_INT_2,
> +	MAX77759_CHGR_INT1_AICL,
> +	MAX77759_CHGR_INT1_CHGIN,
> +	MAX77759_CHGR_INT1_WCIN,
> +	MAX77759_CHGR_INT1_CHG,
> +	MAX77759_CHGR_INT1_BAT,
> +	MAX77759_CHGR_INT1_INLIM,
> +	MAX77759_CHGR_INT1_THM2,
> +	MAX77759_CHGR_INT1_BYP,
> +	MAX77759_CHGR_INT2_INSEL,
> +	MAX77759_CHGR_INT2_SYS_UVLO1,
> +	MAX77759_CHGR_INT2_SYS_UVLO2,
> +	MAX77759_CHGR_INT2_BAT_OILO,
> +	MAX77759_CHGR_INT2_CHG_STA_CC,
> +	MAX77759_CHGR_INT2_CHG_STA_CV,
> +	MAX77759_CHGR_INT2_CHG_STA_TO,
> +	MAX77759_CHGR_INT2_CHG_STA_DONE,
>  };
>  
>  static const struct regmap_irq max77759_pmic_irqs[] = {
> @@ -256,8 +286,38 @@ static const struct regmap_irq max77759_topsys_irqs[] = {
>  };
>  
>  static const struct regmap_irq max77759_chgr_irqs[] = {
> -	REGMAP_IRQ_REG(MAX77759_CHARGER_INT_1, 0, GENMASK(7, 0)),
> -	REGMAP_IRQ_REG(MAX77759_CHARGER_INT_2, 1, GENMASK(7, 0)),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_AICL, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_AICL),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_CHGIN, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_CHGIN),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_WCIN, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_WCIN),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_CHG, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_CHG),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_BAT, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_BAT),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_INLIM, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_INLIM),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_THM2, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_THM2),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT1_BYP, 0,
> +		       MAX77759_CHGR_REG_CHG_INT_BYP),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_INSEL, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_INSEL),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_SYS_UVLO1, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO1),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_SYS_UVLO2, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO2),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_BAT_OILO, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_BAT_OILO),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_CC, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CC),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_CV, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CV),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_TO, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_CHG_STA_TO),
> +	REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_DONE, 1,
> +		       MAX77759_CHGR_REG_CHG_INT2_CHG_STA_DONE),

Can I suggest using the 100-char limit to expand and neaten these up a bit.

>  };
>  
>  static const struct regmap_irq_chip max77759_pmic_irq_chip = {
> @@ -297,11 +357,12 @@ static const struct regmap_irq_chip max77759_topsys_irq_chip = {
>  	.num_irqs = ARRAY_SIZE(max77759_topsys_irqs),
>  };
>  
> -static const struct regmap_irq_chip max77759_chrg_irq_chip = {
> +static const struct regmap_irq_chip max77759_chgr_irq_chip = {

This is a sneaky change.  If you're going to bundle fixes like this, at
least drop a mention in the commit message.

>  	.name = "max77759-chgr",
>  	.domain_suffix = "CHGR",
>  	.status_base = MAX77759_CHGR_REG_CHG_INT,
>  	.mask_base = MAX77759_CHGR_REG_CHG_INT_MASK,
> +	.ack_base = MAX77759_CHGR_REG_CHG_INT,
>  	.num_regs = 2,
>  	.irqs = max77759_chgr_irqs,
>  	.num_irqs = ARRAY_SIZE(max77759_chgr_irqs),
> @@ -325,8 +386,22 @@ static const struct resource max77759_gpio_resources[] = {
>  };
>  
>  static const struct resource max77759_charger_resources[] = {
> -	DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_1, "INT1"),
> -	DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_2, "INT2"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_AICL,         "AICL"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_CHGIN,        "CHGIN"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_WCIN,         "WCIN"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_CHG,          "CHG"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_BAT,          "BAT"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_INLIM,        "INLIM"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_THM2,         "THM2"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_BYP,          "BYP"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_INSEL,        "INSEL"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_SYS_UVLO1,    "SYS_UVLO1"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_SYS_UVLO2,    "SYS_UVLO2"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_BAT_OILO,     "BAT_OILO"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_CC,   "CHG_STA_CC"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_CV,   "CHG_STA_CV"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_TO,   "CHG_STA_TO"),
> +	DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_DONE, "CHG_STA_DONE"),
>  };
>  
>  static const struct mfd_cell max77759_cells[] = {
> @@ -567,7 +642,7 @@ static int max77759_add_chained_charger(struct i2c_client *client,
>  					    max77759->regmap_charger,
>  					    MAX77759_INT_CHGR,
>  					    parent,
> -					    &max77759_chrg_irq_chip,
> +					    &max77759_chgr_irq_chip,
>  					    &irq_chip_data);
>  	if (ret)
>  		return ret;
> diff --git a/include/linux/mfd/max77759.h b/include/linux/mfd/max77759.h
> index c6face34e385..ec19be952877 100644
> --- a/include/linux/mfd/max77759.h
> +++ b/include/linux/mfd/max77759.h
> @@ -59,35 +59,65 @@
>  #define MAX77759_MAXQ_REG_AP_DATAIN0            0xb1
>  #define MAX77759_MAXQ_REG_UIC_SWRST             0xe0
>  
> -#define MAX77759_CHGR_REG_CHG_INT               0xb0
> -#define MAX77759_CHGR_REG_CHG_INT2              0xb1
> -#define MAX77759_CHGR_REG_CHG_INT_MASK          0xb2
> -#define MAX77759_CHGR_REG_CHG_INT2_MASK         0xb3
> -#define MAX77759_CHGR_REG_CHG_INT_OK            0xb4
> -#define MAX77759_CHGR_REG_CHG_DETAILS_00        0xb5
> -#define MAX77759_CHGR_REG_CHG_DETAILS_01        0xb6
> -#define MAX77759_CHGR_REG_CHG_DETAILS_02        0xb7
> -#define MAX77759_CHGR_REG_CHG_DETAILS_03        0xb8
> -#define MAX77759_CHGR_REG_CHG_CNFG_00           0xb9
> -#define MAX77759_CHGR_REG_CHG_CNFG_01           0xba
> -#define MAX77759_CHGR_REG_CHG_CNFG_02           0xbb
> -#define MAX77759_CHGR_REG_CHG_CNFG_03           0xbc
> -#define MAX77759_CHGR_REG_CHG_CNFG_04           0xbd
> -#define MAX77759_CHGR_REG_CHG_CNFG_05           0xbe
> -#define MAX77759_CHGR_REG_CHG_CNFG_06           0xbf
> -#define MAX77759_CHGR_REG_CHG_CNFG_07           0xc0
> -#define MAX77759_CHGR_REG_CHG_CNFG_08           0xc1
> -#define MAX77759_CHGR_REG_CHG_CNFG_09           0xc2
> -#define MAX77759_CHGR_REG_CHG_CNFG_10           0xc3
> -#define MAX77759_CHGR_REG_CHG_CNFG_11           0xc4
> -#define MAX77759_CHGR_REG_CHG_CNFG_12           0xc5
> -#define MAX77759_CHGR_REG_CHG_CNFG_13           0xc6
> -#define MAX77759_CHGR_REG_CHG_CNFG_14           0xc7
> -#define MAX77759_CHGR_REG_CHG_CNFG_15           0xc8
> -#define MAX77759_CHGR_REG_CHG_CNFG_16           0xc9
> -#define MAX77759_CHGR_REG_CHG_CNFG_17           0xca
> -#define MAX77759_CHGR_REG_CHG_CNFG_18           0xcb
> -#define MAX77759_CHGR_REG_CHG_CNFG_19           0xcc
> +#define MAX77759_CHGR_REG_CHG_INT                      0xb0
> +#define   MAX77759_CHGR_REG_CHG_INT_AICL               BIT(7)
> +#define   MAX77759_CHGR_REG_CHG_INT_CHGIN              BIT(6)
> +#define   MAX77759_CHGR_REG_CHG_INT_WCIN               BIT(5)
> +#define   MAX77759_CHGR_REG_CHG_INT_CHG                BIT(4)
> +#define   MAX77759_CHGR_REG_CHG_INT_BAT                BIT(3)
> +#define   MAX77759_CHGR_REG_CHG_INT_INLIM              BIT(2)
> +#define   MAX77759_CHGR_REG_CHG_INT_THM2               BIT(1)
> +#define   MAX77759_CHGR_REG_CHG_INT_BYP                BIT(0)
> +#define MAX77759_CHGR_REG_CHG_INT2                     0xb1
> +#define   MAX77759_CHGR_REG_CHG_INT2_INSEL             BIT(7)
> +#define   MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO1         BIT(6)
> +#define   MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO2         BIT(5)
> +#define   MAX77759_CHGR_REG_CHG_INT2_BAT_OILO          BIT(4)
> +#define   MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CC        BIT(3)
> +#define   MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CV        BIT(2)
> +#define   MAX77759_CHGR_REG_CHG_INT2_CHG_STA_TO        BIT(1)
> +#define   MAX77759_CHGR_REG_CHG_INT2_CHG_STA_DONE      BIT(0)
> +#define MAX77759_CHGR_REG_CHG_INT_MASK                 0xb2
> +#define MAX77759_CHGR_REG_CHG_INT2_MASK                0xb3
> +#define MAX77759_CHGR_REG_CHG_INT_OK                   0xb4
> +#define MAX77759_CHGR_REG_CHG_DETAILS_00               0xb5
> +#define   MAX77759_CHGR_REG_CHG_DETAILS_00_CHGIN_DTLS  GENMASK(6, 5)
> +#define MAX77759_CHGR_REG_CHG_DETAILS_01               0xb6
> +#define   MAX77759_CHGR_REG_CHG_DETAILS_01_BAT_DTLS    GENMASK(6, 4)
> +#define   MAX77759_CHGR_REG_CHG_DETAILS_01_CHG_DTLS    GENMASK(3, 0)
> +#define MAX77759_CHGR_REG_CHG_DETAILS_02               0xb7
> +#define   MAX77759_CHGR_REG_CHG_DETAILS_02_CHGIN_STS   BIT(5)
> +#define MAX77759_CHGR_REG_CHG_DETAILS_03               0xb8
> +#define MAX77759_CHGR_REG_CHG_CNFG_00                  0xb9
> +#define   MAX77759_CHGR_REG_CHG_CNFG_00_MODE           GENMASK(3, 0)
> +#define MAX77759_CHGR_REG_CHG_CNFG_01                  0xba
> +#define MAX77759_CHGR_REG_CHG_CNFG_02                  0xbb
> +#define   MAX77759_CHGR_REG_CHG_CNFG_02_CHGCC          GENMASK(5, 0)
> +#define MAX77759_CHGR_REG_CHG_CNFG_03                  0xbc
> +#define MAX77759_CHGR_REG_CHG_CNFG_04                  0xbd
> +#define   MAX77759_CHGR_REG_CHG_CNFG_04_CHG_CV_PRM     GENMASK(5, 0)
> +#define MAX77759_CHGR_REG_CHG_CNFG_05                  0xbe
> +#define MAX77759_CHGR_REG_CHG_CNFG_06                  0xbf
> +#define   MAX77759_CHGR_REG_CHG_CNFG_06_CHGPROT        GENMASK(3, 2)
> +#define MAX77759_CHGR_REG_CHG_CNFG_07                  0xc0
> +#define MAX77759_CHGR_REG_CHG_CNFG_08                  0xc1
> +#define MAX77759_CHGR_REG_CHG_CNFG_09                  0xc2
> +#define   MAX77759_CHGR_REG_CHG_CNFG_09_CHGIN_ILIM     GENMASK(6, 0)
> +#define MAX77759_CHGR_REG_CHG_CNFG_10                  0xc3
> +#define MAX77759_CHGR_REG_CHG_CNFG_11                  0xc4
> +#define MAX77759_CHGR_REG_CHG_CNFG_12                  0xc5
> +/* Wireless Charging input channel select */
> +#define   MAX77759_CHGR_REG_CHG_CNFG_12_WCINSEL        BIT(6)
> +/* CHGIN/USB input channel select */
> +#define   MAX77759_CHGR_REG_CHG_CNFG_12_CHGINSEL       BIT(5)

Should we ensure these comments are formatted as complete sentences with a full
stop at the end, to comply with our documentation guidelines?

> +#define MAX77759_CHGR_REG_CHG_CNFG_13                  0xc6
> +#define MAX77759_CHGR_REG_CHG_CNFG_14                  0xc7
> +#define MAX77759_CHGR_REG_CHG_CNFG_15                  0xc8
> +#define MAX77759_CHGR_REG_CHG_CNFG_16                  0xc9
> +#define MAX77759_CHGR_REG_CHG_CNFG_17                  0xca
> +#define MAX77759_CHGR_REG_CHG_CNFG_18                  0xcb
> +#define   MAX77759_CHGR_REG_CHG_CNFG_18_WDTEN          BIT(0)
> +#define MAX77759_CHGR_REG_CHG_CNFG_19                  0xcc
>  
>  /* MaxQ opcodes for max77759_maxq_command() */
>  #define MAX77759_MAXQ_OPCODE_MAXLENGTH (MAX77759_MAXQ_REG_AP_DATAOUT32 - \
> @@ -101,6 +131,84 @@
>  #define MAX77759_MAXQ_OPCODE_USER_SPACE_READ     0x81
>  #define MAX77759_MAXQ_OPCODE_USER_SPACE_WRITE    0x82
>  
> +/**
> + * enum max77759_chgr_chgin_dtls_status - Charger Input Status
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE:
> + *     Charger input voltage (Vchgin) < Under Voltage Threshold (Vuvlo)
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE:
> + *     Vchgin > Vuvlo and Vchgin < (Battery Voltage (Vbatt) + system voltage (Vsys))
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE:
> + *     Vchgin > Over Voltage threshold (Vovlo)
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID:
> + *     Vchgin > Vuvlo, Vchgin < Vovlo and Vchgin > (Vsys + Vbatt)
> + */
> +enum max77759_chgr_chgin_dtls_status {
> +	MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE,
> +	MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE,
> +	MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE,
> +	MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID,
> +};
> +
> +/**
> + * enum max77759_chgr_bat_dtls_states - Battery Details
> + * @MAX77759_CHGR_BAT_DTLS_NO_BATT_CHG_SUSP:	No battery and the charger suspended
> + * @MAX77759_CHGR_BAT_DTLS_DEAD_BATTERY:	Vbatt < Vtrickle
> + * @MAX77759_CHGR_BAT_DTLS_BAT_CHG_TIMER_FAULT:	Charging suspended due to timer fault
> + * @MAX77759_CHGR_BAT_DTLS_BAT_OKAY:		Battery okay and Vbatt > Min Sys Voltage (Vsysmin)
> + * @MAX77759_CHGR_BAT_DTLS_BAT_UNDERVOLTAGE:	Battery is okay. Vtrickle < Vbatt < Vsysmin
> + * @MAX77759_CHGR_BAT_DTLS_BAT_OVERVOLTAGE:	Battery voltage > Overvoltage threshold
> + * @MAX77759_CHGR_BAT_DTLS_BAT_OVERCURRENT:	Battery current exceeds overcurrent threshold
> + * @MAX77759_CHGR_BAT_DTLS_BAT_ONLY_MODE:	Battery only mode and battery level not available
> + */
> +enum max77759_chgr_bat_dtls_states {
> +	MAX77759_CHGR_BAT_DTLS_NO_BATT_CHG_SUSP,
> +	MAX77759_CHGR_BAT_DTLS_DEAD_BATTERY,
> +	MAX77759_CHGR_BAT_DTLS_BAT_CHG_TIMER_FAULT,
> +	MAX77759_CHGR_BAT_DTLS_BAT_OKAY,
> +	MAX77759_CHGR_BAT_DTLS_BAT_UNDERVOLTAGE,
> +	MAX77759_CHGR_BAT_DTLS_BAT_OVERVOLTAGE,
> +	MAX77759_CHGR_BAT_DTLS_BAT_OVERCURRENT,
> +	MAX77759_CHGR_BAT_DTLS_BAT_ONLY_MODE,
> +};
> +
> +/**
> + * enum max77759_chgr_chg_dtls_states - Charger Details
> + * @MAX77759_CHGR_CHG_DTLS_PREQUAL:		Charger in prequalification mode
> + * @MAX77759_CHGR_CHG_DTLS_CC:			Charger in fast charge const curr mode
> + * @MAX77759_CHGR_CHG_DTLS_CV:			Charger in fast charge const voltage mode
> + * @MAX77759_CHGR_CHG_DTLS_TO:			Charger is in top off mode
> + * @MAX77759_CHGR_CHG_DTLS_DONE:		Charger is done
> + * @MAX77759_CHGR_CHG_DTLS_RSVD_1:		Reserved
> + * @MAX77759_CHGR_CHG_DTLS_TIMER_FAULT:		Charger is in timer fault mode
> + * @MAX77759_CHGR_CHG_DTLS_SUSP_BATT_THM:	Charger is suspended as battery removal detected
> + * @MAX77759_CHGR_CHG_DTLS_OFF:			Charger is off. Input invalid or charger disabled
> + * @MAX77759_CHGR_CHG_DTLS_RSVD_2:		Reserved
> + * @MAX77759_CHGR_CHG_DTLS_RSVD_3:		Reserved
> + * @MAX77759_CHGR_CHG_DTLS_OFF_WDOG_TIMER:	Charger is off as watchdog timer expired
> + * @MAX77759_CHGR_CHG_DTLS_SUSP_JEITA:		Charger is in JEITA control mode
> + */
> +enum max77759_chgr_chg_dtls_states {
> +	MAX77759_CHGR_CHG_DTLS_PREQUAL,
> +	MAX77759_CHGR_CHG_DTLS_CC,
> +	MAX77759_CHGR_CHG_DTLS_CV,
> +	MAX77759_CHGR_CHG_DTLS_TO,
> +	MAX77759_CHGR_CHG_DTLS_DONE,
> +	MAX77759_CHGR_CHG_DTLS_RSVD_1,
> +	MAX77759_CHGR_CHG_DTLS_TIMER_FAULT,
> +	MAX77759_CHGR_CHG_DTLS_SUSP_BATT_THM,
> +	MAX77759_CHGR_CHG_DTLS_OFF,
> +	MAX77759_CHGR_CHG_DTLS_RSVD_2,
> +	MAX77759_CHGR_CHG_DTLS_RSVD_3,
> +	MAX77759_CHGR_CHG_DTLS_OFF_WDOG_TIMER,
> +	MAX77759_CHGR_CHG_DTLS_SUSP_JEITA,
> +};
> +
> +enum max77759_chgr_mode {
> +	MAX77759_CHGR_MODE_OFF,
> +	MAX77759_CHGR_MODE_CHG_BUCK_ON = 0x5,
> +	MAX77759_CHGR_MODE_OTG_BOOST_ON = 0xA,
> +};

Would it be safer to explicitly initialise 'MAX77759_CHGR_MODE_OFF' to 0 here?
Relying on implicit zero initialisation whilst explicitly setting other values
can sometimes lead to unexpected behaviour if new entries are added.

-- 
Lee Jones


^ permalink raw reply

* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Mathias Stearn @ 2026-04-24  8:32 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Thomas Gleixner, Jinjie Ruan, linux-man, Mark Rutland,
	Mathieu Desnoyers, Catalin Marinas, Will Deacon, Boqun Feng,
	Paul E. McKenney, Chris Kennelly, regressions, linux-kernel,
	linux-arm-kernel, Peter Zijlstra, Ingo Molnar, Blake Oler
In-Reply-To: <CACT4Y+bBD7uCHXKqGo=epBXeEmsZ67Og2YO9kjNMT3ryjUY_sA@mail.gmail.com>

On Fri, Apr 24, 2026 at 9:57 AM Dmitry Vyukov <dvyukov@google.com> wrote:
> > So if the code only requires to know when it got rescheduled to another
> > CPU then it still should work, no?
>
> This was my first thought too:
> https://lore.kernel.org/lkml/CACT4Y+a9GnOh3wHKSRwzoKF6_OSksQ8qehnHfpCgkQSt_OOmYg@mail.gmail.com/
> The only problem is with membarrier (it used to force write to
> __rseq_abi.cpu_id_start for all threads, but now it does not).
> Otherwise the caching scheme works.

I almost wrote a message last night saying that we didn't need
cpu_id_start invalidation on preemption. However, I remembered that
the Grow() function[1] does a load outside of a critical section then
stores a derived value inside the critical section, guarded only by
the cpu_id_start invalidation check in StoreCurrentCpu[2]. It really
should be doing a compare against the original value inside the
critical section (or just do the whole thing inside), but it doesn't.
I haven't reasoned end-to-end through this fully to prove corruption
is possible, but I suspect that it is if another thread same-cpu
preempts between the loads and the store and updates the header before
the original thread resumes and writes its original intended header
value. Ditto for signals, which sometimes allocate even though they
shouldn't.

I was really hoping that we would only need to do the "redundant"
cpu_id_start writes would only be needed on membarrier_rseq IPIs where
it really is a pay-for-what-you-use functionality, I think existing
binaries depend on invalidation on preemption. Luckily that should be
cheap enough to be ~free.


[1] https://github.com/google/tcmalloc/blob/8e98046ec5639bffbe70a53770a2699dd355b26d/tcmalloc/internal/percpu_tcmalloc.h#L964-L980
[2] https://github.com/google/tcmalloc/blob/8e98046ec5639bffbe70a53770a2699dd355b26d/tcmalloc/internal/percpu_tcmalloc.h#L551-L605


^ permalink raw reply

* Re: [PATCH v2 15/20] drm/drv: Call drm_mode_config_create_state() by default
From: Maxime Ripard @ 2026-04-24  8:44 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Maarten Lankhorst, David Airlie, Simona Vetter, Jonathan Corbet,
	Shuah Khan, Dmitry Baryshkov, Jyri Sarha, Tomi Valkeinen,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Simon Ser, Harry Wentland,
	Melissa Wen, Sebastian Wick, Alex Hung, Jani Nikula, Rodrigo Vivi,
	Joonas Lahtinen, Tvrtko Ursulin, Chen-Yu Tsai, Samuel Holland,
	Dave Stevenson, Maíra Canal, Raspberry Pi Kernel Maintenance,
	dri-devel, linux-doc, linux-kernel, Daniel Stone, intel-gfx,
	intel-xe, linux-arm-kernel, linux-sunxi
In-Reply-To: <79cc30d5-80b5-4d87-a3ad-36d6fad98853@suse.de>

[-- Attachment #1: Type: text/plain, Size: 2088 bytes --]

Hi,

On Tue, Apr 21, 2026 at 03:38:16PM +0200, Thomas Zimmermann wrote:
> Am 20.03.26 um 17:27 schrieb Maxime Ripard:
> > Almost all drivers, and our documented skeleton, call
> > drm_mode_config_reset() prior to calling drm_dev_register() to
> > initialize its DRM object states.
> > 
> > Now that we have drm_mode_config_create_state() to create that initial
> > state if it doesn't exist, we can call it directly in
> > drm_dev_register(). That way, we know that the initial atomic state will
> > always be allocated without any boilerplate.
> > 
> > Signed-off-by: Maxime Ripard <mripard@kernel.org>
> > ---
> >   drivers/gpu/drm/drm_drv.c | 4 ++++
> >   1 file changed, 4 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> > index 2915118436ce8a6640cfb0c59936031990727ed1..820106d56ab399a39cac56d98662b5ddbcae8ded 100644
> > --- a/drivers/gpu/drm/drm_drv.c
> > +++ b/drivers/gpu/drm/drm_drv.c
> > @@ -1097,10 +1097,14 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
> >   	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
> >   		ret = drm_modeset_register_all(dev);
> >   		if (ret)
> >   			goto err_unload;
> > +
> > +		ret = drm_mode_config_create_state(dev);
> > +		if (ret)
> > +			goto err_unload;
> 
> Way too late.

Yeah... I think that was Ville's main objection too.

> Lets rather go through drivers and call this where they currently call
> drm_mode_config_reset() for initialization.

I was really hoping to remove the boilerplate from drivers, but I don't
really see a good place for it then. drm_mode_config_init() could be
another candidate, but it looks weird to put it there too.

I'll drop that then.

> This can be a single-patch mass conversion IMHO.

I'm not really sure? For it to work we'd need to convert these drivers
objects from reset to atomic_create_state too. I absolutely want to do
it next, but I don't think it will be as trivial as a sed call, and it
would probably be best done by driver to allow reverts if we screw up.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply

* [PATCH 0/6] KVM: arm64: pKVM init and feature detection fixes
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui

Hi folks,

These six patches are standalone correctness fixes I'd like to land
before posting a follow-up to Will's pKVM infrastructure series [1]
that moves vCPU state management to EL2. Sending them separately keeps
the bigger series focused, but they are all valid fixes to have
regardless.

The first patch fixes feature detection for FEAT_Debugv8p9: it was
checking the wrong field in ID_AA64DFR0_EL1, causing KVM to treat
certain EL2 control bits as RES0 on hardware that implements the
feature.

The second patch is a trivial typo fix in comments.

The third patch fixes feature detection for FEAT_SPE_FnE, which was
also checking the wrong field.

The last three fix bugs in the pKVM vCPU and hypervisor initialisation
paths: a latent macro parameter bug, a pin-reference leak with a
publication ordering issue in __pkvm_init_vcpu(), and a call-ordering
hazard in __pkvm_init_finalise() that is benign today but becomes a
crash once fix_host_ownership() is extended to operate on a non-empty
page-table.

[1] https://lore.kernel.org/all/20260105154939.11041-1-will@kernel.org/

Cheers,
/fuad

Fuad Tabba (5):
  KVM: arm64: Fix FEAT_Debugv8p9 to check DebugVer, not PMUVer
  KVM: arm64: Fix typo in feature check comments
  KVM: arm64: Fix FEAT_SPE_FnE to use PMSIDR_EL1.FnE, not PMSVer
  KVM: arm64: Fix kvm_vcpu_initialized() macro parameter
  KVM: arm64: Fix pin leak and publication ordering in
    __pkvm_init_vcpu()

Quentin Perret (1):
  KVM: arm64: Fix initialisation order in __pkvm_init_finalise()

 arch/arm64/include/asm/kvm_host.h |  2 +-
 arch/arm64/kvm/config.c           | 23 +++++++++++++------
 arch/arm64/kvm/hyp/nvhe/pkvm.c    | 38 ++++++++++++++++++++-----------
 arch/arm64/kvm/hyp/nvhe/setup.c   |  8 +++----
 4 files changed, 46 insertions(+), 25 deletions(-)

-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply

* [PATCH 1/6] KVM: arm64: Fix FEAT_Debugv8p9 to check DebugVer, not PMUVer
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui
In-Reply-To: <20260424084908.370776-1-tabba@google.com>

FEAT_Debugv8p9 is incorrectly defined against ID_AA64DFR0_EL1.PMUVer
instead of ID_AA64DFR0_EL1.DebugVer.  All three consumers of the macro
gate features that are architecturally tied to FEAT_Debugv8p9
(DebugVer = 0b1011, DDI0487 M.b A2.2.10):

  - HDFGRTR2_EL2.nMDSELR_EL1, HDFGWTR2_EL2.nMDSELR_EL1: MDSELR_EL1
    is present only when FEAT_Debugv8p9 is implemented (D24.3.21).

  - MDCR_EL2.EBWE: the Extended Breakpoint and Watchpoint Enable bit
    is RES0 unless FEAT_Debugv8p9 is implemented (D24.3.17).

Neither register has any dependency on PMUVer.

FEAT_Debugv8p9 and FEAT_PMUv3p9 are independent.  Per DDI0487 M.b
A2.2.10, FEAT_Debugv8p9 is unconditionally mandatory from Armv8.9,
whereas FEAT_PMUv3p9 is mandatory only when FEAT_PMUv3 is implemented.
An Armv8.9 CPU without a PMU has DebugVer = 0b1011 but PMUVer = 0b0000,
so the wrong field check would cause KVM to incorrectly treat EBWE and
MDSELR_EL1 as RES0 on such hardware.

Fixes: 4bc0fe089840 ("KVM: arm64: Add sanitisation for FEAT_FGT2 registers")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
 arch/arm64/kvm/config.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index f35b8dddd7c1..093290b366e6 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -192,7 +192,7 @@ struct reg_feat_map_desc {
 #define FEAT_SRMASK		ID_AA64MMFR4_EL1, SRMASK, IMP
 #define FEAT_PoPS		ID_AA64MMFR4_EL1, PoPS, IMP
 #define FEAT_PFAR		ID_AA64PFR1_EL1, PFAR, IMP
-#define FEAT_Debugv8p9		ID_AA64DFR0_EL1, PMUVer, V3P9
+#define FEAT_Debugv8p9		ID_AA64DFR0_EL1, DebugVer, V8P9
 #define FEAT_PMUv3_SS		ID_AA64DFR0_EL1, PMSS, IMP
 #define FEAT_SEBEP		ID_AA64DFR0_EL1, SEBEP, IMP
 #define FEAT_EBEP		ID_AA64DFR1_EL1, EBEP, IMP
-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply related

* [PATCH 3/6] KVM: arm64: Fix FEAT_SPE_FnE to use PMSIDR_EL1.FnE, not PMSVer
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui
In-Reply-To: <20260424084908.370776-1-tabba@google.com>

FEAT_SPE_FnE is architecturally detected via PMSIDR_EL1.FnE [6], not
ID_AA64DFR0_EL1.PMSVer. The FEAT_X macro form (register, field, value)
cannot encode a PMSIDR_EL1-based feature, so FEAT_SPE_FnE was defined
identically to FEAT_SPEv1p2 (ID_AA64DFR0_EL1, PMSVer, V1P2), producing
a duplicate that used PMSVer >= V1P2 as a proxy.

Replace the macro with feat_spe_fne(), following the same pattern as
the sibling feat_spe_fds(): guard on FEAT_SPEv1p2 and read
PMSIDR_EL1.FnE [6] directly. Wire the two NEEDS_FEAT consumers to use
the new function.

Remove the now-unused FEAT_SPE_FnE macro.

Fixes: 63d423a7635b ("KVM: arm64: Switch to table-driven FGU configuration")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
 arch/arm64/kvm/config.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index a722ea178f68..0622162b089e 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -131,7 +131,6 @@ struct reg_feat_map_desc {
 	}
 
 #define FEAT_SPE		ID_AA64DFR0_EL1, PMSVer, IMP
-#define FEAT_SPE_FnE		ID_AA64DFR0_EL1, PMSVer, V1P2
 #define FEAT_BRBE		ID_AA64DFR0_EL1, BRBE, IMP
 #define FEAT_TRC_SR		ID_AA64DFR0_EL1, TraceVer, IMP
 #define FEAT_PMUv3		ID_AA64DFR0_EL1, PMUVer, IMP
@@ -302,6 +301,16 @@ static bool feat_spe_fds(struct kvm *kvm)
 		(read_sysreg_s(SYS_PMSIDR_EL1) & PMSIDR_EL1_FDS));
 }
 
+static bool feat_spe_fne(struct kvm *kvm)
+{
+	/*
+	 * Revisit this if KVM ever supports SPE -- this really should
+	 * look at the guest's view of PMSIDR_EL1.
+	 */
+	return (kvm_has_feat(kvm, FEAT_SPEv1p2) &&
+		(read_sysreg_s(SYS_PMSIDR_EL1) & PMSIDR_EL1_FnE));
+}
+
 static bool feat_trbe_mpam(struct kvm *kvm)
 {
 	/*
@@ -537,7 +546,7 @@ static const struct reg_bits_to_feat_map hdfgrtr_feat_map[] = {
 		   HDFGRTR_EL2_PMBPTR_EL1	|
 		   HDFGRTR_EL2_PMBLIMITR_EL1,
 		   FEAT_SPE),
-	NEEDS_FEAT(HDFGRTR_EL2_nPMSNEVFR_EL1, FEAT_SPE_FnE),
+	NEEDS_FEAT(HDFGRTR_EL2_nPMSNEVFR_EL1, feat_spe_fne),
 	NEEDS_FEAT(HDFGRTR_EL2_nBRBDATA		|
 		   HDFGRTR_EL2_nBRBCTL		|
 		   HDFGRTR_EL2_nBRBIDR,
@@ -605,7 +614,7 @@ static const struct reg_bits_to_feat_map hdfgwtr_feat_map[] = {
 		   HDFGWTR_EL2_PMBPTR_EL1	|
 		   HDFGWTR_EL2_PMBLIMITR_EL1,
 		   FEAT_SPE),
-	NEEDS_FEAT(HDFGWTR_EL2_nPMSNEVFR_EL1, FEAT_SPE_FnE),
+	NEEDS_FEAT(HDFGWTR_EL2_nPMSNEVFR_EL1, feat_spe_fne),
 	NEEDS_FEAT(HDFGWTR_EL2_nBRBDATA		|
 		   HDFGWTR_EL2_nBRBCTL,
 		   FEAT_BRBE),
-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply related

* [PATCH 5/6] KVM: arm64: Fix pin leak and publication ordering in __pkvm_init_vcpu()
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui
In-Reply-To: <20260424084908.370776-1-tabba@google.com>

Two bugs exist in the vCPU initialisation path:

1. If a check fails after hyp_pin_shared_mem() succeeds, the cleanup
   path jumps to 'unlock' without calling unpin_host_vcpu() or
   unpin_host_sve_state(), permanently leaking pin references on the
   host vCPU and SVE state pages.

   Extract a register_hyp_vcpu() helper that performs the checks and
   the store. When register_hyp_vcpu() returns an error, call
   unpin_host_vcpu() and unpin_host_sve_state() inline before falling
   through to the existing 'unlock' label.

2. register_hyp_vcpu() publishes the new vCPU pointer into
   'hyp_vm->vcpus[]' with a bare store, allowing a concurrent caller
   of pkvm_load_hyp_vcpu() to observe a partially initialised vCPU
   object.

   Ensure the store uses smp_store_release() and the load uses
   smp_load_acquire(). While 'vm_table_lock' currently serialises the
   store and the load, these barriers ensure the reader sees the fully
   initialised 'hyp_vcpu' object even if there were a lockless path or
   if the lock's own ordering guarantees were insufficient for nested
   object initialization.

Fixes: 49af6ddb8e5c ("KVM: arm64: Add infrastructure to create and track pKVM instances at EL2")
Reported-by: Ben Simner <ben.simner@cl.cam.ac.uk>
Co-developed-by: Will Deacon <willdeacon@google.com>
Signed-off-by: Will Deacon <willdeacon@google.com>
Signed-off-by: Fuad Tabba <tabba@google.com>
---
 arch/arm64/kvm/hyp/nvhe/pkvm.c | 38 ++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 7ed96d64d611..e7496eb85628 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -266,7 +266,8 @@ struct pkvm_hyp_vcpu *pkvm_load_hyp_vcpu(pkvm_handle_t handle,
 	if (hyp_vm->kvm.created_vcpus <= vcpu_idx)
 		goto unlock;
 
-	hyp_vcpu = hyp_vm->vcpus[vcpu_idx];
+	/* Pairs with smp_store_release() in register_hyp_vcpu(). */
+	hyp_vcpu = smp_load_acquire(&hyp_vm->vcpus[vcpu_idx]);
 	if (!hyp_vcpu)
 		goto unlock;
 
@@ -860,12 +861,30 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
  *	     the page-aligned size of 'struct pkvm_hyp_vcpu'.
  * Return 0 on success, negative error code on failure.
  */
+static int register_hyp_vcpu(struct pkvm_hyp_vm *hyp_vm,
+			      struct pkvm_hyp_vcpu *hyp_vcpu)
+{
+	unsigned int idx = hyp_vcpu->vcpu.vcpu_idx;
+
+	if (idx >= hyp_vm->kvm.created_vcpus)
+		return -EINVAL;
+
+	if (hyp_vm->vcpus[idx])
+		return -EINVAL;
+
+	/*
+	 * Ensure the hyp_vcpu is initialised before publishing it to
+	 * the vCPU-load path via 'hyp_vm->vcpus[]'.
+	 */
+	smp_store_release(&hyp_vm->vcpus[idx], hyp_vcpu);
+	return 0;
+}
+
 int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 		     unsigned long vcpu_hva)
 {
 	struct pkvm_hyp_vcpu *hyp_vcpu;
 	struct pkvm_hyp_vm *hyp_vm;
-	unsigned int idx;
 	int ret;
 
 	hyp_vcpu = map_donated_memory(vcpu_hva, sizeof(*hyp_vcpu));
@@ -884,18 +903,11 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
 	if (ret)
 		goto unlock;
 
-	idx = hyp_vcpu->vcpu.vcpu_idx;
-	if (idx >= hyp_vm->kvm.created_vcpus) {
-		ret = -EINVAL;
-		goto unlock;
+	ret = register_hyp_vcpu(hyp_vm, hyp_vcpu);
+	if (ret) {
+		unpin_host_vcpu(host_vcpu);
+		unpin_host_sve_state(hyp_vcpu);
 	}
-
-	if (hyp_vm->vcpus[idx]) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	hyp_vm->vcpus[idx] = hyp_vcpu;
 unlock:
 	hyp_spin_unlock(&vm_table_lock);
 
-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply related

* [PATCH 4/6] KVM: arm64: Fix kvm_vcpu_initialized() macro parameter
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui
In-Reply-To: <20260424084908.370776-1-tabba@google.com>

The macro is defined with parameter 'v' but the body references the
literal token 'vcpu' instead, causing it to silently operate on whatever
'vcpu' resolves to in the caller's scope rather than the value passed by
the caller. All current call sites happen to use a variable named 'vcpu',
so the bug is latent.

Fixes: e016333745c7 ("KVM: arm64: Only reset vCPU-scoped feature ID regs once")
Signed-off-by: Fuad Tabba <tabba@google.com>
---
 arch/arm64/include/asm/kvm_host.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 851f6171751c..0e5dbc1c5879 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1548,7 +1548,7 @@ static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature)
 #define kvm_vcpu_has_feature(k, f)	__vcpu_has_feature(&(k)->arch, (f))
 #define vcpu_has_feature(v, f)	__vcpu_has_feature(&(v)->kvm->arch, (f))
 
-#define kvm_vcpu_initialized(v) vcpu_get_flag(vcpu, VCPU_INITIALIZED)
+#define kvm_vcpu_initialized(v) vcpu_get_flag(v, VCPU_INITIALIZED)
 
 int kvm_trng_call(struct kvm_vcpu *vcpu);
 #ifdef CONFIG_KVM
-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply related

* [PATCH 2/6] KVM: arm64: Fix typo in feature check comments
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui
In-Reply-To: <20260424084908.370776-1-tabba@google.com>

Revists -> Revisit. The following patch will add another similar line.

No functional change intended.

Signed-off-by: Fuad Tabba <tabba@google.com>
---
 arch/arm64/kvm/config.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 093290b366e6..a722ea178f68 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -283,7 +283,7 @@ static bool feat_anerr(struct kvm *kvm)
 static bool feat_sme_smps(struct kvm *kvm)
 {
 	/*
-	 * Revists this if KVM ever supports SME -- this really should
+	 * Revisit this if KVM ever supports SME -- this really should
 	 * look at the guest's view of SMIDR_EL1. Funnily enough, this
 	 * is not captured in the JSON file, but only as a note in the
 	 * ARM ARM.
@@ -295,7 +295,7 @@ static bool feat_sme_smps(struct kvm *kvm)
 static bool feat_spe_fds(struct kvm *kvm)
 {
 	/*
-	 * Revists this if KVM ever supports SPE -- this really should
+	 * Revisit this if KVM ever supports SPE -- this really should
 	 * look at the guest's view of PMSIDR_EL1.
 	 */
 	return (kvm_has_feat(kvm, FEAT_SPEv1p4) &&
@@ -305,7 +305,7 @@ static bool feat_spe_fds(struct kvm *kvm)
 static bool feat_trbe_mpam(struct kvm *kvm)
 {
 	/*
-	 * Revists this if KVM ever supports both MPAM and TRBE --
+	 * Revisit this if KVM ever supports both MPAM and TRBE --
 	 * this really should look at the guest's view of TRBIDR_EL1.
 	 */
 	return (kvm_has_feat(kvm, FEAT_TRBE) &&
-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply related

* [PATCH 6/6] KVM: arm64: Fix initialisation order in __pkvm_init_finalise()
From: Fuad Tabba @ 2026-04-24  8:49 UTC (permalink / raw)
  To: kvmarm, linux-arm-kernel, linux-kernel
  Cc: tabba, catalin.marinas, will, maz, oupton, qperret,
	suzuki.poulose, joey.gouly, yuzenghui
In-Reply-To: <20260424084908.370776-1-tabba@google.com>

From: Quentin Perret <qperret@google.com>

fix_host_ownership() walks the hypervisor's stage-1 page-table to
adjust the host's stage-2 accordingly. Any such adjustment that
requires cache maintenance operations depends on the per-CPU hyp
fixmap being present. However, fix_host_ownership() is currently
called before fix_hyp_pgtable_refcnt() and hyp_create_fixmap(), so
the fixmap does not yet exist when it runs.

This is benign today because the host stage-2 starts empty and no
CMOs are needed, but it becomes a latent crash as soon as
fix_host_ownership() is extended to operate on a non-empty
page-table.

Reorder the calls so that fix_hyp_pgtable_refcnt() and
hyp_create_fixmap() complete before fix_host_ownership() is invoked.

Fixes: 0d16d12eb26e ("KVM: arm64: Fix-up hyp stage-1 refcounts for all pages mapped at EL2")
Signed-off-by: Quentin Perret <qperret@google.com>
Signed-off-by: Fuad Tabba <tabba@google.com>
---
 arch/arm64/kvm/hyp/nvhe/setup.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index d8e5b563fd3d..d461981616d9 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -312,10 +312,6 @@ void __noreturn __pkvm_init_finalise(void)
 	};
 	pkvm_pgtable.mm_ops = &pkvm_pgtable_mm_ops;
 
-	ret = fix_host_ownership();
-	if (ret)
-		goto out;
-
 	ret = fix_hyp_pgtable_refcnt();
 	if (ret)
 		goto out;
@@ -324,6 +320,10 @@ void __noreturn __pkvm_init_finalise(void)
 	if (ret)
 		goto out;
 
+	ret = fix_host_ownership();
+	if (ret)
+		goto out;
+
 	ret = hyp_ffa_init(ffa_proxy_pages);
 	if (ret)
 		goto out;
-- 
2.54.0.rc2.544.gc7ae2d5bb8-goog



^ permalink raw reply related

* [PATCH RFC] iommu: Enable per-device SSID space for SVA
From: Joonwon Kang @ 2026-04-24  8:50 UTC (permalink / raw)
  To: will, robin.murphy, joro
  Cc: jgg, nicolinc, praan, kees, amhetre, Alexander.Grest, baolu.lu,
	smostafa, linux-arm-kernel, iommu, linux-kernel, Joonwon Kang

For SVA, the IOMMU core always allocates PASID from the global PASID
space. The use of this global PASID space comes from the limitation of
the ENQCMD instruction in Intel CPUs that it fetches its PASID operand
from IA32_PASID, which is per-task.

Due to this nature, SVA with ARM SMMU v3 has been found not working in
our environment when other modules/devices compete for PASID. The
environment looks as follows:

- The device is not a PCIe device.
- The device is to use SVA.
- The supported SSID/PASID space is very small for the device; only 1 to
  3 SSIDs are supported.
- There is a custom way of transmitting the SSID from the kernel to the
  device.

With this setup, when other modules have allocated all the PASIDs that
our device is expected to use from the global PASID space via APIs like
iommu_alloc_global_pasid() or iommu_sva_bind_device(), SVA binding to
our device fails due to the lack of available PASIDs.

Since SSID/PASID is supported per-SID in ARM SMMU v3, this commit
leverages the fact and lifts the use of the global PASID space if
possible. What it does includes:

- Introduce a new IOMMU capability IOMMU_CAP_PER_DEV_PASID_SPACE, which
  represents whether the IOMMU supports an independent PASID space per-
  device, not shared across devices. ARM SMMU v3 is the case.
- Open a new API iommu_attach_device_pasid_any() to allocate any
  available PASID and attach an IOMMU domain to it.
- Opt out the use of the global PASID space for SVA if the IOMMU has
  that capability, and use the new API to allocate a PASID in that case.

Signed-off-by: Joonwon Kang <joonwonkang@google.com>
---
v1: Request comments for this approach, other possible approaches and/or
  other aspects to consider more. Code is not sanitized and commits are
  not separated appropriately in this version.

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  2 +
 drivers/iommu/iommu-sva.c                   | 44 +++++++----
 drivers/iommu/iommu.c                       | 85 ++++++++++++++++++++-
 include/linux/iommu.h                       |  5 ++
 4 files changed, 121 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 4d00d796f078..3a700ab0b5c7 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2494,6 +2494,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
 		return true;
 	case IOMMU_CAP_DIRTY_TRACKING:
 		return arm_smmu_dbm_capable(master->smmu);
+	case IOMMU_CAP_PER_DEV_PASID_SPACE:
+		return true;
 	default:
 		return false;
 	}
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 07d64908a05f..637d8fd29cbf 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -21,6 +21,7 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
 {
 	struct iommu_mm_data *iommu_mm;
 	ioasid_t pasid;
+	const struct iommu_ops *ops = dev_iommu_ops(dev);
 
 	lockdep_assert_held(&iommu_sva_lock);
 
@@ -39,11 +40,18 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
 	if (!iommu_mm)
 		return ERR_PTR(-ENOMEM);
 
-	pasid = iommu_alloc_global_pasid(dev);
-	if (pasid == IOMMU_PASID_INVALID) {
-		kfree(iommu_mm);
-		return ERR_PTR(-ENOSPC);
+	if (ops->capable && ops->capable(dev, IOMMU_CAP_PER_DEV_PASID_SPACE)) {
+		pasid = IOMMU_NO_PASID;
+		iommu_mm->pasid_global = false;
+	} else {
+		pasid = iommu_alloc_global_pasid(dev);
+		if (pasid == IOMMU_PASID_INVALID) {
+			kfree(iommu_mm);
+			return ERR_PTR(-ENOSPC);
+		}
+		iommu_mm->pasid_global = true;
 	}
+
 	iommu_mm->pasid = pasid;
 	iommu_mm->mm = mm;
 	INIT_LIST_HEAD(&iommu_mm->sva_domains);
@@ -114,13 +122,15 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 		goto out_unlock;
 	}
 
-	/* Search for an existing domain. */
-	list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
-		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
-						&handle->handle);
-		if (!ret) {
-			domain->users++;
-			goto out;
+	if (iommu_mm->pasid != IOMMU_NO_PASID) {
+		/* Search for an existing domain. */
+		list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
+			ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
+							&handle->handle);
+			if (!ret) {
+				domain->users++;
+				goto out;
+			}
 		}
 	}
 
@@ -131,8 +141,13 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 		goto out_free_handle;
 	}
 
-	ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
-					&handle->handle);
+	if (iommu_mm->pasid != IOMMU_NO_PASID) {
+		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
+						&handle->handle);
+	} else {
+		ret = iommu_attach_device_pasid_any(domain, dev, &iommu_mm->pasid,
+						    &handle->handle);
+	}
 	if (ret)
 		goto out_free_domain;
 	domain->users = 1;
@@ -211,7 +226,8 @@ void mm_pasid_drop(struct mm_struct *mm)
 	if (!iommu_mm)
 		return;
 
-	iommu_free_global_pasid(iommu_mm->pasid);
+	if (iommu_mm->pasid_global)
+		iommu_free_global_pasid(iommu_mm->pasid);
 	kfree(iommu_mm);
 }
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 35db51780954..b882ecad7f57 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1061,7 +1061,7 @@ struct iommu_group *iommu_group_alloc(void)
 	mutex_init(&group->mutex);
 	INIT_LIST_HEAD(&group->devices);
 	INIT_LIST_HEAD(&group->entry);
-	xa_init(&group->pasid_array);
+	xa_init_flags(&group->pasid_array, XA_FLAGS_ALLOC);
 
 	ret = ida_alloc(&iommu_group_ida, GFP_KERNEL);
 	if (ret < 0) {
@@ -3619,6 +3619,89 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device_pasid);
 
+/**
+ * iommu_attach_device_pasid_any() - Allocate a pasid of device and attach a
+ * domain to it
+ * @domain: the iommu domain.
+ * @dev: the attached device.
+ * @pasid: pointer to the pasid of the device to be allocated.
+ * @handle: the attach handle.
+ *
+ * Caller should always provide a new handle to avoid race with the paths
+ * that have lockless reference to handle if it intends to pass a valid handle.
+ *
+ * Return: 0 on success, or an error.
+ */
+int iommu_attach_device_pasid_any(struct iommu_domain *domain,
+				  struct device *dev,
+				  ioasid_t *pasid,
+				  struct iommu_attach_handle *handle)
+{
+	/* Caller must be a probed driver on dev */
+	struct iommu_group *group = dev->iommu_group;
+	const struct iommu_ops *ops;
+	void *entry;
+	u32 new_pasid;
+	int ret;
+
+	if (!group)
+		return -ENODEV;
+
+	ops = dev_iommu_ops(dev);
+
+	if (!domain->ops->set_dev_pasid ||
+	    !ops->blocked_domain ||
+	    !ops->blocked_domain->ops->set_dev_pasid)
+		return -EOPNOTSUPP;
+
+	if (!domain_iommu_ops_compatible(ops, domain) || !pasid)
+		return -EINVAL;
+
+	mutex_lock(&group->mutex);
+
+	/*
+	 * This is a concurrent attach during a device reset. Reject it until
+	 * pci_dev_reset_iommu_done() attaches the device to group->domain.
+	 */
+	if (group->resetting_domain) {
+		ret = -EBUSY;
+		goto out_unlock;
+	}
+
+	entry = iommu_make_pasid_array_entry(domain, handle);
+
+	struct xa_limit limit = {
+		.min = IOMMU_FIRST_GLOBAL_PASID,
+		.max = dev->iommu->max_pasids - 1,
+	};
+
+	ret = xa_alloc(&group->pasid_array, &new_pasid, XA_ZERO_ENTRY, limit, GFP_KERNEL);
+	if (ret)
+		goto out_unlock;
+
+	ret = __iommu_set_group_pasid(domain, group, new_pasid, NULL);
+	if (ret) {
+		xa_release(&group->pasid_array, new_pasid);
+		goto out_unlock;
+	}
+
+	/*
+	 * The xa_insert() above reserved the memory, and the group->mutex is
+	 * held, this cannot fail. The new domain cannot be visible until the
+	 * operation succeeds as we cannot tolerate PRIs becoming concurrently
+	 * queued and then failing attach.
+	 */
+	WARN_ON(xa_is_err(xa_store(&group->pasid_array,
+				   new_pasid, entry, GFP_KERNEL)));
+
+	*pasid = new_pasid;
+
+out_unlock:
+	mutex_unlock(&group->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_attach_device_pasid_any);
+
 /**
  * iommu_replace_device_pasid - Replace the domain that a specific pasid
  *                              of the device is attached to
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 54b8b48c762e..1665f9fe1d8a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -271,6 +271,7 @@ enum iommu_cap {
 	 */
 	IOMMU_CAP_DEFERRED_FLUSH,
 	IOMMU_CAP_DIRTY_TRACKING,	/* IOMMU supports dirty tracking */
+	IOMMU_CAP_PER_DEV_PASID_SPACE,	/* IOMMU supports per-device PASID space */
 };
 
 /* These are the possible reserved region types */
@@ -1136,6 +1137,7 @@ struct iommu_sva {
 
 struct iommu_mm_data {
 	u32			pasid;
+	bool			pasid_global;
 	struct mm_struct	*mm;
 	struct list_head	sva_domains;
 	struct list_head	mm_list_elm;
@@ -1184,6 +1186,9 @@ void iommu_device_release_dma_owner(struct device *dev);
 int iommu_attach_device_pasid(struct iommu_domain *domain,
 			      struct device *dev, ioasid_t pasid,
 			      struct iommu_attach_handle *handle);
+int iommu_attach_device_pasid_any(struct iommu_domain *domain,
+				  struct device *dev, ioasid_t *pasid,
+				  struct iommu_attach_handle *handle);
 void iommu_detach_device_pasid(struct iommu_domain *domain,
 			       struct device *dev, ioasid_t pasid);
 ioasid_t iommu_alloc_global_pasid(struct device *dev);
-- 
2.54.0.545.g6539524ca2-goog



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox