Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 2/8] arm64, unwind: build kernel with sframe V3 info
From: Dylan Hatch @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Jens Remus
  Cc: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Heiko Carstens, Vasily Gorbik,
	Ilya Leoshkevich
In-Reply-To: <cc7f741c-41a0-4620-b5d5-3428aaa7648f@linux.ibm.com>

On Tue, Apr 14, 2026 at 5:43 AM Jens Remus <jremus@linux.ibm.com> wrote:
>
>
> Good catch!  Should we rather add the following in the series you are
> basing on, as there are already arch-specific unwind_user.h and
> unwind_user_sframe.h?
>
> F:      arch/*/include/asm/unwind*.h

Thanks for the suggestion, this works for me.

>
> On the other hand I wonder whether the arch-specific headers should
> remain maintained by the respective arch maintainers?  How is that
> handled in general?

I had the same question. My scan of MAINTAINERS shows both patterns
are present, so I defer to those who know more about this kind of
maintainership configuration.

>
> > diff --git a/arch/Kconfig b/arch/Kconfig
>
> > @@ -520,6 +520,13 @@ config SFRAME_VALIDATION
> >
> >         If unsure, say N.
> >
> > +config ARCH_SUPPORTS_SFRAME_UNWINDER
> > +     bool
> > +     help
> > +       An architecture can select this if it  enables the sframe (Simple
> > +       Frame) unwinder for unwinding kernel stack traces. It uses unwind
> > +       table that is directly generatedby toolchain based on DWARF CFI information.
>
> Nit: s/sframe/SFrame/
>
> > +
> >  config HAVE_PERF_REGS
> >       bool
> >       help
>
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>
> > @@ -112,6 +112,7 @@ config ARM64
> >       select ARCH_SUPPORTS_SCHED_SMT
> >       select ARCH_SUPPORTS_SCHED_CLUSTER
> >       select ARCH_SUPPORTS_SCHED_MC
> > +     select ARCH_SUPPORTS_SFRAME_UNWINDER
> >       select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
> >       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
> >       select ARCH_WANT_DEFAULT_BPF_JIT
>
> > diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
>
> > @@ -20,4 +20,17 @@ config ARM64_RELOC_TEST
> >       depends on m
> >       tristate "Relocation testing module"
> >
> > +config SFRAME_UNWINDER
>
> Why do you introduce this for arm64 (and debug) only?  If s390 were to
> add support (as replacement for s390 backchain), this would have to be
> moved or duplicated.  It would not suffice to enable
> ARCH_SUPPORTS_SFRAME_UNWINDER to also enable SFRAME_UNWINDER.

Makes sense, I'll look into introducing this as arch-generic.

>
> As mentioned in my feedback on the previous patch in this series:
> Would it make sense to align the naming to the existing
> HAVE_UNWIND_USER_SFRAME, for instance:
>
>   HAVE_UNWIND_KERNEL_SFRAME
>
> > +     bool "Sframe unwinder"
> > +     depends on AS_SFRAME3
> > +     depends on 64BIT
> > +     depends on ARCH_SUPPORTS_SFRAME_UNWINDER
> > +     select SFRAME_LOOKUP
> > +     help
> > +       This option enables the sframe (Simple Frame) unwinder for unwinding
> > +       kernel stack traces. It uses unwind table that is directly generated
> > +       by toolchain based on DWARF CFI information. In, practice this can
> > +       provide more reliable stacktrace results than unwinding with frame
> > +       pointers alone.
>
> Nit: s/sframe/SFrame/
>
> > +
> >  source "drivers/hwtracing/coresight/Kconfig"
>
> You are introducing two new Kconfig options (SFRAME_UNWINDER and
> ARCH_SUPPORTS_SFRAME_UNWINDER).  I wonder whether they could somehow be
> combined into a single new option.  Although I am not sure how an option
> can be both selectable and depending at the same time, so that the ARM64
> config could select it, but it would also depend on the above.

I don't think this is recommended, since the behavior of 'select'
appears to override a 'depends' requirement.

From Documentation/kbuild/kconfig-language.rst: "select should be used
with care. select will force a symbol to a value without visiting the
dependencies. By abusing select you are able to select a symbol FOO
even if FOO depends on BAR that is not set. In general use select only
for non-visible symbols (no prompts anywhere) and for symbols with no
dependencies. That will limit the usefulness but on the other hand
avoid the illegal configurations all over."

>
> > diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
>
> > @@ -491,6 +491,8 @@
> >               *(.rodata1)                                             \
> >       }                                                               \
> >                                                                       \
> > +     SFRAME                                                          \
> > +                                                                     \
> >       /* PCI quirks */                                                \
> >       .pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {        \
> >               BOUNDED_SECTION_PRE_LABEL(.pci_fixup_early,  _pci_fixups_early,  __start, __end) \
> > @@ -911,6 +913,19 @@
> >  #define TRACEDATA
> >  #endif
> >
> > +#ifdef CONFIG_SFRAME_UNWINDER
> > +#define SFRAME                                                       \
> > +     /* sframe */                                            \
> > +     .sframe : AT(ADDR(.sframe) - LOAD_OFFSET) {             \
> > +             __start_sframe_header = .;                      \
>
>                 __start_sframe[_section] = .;
>
> > +             KEEP(*(.sframe))                                \
> > +             KEEP(*(.init.sframe))                           \
> > +             __stop_sframe_header = .;                       \
>
>                 __stop_sframe[_section] = .;
>
> Unless I am missing something both are not the start/stop of the .sframe
> header (in the .sframe section) but the .sframe section itself (see also
> your subsequent "[PATCH v3 4/8] sframe: Provide PC lookup for vmlinux
> .sframe section." where you assign both to kernel_sfsec.sframe_start
> and kernel_sfsec.sframe_end.
>
> > +     }
> > +#else
> > +#define SFRAME
> > +#endif
> > +
> >  #ifdef CONFIG_PRINTK_INDEX
> >  #define PRINTK_INDEX                                                 \
> >       .printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) {         \
>
> Regards,
> Jens
> --
> Jens Remus
> Linux on Z Development (D3303)
> jremus@de.ibm.com / jremus@linux.ibm.com
>
> IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
> IBM Data Privacy Statement: https://www.ibm.com/privacy/
>

I'm working on a new version that I'm hoping to be able to send
sometime next week, which should address your other comments.

Thanks,
Dylan


^ permalink raw reply

* Re: [PATCH v0 07/15] mshv: Add ioctl support for MSHV-VFIO bridge device
From: Mukesh R @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Stanislav Kinsburskii
  Cc: linux-kernel, linux-hyperv, linux-arm-kernel, iommu, linux-pci,
	linux-arch, kys, haiyangz, wei.liu, decui, longli,
	catalin.marinas, will, tglx, mingo, bp, dave.hansen, hpa, joro,
	lpieralisi, kwilczynski, mani, robh, bhelgaas, arnd, nunodasneves,
	mhklinux, romank
In-Reply-To: <aW-pw7GlQdFv-lf5@skinsburskii.localdomain>

On 1/20/26 08:13, Stanislav Kinsburskii wrote:
> On Mon, Jan 19, 2026 at 10:42:22PM -0800, Mukesh R wrote:
>> From: Mukesh Rathor <mrathor@linux.microsoft.com>
>>
>> Add ioctl support for creating MSHV devices for a paritition. At
>> present only VFIO device types are supported, but more could be
>> added. At a high level, a partition ioctl to create device verifies
>> it is of type VFIO and does some setup for bridge code in mshv_vfio.c.
>> Adapted from KVM device ioctls.
>>
>> Credits: Original author: Wei Liu <wei.liu@kernel.org>
>> NB: Slightly modified from the original version.
>>
>> Signed-off-by: Mukesh Rathor <mrathor@linux.microsoft.com>
>> ---
>>   drivers/hv/mshv_root_main.c | 126 ++++++++++++++++++++++++++++++++++++
>>   1 file changed, 126 insertions(+)
>>
>> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
>> index 83c7bad269a0..27313419828d 100644
>> --- a/drivers/hv/mshv_root_main.c
>> +++ b/drivers/hv/mshv_root_main.c
>> @@ -1551,6 +1551,129 @@ mshv_partition_ioctl_initialize(struct mshv_partition *partition)
>>   	return ret;
>>   }
>>   
>> +static long mshv_device_attr_ioctl(struct mshv_device *mshv_dev, int cmd,
>> +				   ulong uarg)
>> +{
>> +	struct mshv_device_attr attr;
>> +	const struct mshv_device_ops *devops = mshv_dev->device_ops;
>> +
>> +	if (copy_from_user(&attr, (void __user *)uarg, sizeof(attr)))
>> +		return -EFAULT;
>> +
>> +	switch (cmd) {
>> +	case MSHV_SET_DEVICE_ATTR:
>> +		if (devops->device_set_attr)
>> +			return devops->device_set_attr(mshv_dev, &attr);
>> +		break;
>> +	case MSHV_HAS_DEVICE_ATTR:
>> +		if (devops->device_has_attr)
>> +			return devops->device_has_attr(mshv_dev, &attr);
>> +		break;
>> +	}
>> +
>> +	return -EPERM;
>> +}
>> +
>> +static long mshv_device_fop_ioctl(struct file *filp, unsigned int cmd,
>> +				  ulong uarg)
>> +{
>> +	struct mshv_device *mshv_dev = filp->private_data;
>> +
>> +	switch (cmd) {
>> +	case MSHV_SET_DEVICE_ATTR:
>> +	case MSHV_HAS_DEVICE_ATTR:
>> +		return mshv_device_attr_ioctl(mshv_dev, cmd, uarg);
>> +	}
>> +
>> +	return -ENOTTY;
>> +}
>> +
>> +static int mshv_device_fop_release(struct inode *inode, struct file *filp)
>> +{
>> +	struct mshv_device *mshv_dev = filp->private_data;
>> +	struct mshv_partition *partition = mshv_dev->device_pt;
>> +
>> +	if (mshv_dev->device_ops->device_release) {
>> +		mutex_lock(&partition->pt_mutex);
>> +		hlist_del(&mshv_dev->device_ptnode);
>> +		mshv_dev->device_ops->device_release(mshv_dev);
>> +		mutex_unlock(&partition->pt_mutex);
>> +	}
>> +
>> +	mshv_partition_put(partition);
>> +	return 0;
>> +}
>> +
>> +static const struct file_operations mshv_device_fops = {
>> +	.owner = THIS_MODULE,
>> +	.unlocked_ioctl = mshv_device_fop_ioctl,
>> +	.release = mshv_device_fop_release,
>> +};
>> +
>> +long mshv_partition_ioctl_create_device(struct mshv_partition *partition,
>> +					void __user *uarg)
>> +{
>> +	long rc;
>> +	struct mshv_create_device devargk;
>> +	struct mshv_device *mshv_dev;
>> +	const struct mshv_device_ops *vfio_ops;
>> +	int type;
>> +
>> +	if (copy_from_user(&devargk, uarg, sizeof(devargk))) {
>> +		rc = -EFAULT;
>> +		goto out;
>> +	}
>> +
>> +	/* At present, only VFIO is supported */
>> +	if (devargk.type != MSHV_DEV_TYPE_VFIO) {
>> +		rc = -ENODEV;
>> +		goto out;
>> +	}
>> +
>> +	if (devargk.flags & MSHV_CREATE_DEVICE_TEST) {
>> +		rc = 0;
>> +		goto out;
>> +	}
>> +
>> +	mshv_dev = kzalloc(sizeof(*mshv_dev), GFP_KERNEL_ACCOUNT);
>> +	if (mshv_dev == NULL) {
>> +		rc = -ENOMEM;
>> +		goto out;
>> +	}
>> +
>> +	vfio_ops = &mshv_vfio_device_ops;
>> +	mshv_dev->device_ops = vfio_ops;
>> +	mshv_dev->device_pt = partition;
>> +
>> +	rc = vfio_ops->device_create(mshv_dev, type);
>> +	if (rc < 0) {
>> +		kfree(mshv_dev);
>> +		goto out;
>> +	}
>> +
>> +	hlist_add_head(&mshv_dev->device_ptnode, &partition->pt_devices);
>> +
>> +	mshv_partition_get(partition);
>> +	rc = anon_inode_getfd(vfio_ops->device_name, &mshv_device_fops,
>> +			      mshv_dev, O_RDWR | O_CLOEXEC);
>> +	if (rc < 0) {
>> +		mshv_partition_put(partition);
>> +		hlist_del(&mshv_dev->device_ptnode);
>> +		vfio_ops->device_release(mshv_dev);
>> +		goto out;
>> +	}
>> +
>> +	devargk.fd = rc;
>> +	rc = 0;
>> +
>> +	if (copy_to_user(uarg, &devargk, sizeof(devargk))) {
> 
> Shouldn't the partition be put here?

No. anon_inode_getfd was successful and so it installed the fd already..
As a result the cleanup will happen in the file op release.

Thanks,
-Mukesh

> Thanks,
> Stanislav
> 
>> +		rc = -EFAULT;
>> +		goto out;
>> +	}
>> +out:
>> +	return rc;
>> +}
>> +
>>   static long
>>   mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
>>   {
>> @@ -1587,6 +1710,9 @@ mshv_partition_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
>>   	case MSHV_ROOT_HVCALL:
>>   		ret = mshv_ioctl_passthru_hvcall(partition, true, uarg);
>>   		break;
>> +	case MSHV_CREATE_DEVICE:
>> +		ret = mshv_partition_ioctl_create_device(partition, uarg);
>> +		break;
>>   	default:
>>   		ret = -ENOTTY;
>>   	}
>> -- 
>> 2.51.2.vfs.0.1
>>



^ permalink raw reply

* [PATCH v2 01/19] crypto: add Kconfig options for standalone crypto module
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules
In-Reply-To: <20260418002032.2877-1-wanjay@amazon.com>

Add Kconfig option `CRYPTO_FIPS140_EXTMOD` to enable standalone crypto
module support that can override built-in cryptographic implementations.

Currently supports X86_64 and ARM64 architectures and requires CRYPTO
and MODULES to be enabled.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Kconfig         |  1 +
 crypto/fips140/Kconfig | 15 +++++++++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 crypto/fips140/Kconfig

diff --git a/crypto/Kconfig b/crypto/Kconfig
index b54a1bef6adef..d792ff01298b7 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1387,6 +1387,7 @@ endif
 endif
 
 source "drivers/crypto/Kconfig"
+source "crypto/fips140/Kconfig"
 source "crypto/asymmetric_keys/Kconfig"
 source "certs/Kconfig"
 source "crypto/krb5/Kconfig"
diff --git a/crypto/fips140/Kconfig b/crypto/fips140/Kconfig
new file mode 100644
index 0000000000000..0665e94b9fe05
--- /dev/null
+++ b/crypto/fips140/Kconfig
@@ -0,0 +1,15 @@
+config CRYPTO_FIPS140_EXTMOD
+	bool "FIPS 140 compliant algorithms as a kernel module"
+	depends on CRYPTO && (X86_64 || ARM64) && MODULES
+	select CRYPTO_FIPS
+	help
+	  This option enables building a kernel module that contains
+	  copies of crypto algorithms that are built in a way that
+	  complies with the FIPS 140 standard.
+
+	  The module registers the algorithms it contains with the
+	  kernel crypto API, and the kernel crypto API's FIPS 140 mode
+	  can be enabled to restrict crypto algorithm usage to only
+	  those provided by this module.
+
+	  If unsure, say N.
-- 
2.47.3



^ permalink raw reply related

* [PATCH v2 00/19] crypto: Standalone crypto module
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules

This patch series is V2 of the previously submitted standalone crypto kernel module feature patch series.

Major update:
V2 is an improved implementation that reduces 3,000 lines of code (~70%) (shrinking patch numbers from ~160 (V1) down to ~20 (V2)), making the patch set significantly less intrusive to the mainline kernel source tree. (For details on how this reduction is achieved, see Section 4 & 7.)
Therefore, compared to the V1 submission where it was organized into 4 patch series, the entire feature is now shipped in one patch series.

Other updates:
1. Update cover letter: Elaborate on how this feature can be used and benefit downstream distros in practice (Section 6). It also clarifies that a stable kernel internal API is not required.
2. Rebase to latest mainline (up to "Merge tag 'v7.1-rc-part1-smbdirect-fixes' of git://git.samba.org/ksmbd").

This feature has been officially launched on the AWS platform, starting from Amazon Linux Kernel 6.18 and later.
The full source code is available at https://github.com/amazonlinux/linux/tree/fips-kernel-module.
Details on this feature and what each patch covers can be found below.

## 1. Introduction

Amazon Linux has released a new kernel feature that converts the previously built-in kernel crypto subsystem into a standalone kernel module. This module becomes the carrier of the kernel crypto subsystem and can be loaded at early boot to provide the same functionality as the original built-in crypto. The primary motivation for this modularization is to streamline Federal Information Processing Standards (FIPS) validation, a critical cryptographic certification for cloud computing users doing business with the U.S. government. This feature is publicly available on the AWS platform.
 
In a bit more detail, previously, FIPS certification was tied to the entire kernel image, meaning non-crypto updates could potentially invalidate certification. With this feature, FIPS certification is tied only to the crypto module. Therefore, once the module is certified, loading this certified module on newer kernels automatically makes those kernels FIPS-certified. As a result, this approach can save re-certification costs and 12-18 months of waiting time by reducing the need for repeated FIPS re-certification cycles.

This document provides technical details on how this feature is designed and implemented for users or developers who are interested in developing upon it, and is organized as follows:
- Section 2 - Getting Started: Quick start on how to enable the feature
- Section 3 - Workflow Overview: Changes this feature brings to build and runtime
- Section 4 - Design Implementation Details: Technical deep-dive into each component
- Section 5 - Customizing and Extending Crypto Module: How to select crypto to be included and extend to new crypto/architectures
- Section 6 - Reusing a Certified Module in Practice: Different reuse and maintenance strategies and their tradeoffs
- Section 7 - Related Work and Comparison
- Section 8 - Summary

## 2. Getting Started

This section provides a quick start guide for developers on how to enable, compile and use the standalone cryptography module feature.

### 2.1 Basic Configuration

The feature is controlled by a single configuration option:
```
CONFIG_CRYPTO_FIPS140_EXTMOD=y
```
What it does: When enabled, automatically redirects a set of cryptographic algorithms from the main kernel into a standalone module `crypto/fips140/fips140.ko`. The cryptographic algorithms that are redirected need to satisfy all the following conditions, otherwise the cryptography will remain in its original form:
1. Must be configured as built-in (i.e., `CONFIG_CRYPTO_*=y`). This means cryptography already configured as modular (i.e., `CONFIG_CRYPTO_*=m`) are not redirected as they are already modularized.
2. Must be among a list, which can be customized by developers as described in Section 5.

When disabled, the kernel behaves as before.

### 2.2 Build Process

Once `CONFIG_CRYPTO_FIPS140_EXTMOD=y` is set, no additional steps are required. The standalone module will be built automatically as part of the standard kernel build process:
```
make -j$(nproc)
# or
make vmlinux
```
**What happens automatically (No user action required):**
1. Build the module as `crypto/fips140/fips140.ko`
2. The cryptography module will be loaded at boot time
3. All kernel cryptographic services will provide the same functionality as before (i.e., prior to introducing this new feature) once boot completes.

### 2.3 Advanced Configuration Options

**Using External Cryptography Module:**
```
CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE=y
```
By default, `CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE` is not set, meaning the freshly built cryptography module is used. Otherwise, the pre-built standalone cryptography module from `fips140_build/crypto/fips140/fips140.ko` and modular cryptography such as `fips140_build/crypto/aes.ko` (need to manually place pre-built modules in these locations before the build) are included in kernel packaging (e.g., during `make modules_install`) and are used at later boot time.

**Dual Version Support:**
```
CONFIG_CRYPTO_FIPS140_DUAL_VERSION=y
```
Encapsulate two versions of `fips140.ko` into kernel: one is freshly built for non-FIPS mode usage, another is pre-built specified by `fips140_build/crypto/fips140/fips140.ko` for FIPS mode usage. The appropriate version is selected and loaded at boot time based on boot time FIPS mode status.

### 2.4 Verification

To verify the feature is working, after install and boot with the new kernel:
```
# Check if fips140.ko module is loaded
lsmod | grep fips140
# Check if crypto algorithms are served by the fips140 module
cat /proc/crypto | grep module | grep fips140
```

## 3. Workflow Overview

This section provides an overview without delving into deep technical details of the changes the standalone cryptography module feature introduces. When this feature is enabled, it introduces changes to both the kernel build and booting process. 

3.1 Build-Time Changes

Kernel cryptography subsystem consists of both cryptography management infrastructure (e.g., `crypto/api.c`, `crypto/algapi.c`, etc), along with hundreds of different cryptography algorithms (e.g., `crypto/arc4.c`).

**Traditional Build Process:**
Traditionally, cryptography management infrastructure are always built-in to the kernel, while cryptographic algorithms can be configured to be built either as built-in (`CONFIG_CRYPTO_*=y`) or as separate modular (`CONFIG_CRYPTO_*=m`) `.ko` file depending on kernel configuration:
As a result, the builtin cryptography management infrastructure and cryptographic algorithms are statically linked into the kernel binary:
```
cryptographic algorithms source files → compiled as .o objfiles →  linked into vmlinux → single kernel binary
```
**With Standalone Cryptography Module:**
This feature automatically transforms the builtin cryptographic components into a standalone cryptography module, `fips140.ko`. To do so, it develops a new kernel build rule `crypto-objs-$(CONFIG_CRYPTO_*)` such that, once this build rule is applied to a cryptographic algorithm, such cryptographic algorithm will be automatically collected into the cryptography module if it is configured as built-in (i.e, `CONFIG_CRYPTO_*=y`), for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
```
Such build change allows the modularization transformation to only affect selected cryptographic algorithms (i.e, where the `crypto-objs-$(CONFIG_CRYPTO_*`) is applied).

Then, after the `fips140.ko` is generated, it will be embedded back into main kernel vmlinux as a replacement part. The purpose of this embedding, instead of traditionally putting the `fips140.ko` into filesystem, is a preparation to allow the module to be loaded early enough even before the filesystem is ready.

The new build process is illustrated below.
```
cryptographic algorithms source files → compiled as .o objfiles → automatically collected and linked into fips140.ko → embedded fips140.ko into vmlinux as a replaceable binary
```

### 3.2 Runtime Changes

**Traditional Boot Process:**
The kernel initializes the cryptographic subsystem early during boot, executing each cryptographic initialization routine accordingly. These initialization routines may depend on other cryptographic components or other kernel subsystems, so their invocation follows a well-defined execution order to ensure they are initialized before their first use.
```
kernel starts → cryptography subsystem initialization → cryptography subsystem available → other components use cryptography
```
**With Standalone Cryptography Module:**
At the start of kernel boot, compared to a regular kernel, the first major change introduced by this feature is that no cryptography services are initially available — since the entire cryptography subsystem has been decoupled from the main kernel.
To ensure that the cryptography subsystem becomes available early enough (before the first kernel component that requires cryptography services), the standalone cryptography kernel module must be loaded at a very early stage, even before the filesystem becomes available.

However, the regular module loading mechanism relies on placing kernel modules in the filesystem and loading them from there, which creates a chicken-and-egg problem — the cryptography module cannot be loaded until the filesystem is ready, yet some kernel components may require cryptography services even before that point.

To address this, the second change introduced by this feature is that the cryptography kernel module is loaded directly from memory, leveraging the earlier compilation changes that embed the module binary into the main kernel image. Afterward, the feature includes a “plug-in” mechanism that connects the decoupled cryptography subsystem back to the main kernel, ensuring that kernel cryptography users can correctly locate and invoke the cryptography routine entry points.

Finally, to ensure proper initialization, the feature guarantees that all cryptography algorithms and the cryptography management infra execute their initialization routines in the exact same order as they would if they were built-in.

The process described above is illustrated below.
```
kernel starts → no cryptography available → load fips140.ko from memory → plug cryptography back to kernel → module initialization → cryptographic services available → other components use cryptography
```

## 4. Design Implementation Details

While the earlier sections provide a holistic view of how this feature shapes the kernel, this section provides deeper design details on how these functionalities are realized. There are three key design components:
1. A specialized compile rule that automatically compiles and collects all built-in cryptographic algorithm object files to generate the final module binary under arbitrary kernel configurations, and then embeds the generated binary into the main kernel image for early loading.
2. A mechanism to convert interactions between the cryptography subsystem and the main kernel into a pluggable interface.
3. A module loading and initialization process that ensures the cryptography subsystem is properly initialized as if it were built-in.

### 4.1. Specialized Compilation System

**Automatic Collection and Linking of Built-in Cryptographic Algorithm Objects:**
The first step in generating the `fips140.ko` module is to compile and collect built-in cryptographic components (i.e., those specified by `CONFIG_CRYPTO_*=y`).
Traditionally, the existing module build process requires all module components (e.g., source files) to reside in a single directory. However, this approach is not suitable for our case, where hundreds of cryptographic algorithm source files are scattered across multiple directories.

A naïve approach would be to create a separate Makefile that duplicates the original build rules with adjusted paths.
However, this method is not scalable due to the large number of cryptographic build rules, many of which are highly customized and can vary under different Kconfig settings, making such a separate Makefile even more complex.
Moreover, this approach cannot ensure that built-in cryptographic algorithms are completely removed from the main kernel, which would result in redundant cryptographic code being included in both the kernel and the module.

To tackle this challenge, we automated the object collection and linking process by introducing special build logic for the kernel cryptography subsystem.
Specifically, to automatically collect cryptography object files while preserving their original compilation settings (such as flags, headers, and paths), we introduced a new compilation rule:
```
crypto-objs-y += *.o
```
This replaces the original `obj-y += *.o` rule in cryptography Makefiles later, for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \
    asymmetric_type.o \
    restrict.o \
    signature.o
```
in the cryptography subsystem Makefiles, allowing most of the existing Makefile logic to be reused.
As a result, when the standalone cryptography module feature is enabled, any cryptographic algorithm configured as built-in (for example, `crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o` where `CONFIG_ASYMMETRIC_KEY_TYPE=y`) will be automatically collected and linked into a single final object binary, `fips140.o`.
During this process, a special compilation flag (`-DFIPS_MODULE=1`) is applied to instruct each object file to be compiled in a module-specific manner. This flag will later be used to generate the pluggable interface on both the main kernel side and the module side from the same source code.

The implementation details are as follows: it follows a similar methodology used by the `obj-y` collection process for building `vmlinux.o`. The `crypto-objs-y` rule is placed in `scripts/Makefile.build`, which is executed by each directory Makefile to collect the corresponding crypto object files. Each directory then creates a `crypto-module.a` archive that contains all `crypto-objs-y += <object>.o` files under that directory. In the parent directories, these `crypto-module.a` archives are recursively included into the parent’s own `crypto-module.a`, and this process continues upward until the final `fips140.o` is generated.

**A Separate Module Generation Pipeline for Building the Final Kernel Module from Linked Cryptographic Algorithm Object:**
With the linked cryptographic algorithm object (i.e., `fips140.o`), the next step is to generate the final kernel module, `fips140.ko`.

A direct approach would be to inject the `fips140.ko` module build into the existing modules generation pipeline (i.e., `make modules`) by providing our pre-generated `fips140.o`. However, we choose not to do this because it would create a circular make rule dependency (which is invalid in Makefiles and causes build failures), resulting in mutual dependencies between the modules and vmlinux targets (i.e., `modules:vmlinux` and `vmlinux:modules` at the same time).
This happens for the following reasons:
1. Since we will later embed `fips140.ko` into the final kernel image (as described in the next section), we must make vmlinux depend on `fips140.ko`. In other words: `vmlinux: fips140.ko`.
2. When the kernel is built with `CONFIG_DEBUG_INFO_BTF_MODULES=y`, it requires: modules: vmlinux. This is because `CONFIG_DEBUG_INFO_BTF_MODULES=y` takes vmlinux as input to generate BTF info for the module, and inserts such info into the `.ko` module by default.
3. If we choose to inject `fips140.ko` into make modules, this would create a make rule dependency: `fips140.ko: modules`. Combined with items 1 and 2, this eventually creates an invalid circular dependency between vmlinux and modules.

Due to these reasons, the design choice is to use a separate make pipeline (defined as `fips140-ready` in the Makefile). This new pipeline reuses the same module generation scripts used by make modules but adds additional logic in `scripts/Makefile.{modfinal|modinst|modpost}` and `scripts/mod/modpost.c` to handle module symbol generation and verification correctly. 

**A Seamless Process That Embeds the Generated Binary Into the Main Kernel Image for Early Loading:**
As mentioned earlier, in order to load the standalone cryptography module early in the boot process—before the filesystem is ready—the module binary must be embedded into the final kernel image (i.e., vmlinux) so that it can be loaded directly from memory.
We intend for this embedding process to be completely seamless and automatically triggered whenever vmlinux is built (i.e., during `make vmlinux`).

To achieve this, the feature adds a Make dependency rule so that vmlinux depends on `fips140.ko`.
It also modifies the vmlinux link rules (i.e., `arch/<arch>/kernel/vmlinux.lds.S`, `scripts/Makefile.vmlinux`, and `scripts/link-vmlinux.sh`) so that the generated module binary is finally combined with `vmlinux.o`.

In addition, we allow multiple cryptography module binary versions (for example, a certified cryptography binary and a latest, up-to-date but uncertified one) to be embedded into the main kernel image to serve different user needs. This design allows regular (non-FIPS) users to benefit from the latest cryptographic updates, while FIPS-mode users continue to use the certified cryptography module.

To support this, we introduce an optional configuration, `CONFIG_CRYPTO_FIPS140_DUAL_VERSION`. When enabled, this option allows two cryptography module versions to be embedded within a single kernel build and ensures that the appropriate module is selected and loaded at boot time based on the system’s FIPS mode status.

### 4.2. Pluggable Interface Between the Built-in Cryptography Subsystem and the Main Kernel

Although the module binary (`fips140.ko`) has been embedded into the final kernel image (`vmlinux`) as described in the previous section, it is not linked to the kernel in any way. This is because `fips140.ko` is embedded in a data-only manner, so the main kernel cannot directly call any functions or access any data defined in the module binary. Since the main kernel and modules can only interact through exported symbols (i.e., via `EXPORT_SYMBOL()`), this also applies to the crypto kernel module — the main kernel can only interact with the crypto functions and variables defined in the crypto module through exported symbols, meaning these functions and variables must also have their symbols exported in the module after they are moved from the main kernel to the module.

However, simply making these crypto symbols symbol-exported in the module without additional handling would cause the kernel to fail to compile. This is because the existing kernel module symbol resolution mechanism is essentially one-way: it supports symbols defined in the main kernel and referenced by kernel modules. However, it does not support the reverse case — symbols defined in a kernel module but used by the main kernel — which is exactly the crypto module case, as there are many crypto users still residing in the main kernel. The reason is that compilation of the main kernel requires all symbol addresses to be known to achieve a successful linking phase.

To address this, we introduce a pluggable interface to support this reverse-direction symbol resolution between crypto symbols defined in the module and referenced by the main kernel, by placing **address placeholders** at all crypto usage points in the main kernel. These address placeholders are initially set to NULL during compilation to provide a concrete address that satisfies the linking phase. Then, during runtime, once the cryptography kernel module is loaded, these placeholders are updated to the correct addresses before their first use in the main kernel. In the rest of this section, we first introduce this pluggable interface mechanism, and then explain how to apply it to the built-in cryptographic algorithms and variables.

**The Pluggable Interface Mechanism:**
There are two types of address holders used to achieve this pluggable interface:
- Function addresses (the majority): We use a trampoline to redirect the original jump instruction to another location whose target destination is held by the value of a function pointer. To avoid additional security concerns, such as the function pointer being arbitrarily modified, these function pointers are made `__ro_after_init` to ensure they cannot be modified after kernel init. We implement this function-address placeholder as the `DEFINE_CRYPTO_FN_REDIRECT()` wrapper.
- Variable addresses (the remaining smaller portion): For these, we use a pointer of the corresponding data type. We implement this address placeholder as the `DECLARE_CRYPTO_VAR()` and `DEFINE_CRYPTO_API_STUB()` wrappers:

These wrappers are applied to each symbol-exported (i.e., `EXPORT_SYMBOL()`) cryptographic function and variable (details on how to apply them are described later). Once applied, the wrappers are compiled differently for the main kernel and for the built-in cryptographic algorithm source code—acting as the “outlet” and the “plug,” respectively—using different compilation flags (`-DFIPS_MODULE`) introduced by our customized build rules described earlier.

As a result, the kernel can successfully compile even when the built-in cryptographic algorithms are removed, thanks to these address placeholders. At boot time, the placeholders initially hold NULL, but since no cryptography users exist at that stage, the kernel can still start booting correctly. After the cryptography module is loaded, the placeholders are dynamically updated to the correct addresses later (by `do_crypto_var()` and `do_crypto_fn()`, described in a later section).

**Applying the Pluggable Interface Mechanism to Cryptographic Algorithms:**

To apply these pluggable interface wrappers to a cryptographic algorithm and make them take effect, we follow the steps below (using `crypto/asymmetric_keys/asymmetric_type.c` as an example):
1. **Apply `crypto-objs-y` compile rule to the cryptographic algorithm:**
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \
    asymmetric_type.o \
    restrict.o \
    signature.o
```
2. **Locate the communication point between the cryptographic algorithm and the main kernel:**

The cryptography subsystem is designed such that most interactions between the main kernel and cryptographic algorithms occur through exported symbols using `EXPORT_SYMBOL()` wrappers.
This kernel design exists because most cryptographic algorithm implementations must support both built-in and modular modes. 

Consequently, the cryptographic functions and variables exported by `EXPORT_SYMBOL()` are a well-defined and identifiable interface between the cryptography subsystem and the main kernel: 
```
// in crypto/asymmetric_keys/asymmetric_type.c 
//Exported cryptographic function:
bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
                const struct asymmetric_key_id *kid2) {...}
EXPORT_SYMBOL_GPL(asymmetric_key_id_same); 
//Exported cryptographic variable:
struct key_type key_type_asymmetric = {...};
EXPORT_SYMBOL_GPL(key_type_asymmetric); 
```

3. **Redirect crypto symbol references in the main kernel to address placeholders:**

With the placeholders in place, the remaining problem is directing the main kernel to use them rather than the original symbols. Since all crypto users must include the corresponding header files to obtain function and variable declarations, the headers are a natural place to perform this redirection. Each declaration is transformed using a macro that hooks it to the corresponding placeholder.

For exported variable symbols (a small number, ~10 symbols), their declaration in the header file is replaced with the `DECLARE_CRYPTO_VAR()` wrapper to redirect variable access from a concrete address to a placeholder:
```
// in include/keys/asymmetric-type.h
// for exported cryptographic variables:
- struct key_type key_type_asymmetric;
+ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
+ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
+ #endif 
```
By doing so, we can automatically force all cryptography users to go through the placeholders, because those users already include the same header file.
The wrapper also takes the cryptographic algorithm Kconfig symbol as a parameter, so that when a cryptographic algorithm is built as a module (for example, `CONFIG_ASYMMETRIC_KEY_TYPE=m`), the original function declarations remain unchanged and are not affected.

For exported function symbols (the majority, ~hundreds), a similar approach could be taken, but instead we use an automated method to redirect function address usage to placeholders during the kernel compilation process. This makes the crypto module implementation less intrusive to the kernel source tree, as no header file modifications are needed. To achieve this, a linker option `--wrap=<symbols-to-redirect>` is leveraged to rename all uses of crypto functions in the main kernel to dedicated trampolines that act as address placeholders. As a consequence, all references to crypto function symbols are automatically redirected to the address placeholders, avoiding mass intrusive changes to the mainline kernel source tree.

4. **Add the address-placeholder definition wrappers into a dedicated file `fips140-var-redirect.c`:**

After redirecting crypto users to use address placeholders, we also need to add the definitions of those address placeholders.

For exported variable symbols (a small number, ~10 symbols), add the placeholder definition wrapper `DEFINE_CRYPTO_VAR_STUB` to a dedicated file `fips140-var-redirect.c`.
```
// in crypto/fips140/fips140-var-redirect.c
// for exported cryptographic variables:
+ #undef key_type_asymmetric
+ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
+ #endif
```
This file will be compiled separately and acts as both the “outlet” and the “plug” for the main kernel and the cryptography module, respectively.

For exported function symbols (the majority, ~hundreds), a similar wrapper `DEFINE_CRYPTO_FN_REDIRECT()` is used, but again, the application of this wrapper is automated, so there is no need to manually apply it. Instead, it is generated automatically by the script `crypto/fips140/gen-fips140-fn-redirect.sh` on every kernel build.

We apply the above steps to both architecture-independent and architecture-specific cryptographic algorithms.

### 4.3. Initialization Synchronization

To ensure the embedded `fips140.ko` module binary provides the same cryptography functionality as the regular kernel, the kernel needs:
1. A module loader to load the module binary directly from memory,
2. A mechanism to plug the module back into the kernel by updating the address placeholders, and
3. Correct cryptography subsystem initialization, as if the cryptographic algorithms were still built-in.

**Directly Load Module Binary from Memory:**
Regular modules are loaded from the filesystem and undergo signature verification on the module binary, which relies on cryptographic operations. However, since we have already fully decoupled the cryptography subsystem, we must skip this step for this `fips140.ko` module.
To achieve this, we add a new loader function `load_crypto_module_mem()` that can load the module binary directly from memory at the designed address without checking the signature. Since the module binary is embedded into main kernel in an ELF section, as specified in the linker script:
```
// in arch/<arch>/kernel/vmlinux.lds.S
    .fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
        . = ALIGN(8);
        _binary_fips140_ko_start = .;
        KEEP(*(.fips140_module_data))
        _binary_fips140_ko_end = .;
    }
```
Therefore, the runtime memory address of the module can be accessed directly by the module loader to invoke the new loader function `load_crypto_module_mem()`.

**Plug Back the Module by Updating Address Placeholder Values:**
To update the address placeholders in the main kernel to the correct addresses matching the loaded module, after compilation the placeholder values are placed into dedicated key-value data structures, which reside in ELF sections `__crypto_fn_keys` and `__crypto_var_keys`.
This can be seen from the definition of the placeholder's key-value data structure:
```
#define __CRYPTO_FN_KEY(sym)					\
	extern void *__fips140_fn_ptr_##sym;			\
	static struct _crypto_fn_key __##sym##_fn_key		\
		__used						\
		__section("__crypto_fn_keys")			\ // Place in a dedicated ELF Section
		__aligned(__alignof__(struct _crypto_fn_key)) = {	\
		.ptr = (void **)&__fips140_fn_ptr_##sym,		\
		.func = (void *)&sym,				\
	};

#define DEFINE_CRYPTO_VAR_STUB(name) \
    static struct crypto_var_key __crypto_##name##_var_key \
        __used \
        __section("__crypto_var_keys") \ // Place in a dedicated ELF Section
        __aligned(__alignof__(struct crypto_var_key)) = \
    { \
        .ptr = &CRYPTO_VAR_NAME(name), \
        .var = (void*)&name, \
    };
```
The purpose of doing this is to allow the main kernel to quickly locate the placeholders and update them to the correct addresses. The update functions are defined as `do_crypto_var()` and `do_crypto_fn()`, which are executed at module load.

As a result, all cryptography users in the main kernel can now call the cryptographic functions as if they were built-in.

**Initialize Cryptography Subsystem as if it Were Built-in:**
Cryptographic components must be properly initialized before use, and this initialization is typically achieved through dedicated initialization functions (e.g., `module_init(crypto_init_func)` or `late_initcall(crypto_init_func)`). Traditionally, these init functions are executed automatically as part of the kernel boot phase. However, now that they are moved to a crypto module, there needs to be a way to collect and execute them.

To collect these init functions, the init wrappers (e.g., `module_init()` and `late_initcall`) are modified to automatically place the wrapped crypto init function into a dedicated list in the crypto module, for example:
```
// in include/linux/module.h
#define subsys_initcall(fn) \
	static initcall_t __used __section(".fips_initcall0") \ // a dedicated list
		__fips_##fn = fn;

#define module_init(initfn) \
	static initcall_t __used __section(".fips_initcall1") \ // a dedicated list
		__fips_##initfn = initfn;
```
By doing so, all init functions are now aggregated for execution by `run_initcalls()` at module load.

Besides collecting these crypto init functions, rather than simply executing them, another key consideration is that their execution order often has strict requirements. In other words, for these collected crypto init functions, we must ensure that their initialization order is preserved as before because failure to follow the correct order can result in kernel panic.

To address this, we introduce a synchronization mechanism between the main kernel and the module to ensure all cryptographic algorithms are executed in the correct kernel boot phase. In more details, we spawn the module initialization process `fips_loader_init()` as an async thread `fips140_sync_thread()`, in which we call `run_initcalls()` to execute the initialization calls of each cryptographic algorithm.
Then, we introduce synchronization helpers such as `wait_until_fips140_level_sync(int level)` to ensure the initialization order of all cryptographic algorithms is synchronized with the main kernel.

## 5. Customization and Extension of Cryptography Module

This section describes how developers can customize which cryptographic algorithms are included in the standalone cryptography module, as well as extend this feature to other cryptographic algorithms or hardware architectures.

### 5.1. Cryptography Selection Mechanism

The feature automatically includes cryptographic algorithms that meet specific criteria:
1. **Built-in Configuration**: Only cryptographic algorithms configured as `CONFIG_CRYPTO_*=y` are candidates for inclusion
2. **Explicit Inclusion**: Cryptographic algorithms must be explicitly converted using the `crypto-objs-$(CONFIG__CRYPTO_*`) build rule

### 5.2. Extend Support to New Cryptographic Algorithms

To extend support to a new cryptographic algorithm in the standalone module, follow these steps:

**Step 1: Update the Makefile**
```
# in crypto/[algorithm]/Makefile
- obj-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
+ crypto-objs-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
```
For Architecture-Specific Cryptographic Algorithms:
- Apply the `crypto-objs-` rule in the appropriate `arch/*/crypto/Makefile`

**Step 2: Add Pluggable Interface Support**
If the cryptographic algorithm has symbol-exported variables via `EXPORT_SYMBOL()`, add the pluggable interface wrappers. There is no need to manually apply wrappers for symbol-exported functions:
```
// Example: in include/keys/asymmetric-type.h
// for exported cryptographic variables:
- struct key_type key_type_asymmetric;
+ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
+ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
+ #endif 
```
Then, add the corresponding stubs in `crypto/fips140/fips140-var-redirect.c`:
```
+ #undef key_type_asymmetric
+ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
+ #endif
```
For Architecture-Specific Cryptographic Algorithms:
- Include architecture-specific stubs in `arch/*/crypto/fips140/fips140-var-redirect.c`:

### 5.3. Architecture-Specific Extensions

**Extending to New Architectures:**
Currently supported architectures are x86_64 and ARM64. To extend this feature to additional architectures:
1. **Update Linker Scripts**: Add ELF sections in `arch/[new-arch]/kernel/vmlinux.lds.S`:
```
.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
    . = ALIGN(8);
    _binary_fips140_ko_start = .;
    KEEP(*(.fips140_module_data))
    _binary_fips140_ko_end = .;
}
```
2. **Create Architecture-Specific Files**: Set up `arch/[new-arch]/crypto/fips140/` directory with Makefile and `fips140-var-redirect.c` following the pattern used in x86_64 and ARM64.

## 6. Reusing a certified module in practice

With the crypto subsystem restructured as a loadable module, a previously certified module can be reused across kernel updates. Crypto development does not freeze in the meantime — updated modules can always be submitted for fresh certification. The reuse of an already-certified module is intended to simply bridge the gap until the new certification arrives, that is, using the old one before the new one gets certified. How much of the certified module to reuse, however, involves a tradeoff between crypto feature availability, certification turnaround time, and engineering effort.

The most conservative option is no reuse at all: abandon the previous certification and submit the updated crypto module for a full FIPS certification. This allows the crypto subsystem to benefit from the latest upstream changes, but at the cost of the full 12-to-18-month waiting period, according to experiences from downstream distributions.

At the opposite end, distributions can choose to reuse the certified module binary entirely on a newer kernel. This enables the new kernel to be validated on day one. The tradeoff is clear: besides forgoing crypto updates, engineers must ensure ABI compatibility between the updated kernel and the module.

A middle ground is to reuse only the source code of the certified module, freezing it and recompiling against the updated main kernel. Since the source code remains unchanged, the new module can go through a Non-Security Relevant ([NSRL](https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS-140-3-CMVP%20Management%20Manual.pdf)) process — a simpler FIPS re-certification that typically reduces the waiting time from 12–18 months down to 3–4 months. Compared to reusing the binary entirely, this option requires less engineering effort, since engineers need only maintain source-level API compatibility (i.e., by patching the main kernel source code, not touching the crypto module source code) rather than binary-level ABI compatibility between the crypto module and the main kernel.

In summary, converting the kernel crypto subsystem into a loadable module enables reuse of a certified module across kernel updates. Whether through binary reuse, source-code reuse, or fresh certification, different choices represent different tradeoffs, and distributions can balance crypto feature availability, certification turnaround time, and engineering effort according to their needs.

## 7. Related Work and Comparison

The idea of modularizing kernel cryptographic functionality has also attracted attention from other Linux distributions as well as Linux-kernel-based platforms that are not traditional distributions. Specifically, there are two related efforts: one from [Android's GKI kernel](https://source.android.com/docs/core/architecture/kernel/gki-fips140-module) and another from [Oracle Linux](https://git.kernel.org/pub/scm/linux/kernel/git/vegard/linux-fips140.git/log/?h=fips140). While Amazon Linux incorporated several valuable ideas from these efforts (and have acknowledged them in the patch commits—thank you again!), this section highlights the key differences between those approaches and this approach. The goal is to describe the trade-offs and design choices objectively, rather than to criticize other implementations.

### 7.1. Comparison with Android's GKI

Android's work is the earliest one on modularizing kernel cryptographic code, and it targets a non-intrusive approach to the core GKI kernel, with the goal of minimizing modifications to the kernel source. To achieve this, the crypto module relies on several interception or "hijacking" techniques that intervene in the core kernel execution path.

While this approach minimizes kernel code changes, we don't adopt such an approach for several reasons. First, these interception mechanisms tightly depend on internal kernel crypto subsystem behavior, making them fragile across major kernel updates thus less suitable to reuse the same module on newer major kernel versions. Second, this design requires substantial additional cryptographic code duplication, which impacts maintainability. Finally, the solution only supports a fixed set of cryptographic algorithms, making it non-general and difficult to extend.

In contrast, our design integrates directly into the Linux kernel source tree, avoids duplicated cryptographic implementations, supports arbitrary kernel configuration settings, and works with any chosen set of cryptographic algorithms.

### 7.2. Comparison with Oracle Linux

Oracle’s work was developed concurrently with this approach. The primary differences between Oracle’s approach and Amazon's lie in build integration, pluggable interface design, and module initialization.

**Build Integration:**
Oracle's module is implemented as an out-of-tree module with a separate Makefile. This introduces three major reasons we don't adopt such an approach: 

*First*, the separate Makefile duplicates many kernel build rules, which increases maintenance cost, as upstream kernel build changes must be tracked and replicated. One concrete example can be seen below:

in Oracle's module makefile
```
fips140-y += crypto/skcipher.o
fips140-y += crypto/lskcipher.o
```
However, in upstream, the corresponding build logic is more complex and configuration-dependent:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As shown above, when `CONFIG_BPF_SYSCALL` is enabled, `bpf_crypto_skcipher.o` must also be included. Tracking such dependencies is hard in the duplicated Makefile approach. In contrast, our approach integrates seamlessly into the kernel build system by introducing a customized build rule (`crypto-objs-*`) rather than relying on a duplicated Makefile, such that this is handled correctly by reusing the existing kernel build logic:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As a result, such a Makefile-duplication approach does not scale well across all kernel configurations and does not easily support arbitrary sets of cryptographic algorithms.

*Second*, since the module is to be embedded as part of the kernel image (i.e., `vmlinux`) as described earlier, the module build must be triggered automatically as part of the `vmlinux` build process to achieve a seamless build workflow. However, Oracle's module build is not tightly integrated into the kernel build framework and requires special build commands (e.g., first do `make M=fips140/` specifically, then do some shell command and finally `make`). 

In contrast, our approach improves this aspect by integrating the module build tightly into the regular kernel build, so the build process is seamless and automatic with regular build and packaging processes such as `make` or `make vmlinux` or `make install`.

**Pluggable Interface:**
There are several differences in the pluggable interface design.

*First*, the approach we use avoids massive intrusion to the main kernel source tree (i.e., significantly fewer lines of source code modification), making it easier to maintain and merge to mainline. This reduction is mainly achieved by automating the conversion process of crypto function symbols to pluggable symbols. Specifically, the existing approach requires modifications to the cryptographic implementation (.c) files and the declaration (.h) header files of crypto function symbols, as well as the code pattern of crypto's initialization routine (e.g., replace `module_init(init_fn)` with `crypto_module_init(init_fn)`). In contrast, our approach fully automates this process without requiring any source code modification. As a result, our method achieves a reduction of ~3K lines of code (~70% of total), making it easier to maintain and merge to mainline.

*Second*, we avoid duplicate crypto code so only keep one crypto code in kernel memory, while existing work keeps two crypto code even if these crypto code are from the same source code. This is due to the way Oracle defines pluggable interface macros in `crypto/api`, where its design requires some cryptographic code to remain compiled into the main kernel image in addition to the code inside the standalone cryptography module. Keeping two crypto code is ok if these code are different and designed to be used for different runtime modes (i.e., FIPS/non-FIPS mode), but will be unnecessary if both crypto code are the same.

In contrast, the approach we use can flexibly support both choices: keep one cryptography subsystem, or two different crypto subsystems. To do so, we introduce an option `CRYPTO_FIPS140_DUAL_VERSION` such that when it is disabled, we only keep one cryptographic subsystem in the cryptography module while completely removing it from the main kernel; and when it is enabled, we allow having two different modules carrying different cryptography for different kernel runtime modes (i.e., FIPS and non-FIPS mode).

*Third*, prior approaches mainly support making cryptographic function calls pluggable, while our approach extends pluggability to cryptographic variables as well.

*Fourth*, prior approach requires all cryptographics that we care (for any purpose such as those within FIPS boundary) to be included within a single kernel module `fips140.ko` (e.g., when `CONFIG_CRYPTO_AES=m`, it cannot be `aes.ko` but must be within fips140.ko). However, this requirement limits the inherent benefit of a kernel module (i.e., on-demand loading for memory efficiency). In contrast, our approach allows the cryptographic we care remain its original modular if it is configured as being so (i.e., if `CONFIG_CRYPTO_AES=m`, the aes will still be as `aes.ko` but not forced to `fips140.ko`) up to the `.config` setting. One benefit of this design is that it does not impose strict requirements on `.config` setting (i.e., a cryptography `.config` can be set to both `=y|m` while existing work must be set as `=y`), preserving configuration flexibility.

To support so, for any cryptography within the interest (i.e., whose makerule has been replaced with `crypto-objs-*`) but configured as build-as-module (i.e., `CONFIG_CRYPTO_*=m`), its compiled `.ko` binary will be marked automatically, such that the loader will have a way to recognize to perform some interest-specific processing (e.g., registered as FIPS-required flag) if needed. And the pluggable interface can also adjust its coverage automatically based on different `CONFIG_CRYPTO_*=y|=m` settings. This is achieved by letting the pluggable interface macro to take `CONFIG_CRYPTO_*` option as a parameter to recognize the `.config` setting.

**Module Initialization:**
Oracle's initialization routine does not guarantee preservation of the original crypto initialization order (i.e., the order they should follow if they were originally built-in in the main kernel), which limits its ability to support arbitrary combinations of cryptographic algorithms. This is because the crypto initialization routine in the module is executed too early, such that all module crypto is initialized before the cryptography init in the main kernel. So if there is a crypto in the module (e.g., a crypto init defined as `late_init()`) that depends on a cryptography (whose init is defined as `module_init()`) in the main kernel, since the one in the main kernel should be executed earlier (but because the module init is too early, it makes the crypto in the main kernel executed too late), such a case will break the kernel boot process.

Our design, on the other hand, introduces explicit initialization synchronization mechanisms between cryptography's init routine in the module and in the main kernel that can preserve the original built-in initialization order. As a result, our module supports any chosen crypto set to be included in the module.

### 7.3. Comparison Summary

Overall, combined with differences in coding style and integration strategy, the proposed approach has less source-code modification, is more seamlessly integrated with the upstream Linux kernel, making it more generalizable across different kernel configuration settings, and the changed behavior more invisible to kernel users.

## 8. Summary
In this patch series, Amazon Linux proposes a new kernel feature that decouples the built-in crypto subsystem into a dedicated kernel module. To achieve this, several key mechanisms are designed, including specialized compile rules, a novel pluggable interface mechanism, and a module-loading initialization process. This feature is designed in an upstream-friendly manner so that it can support arbitrary kernel configuration settings and arbitrary chosen sets of cryptographic algorithms. It has been officially launched with the Amazon Linux Kernel 6.18 as well as future kernels.

---
Written by Jay Wang <wanjay@amazon.com> <jay.wang.upstream@gmail.com>, Amazon Linux

Jay Wang (17):
      crypto: add Kconfig options for standalone crypto module
      crypto: add module entry for standalone crypto kernel module
      build: special compilation rule for building the standalone crypto module
      build: Add ELF marker for crypto-objs-m modules
      crypto: add pluggable interface for module symbols referenced by the main kernel
      crypto: dedicated ELF sections for collected crypto initcalls
      crypto: fips140: add crypto module loader
      build: embed the standalone crypto module into vmlinux
      module: skip modversion checks for crypto modules
      build: add CONFIG_DEBUG_INFO_BTF_MODULES support for the standalone crypto kernel module
      Allow selective crypto module loading at boot based on FIPS mode
      Execute crypto initcalls during module initialization
      crypto: fips140: add module integrity self-check
      crypto: convert exported symbols in architecture-independent crypto to pluggable symbols
      x86/crypto: convert exported symbols in x86 crypto to pluggable symbols
      arm64/crypto: convert exported symbols in arm64 crypto to pluggable symbols
      Add standalone crypto kernel module technical documentation

Vegard Nossum (2):
      module: allow kernel module loading directly from memory
      crypto/algapi.c: skip crypto_check_module_sig() for the standalone crypto module

 Makefile                                         | 106 +++++-
 arch/arm64/crypto/Makefile                       |  23 +-
 arch/arm64/crypto/fips140/Makefile               |  14 +
 arch/arm64/crypto/fips140/fips140-var-redirect.c |   0
 arch/arm64/kernel/vmlinux.lds.S                  |  40 +++
 arch/x86/crypto/Makefile                         |  41 +--
 arch/x86/crypto/fips140/Makefile                 |  14 +
 arch/x86/crypto/fips140/fips140-var-redirect.c   |   0
 arch/x86/kernel/vmlinux.lds.S                    |  40 +++
 certs/system_keyring.c                           |   1 +
 crypto/Kconfig                                   |   1 +
 crypto/Makefile                                  | 207 ++++++------
 crypto/algapi.c                                  |  14 +-
 crypto/asymmetric_keys/Makefile                  |  16 +-
 crypto/asymmetric_keys/restrict.c                |   2 +
 crypto/asymmetric_keys/verify_pefile.c           |   1 +
 crypto/async_tx/Makefile                         |  12 +-
 crypto/fips140/Kconfig                           |  70 ++++
 crypto/fips140/Makefile                          |  25 ++
 crypto/fips140/README                            | 404 +++++++++++++++++++++++
 crypto/fips140/fips140-crypto-module-marker.h    |   8 +
 crypto/fips140/fips140-fn-redirect.c             |  10 +
 crypto/fips140/fips140-loader.c                  | 195 +++++++++++
 crypto/fips140/fips140-module.c                  | 155 +++++++++
 crypto/fips140/fips140-module.h                  |  30 ++
 crypto/fips140/fips140-var-redirect.c            |  78 +++++
 crypto/fips140/fips140.lds                       |  38 +++
 crypto/fips140/gen-fips140-fn-redirect.sh        |  28 ++
 crypto/krb5/Makefile                             |   2 +-
 include/asm-generic/vmlinux.lds.h                |   2 +
 include/crypto/cast_common.h                     |  17 +-
 include/crypto/fips140-fn-redirect.h             |  63 ++++
 include/crypto/fips140-redirect.h                |  92 ++++++
 include/crypto/md5.h                             |   8 +-
 include/crypto/public_key.h                      |   7 +-
 include/crypto/rng.h                             |   1 +
 include/crypto/sm4.h                             |  13 +-
 include/keys/asymmetric-type.h                   |   7 +-
 include/linux/export.h                           |  22 ++
 include/linux/init.h                             |  10 +
 include/linux/module.h                           |  25 ++
 include/uapi/linux/module.h                      |   6 +
 init/main.c                                      |   4 +
 kernel/bpf/btf.c                                 |  20 ++
 kernel/module/internal.h                         |   1 +
 kernel/module/main.c                             | 185 +++++++++--
 kernel/module/version.c                          |   9 +
 kernel/params.c                                  |   3 +-
 scripts/Makefile.build                           | 124 ++++++-
 scripts/Makefile.modfinal                        |  38 +++
 scripts/Makefile.modinst                         |  13 +-
 scripts/Makefile.modpost                         |  25 ++
 scripts/Makefile.vmlinux                         |  59 +++-
 scripts/link-vmlinux.sh                          |  26 ++
 scripts/mod/modpost.c                            |  24 +-
 55 files changed, 2182 insertions(+), 197 deletions(-)
 create mode 100644 arch/arm64/crypto/fips140/Makefile
 create mode 100644 arch/arm64/crypto/fips140/fips140-var-redirect.c
 create mode 100644 arch/x86/crypto/fips140/Makefile
 create mode 100644 arch/x86/crypto/fips140/fips140-var-redirect.c
 create mode 100644 crypto/fips140/Kconfig
 create mode 100644 crypto/fips140/Makefile
 create mode 100644 crypto/fips140/README
 create mode 100644 crypto/fips140/fips140-crypto-module-marker.h
 create mode 100644 crypto/fips140/fips140-fn-redirect.c
 create mode 100644 crypto/fips140/fips140-loader.c
 create mode 100644 crypto/fips140/fips140-module.c
 create mode 100644 crypto/fips140/fips140-module.h
 create mode 100644 crypto/fips140/fips140-var-redirect.c
 create mode 100644 crypto/fips140/fips140.lds
 create mode 100755 crypto/fips140/gen-fips140-fn-redirect.sh
 create mode 100644 include/crypto/fips140-fn-redirect.h
 create mode 100644 include/crypto/fips140-redirect.h

-- 
2.47.3



^ permalink raw reply

* Re: [PATCH v2 3/4] usb: dwc3: xilinx: Add Versal2 MMI USB 3.2 controller support
From: Thinh Nguyen @ 2026-04-17 23:53 UTC (permalink / raw)
  To: Radhey Shyam Pandey
  Cc: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org,
	conor+dt@kernel.org, michal.simek@amd.com, Thinh Nguyen,
	p.zabel@pengutronix.de, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, git@amd.com
In-Reply-To: <20260330190304.1841593-4-radhey.shyam.pandey@amd.com>

On Tue, Mar 31, 2026, Radhey Shyam Pandey wrote:
> Multi-media integrated (MMI) USB3.2 DRD IP is usb3.1 gen2 controller
> which support following speed SSP (10-Gbps), SuperSpeed(5-Gbps),
> high-speed(480-Mbps), full-speed(12-Mbps), and low-speed(1.5-Mbps)
> operation modes.
> 
> USB2 and USB3 PHY support Physical connectivity via the Type-C
> connectivity. The MMI USB controller does not have a dedicated wrapper
> register space, so ioremap is skipped via the map_resource config flag.
> 
> The driver handles clock and reset initialization. In this initial
> version typec reversibility is not implemented and it is assumed that
> USB3 PHY TCA mux programming is done by MMI configuration data object
> (CDOs) and TI PD controller is configured using external tiva programmer
> on VEK385 evaluation board.
> 
> Tested host mode with mass storage device.
> 
> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
> ---
> - Introduce xlnx,usb-syscon phandle to access UDH address space
>   which is wrapper subsystem IP for USB, DP and HDCP.

Where's xlnx,usb-syscon phandle?



> - Split config struct refactoring into separate patch (2/4).
> - Remove unused regmap/syscon fields and parsing code; defer to
>   patch that first consumes them.
> - Fix error message capitalization to lowercase ("reset", "deassert").
> ---
>  drivers/usb/dwc3/dwc3-xilinx.c | 50 ++++++++++++++++++++++++++++++----
>  1 file changed, 44 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
> index bb59b56726e7..f2dee28bdc65 100644
> --- a/drivers/usb/dwc3/dwc3-xilinx.c
> +++ b/drivers/usb/dwc3/dwc3-xilinx.c
> @@ -46,6 +46,7 @@ struct dwc3_xlnx;
>  
>  struct dwc3_xlnx_config {
>  	int				(*pltfm_init)(struct dwc3_xlnx *data);
> +	bool				map_resource;

Perhaps this property should be inversed since the versal2 is unusual
that it doesn't need mapping of resource. How about no_mem_map?

>  };
>  
>  struct dwc3_xlnx {
> @@ -93,6 +94,29 @@ static void dwc3_xlnx_set_coherency(struct dwc3_xlnx *priv_data, u32 coherency_o
>  	}
>  }
>  
> +static int dwc3_xlnx_init_versal2(struct dwc3_xlnx *priv_data)
> +{
> +	struct device		*dev = priv_data->dev;
> +	struct reset_control	*crst;
> +	int			ret;
> +
> +	crst = devm_reset_control_get_optional_exclusive(dev, NULL);
> +	if (IS_ERR(crst))
> +		return dev_err_probe(dev, PTR_ERR(crst),
> +				     "failed to get reset signal\n");
> +
> +	/* assert and deassert reset */
> +	ret = reset_control_assert(crst);
> +	if (ret < 0)
> +		return dev_err_probe(dev, ret, "failed to assert reset\n");

Any requirement on how long the reset needs to stay asserted?

> +
> +	ret = reset_control_deassert(crst);
> +	if (ret < 0)
> +		return dev_err_probe(dev, ret, "failed to deassert reset\n");
> +
> +	return 0;
> +}
> +
>  static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data)
>  {
>  	struct device		*dev = priv_data->dev;
> @@ -250,10 +274,16 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
>  
>  static const struct dwc3_xlnx_config zynqmp_config = {
>  	.pltfm_init = dwc3_xlnx_init_zynqmp,
> +	.map_resource = true,
>  };
>  
>  static const struct dwc3_xlnx_config versal_config = {
>  	.pltfm_init = dwc3_xlnx_init_versal,
> +	.map_resource = true,
> +};
> +
> +static const struct dwc3_xlnx_config versal2_config = {
> +	.pltfm_init = dwc3_xlnx_init_versal2,
>  };
>  
>  static const struct of_device_id dwc3_xlnx_of_match[] = {
> @@ -265,6 +295,10 @@ static const struct of_device_id dwc3_xlnx_of_match[] = {
>  		.compatible = "xlnx,versal-dwc3",
>  		.data = &versal_config,
>  	},
> +	{
> +		.compatible = "xlnx,versal2-mmi-dwc3",
> +		.data = &versal2_config,
> +	},
>  	{ /* Sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, dwc3_xlnx_of_match);
> @@ -299,19 +333,23 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
>  	struct dwc3_xlnx		*priv_data;
>  	struct device			*dev = &pdev->dev;
>  	struct device_node		*np = dev->of_node;
> -	void __iomem			*regs;
>  	int				ret;
>  
>  	priv_data = devm_kzalloc(dev, sizeof(*priv_data), GFP_KERNEL);
>  	if (!priv_data)
>  		return -ENOMEM;
>  
> -	regs = devm_platform_ioremap_resource(pdev, 0);
> -	if (IS_ERR(regs))
> -		return dev_err_probe(dev, PTR_ERR(regs), "failed to map registers\n");
> -
>  	priv_data->dwc3_config = device_get_match_data(dev);
> -	priv_data->regs = regs;
> +
> +	if (priv_data->dwc3_config->map_resource) {
> +		void __iomem *regs;
> +
> +		regs = devm_platform_ioremap_resource(pdev, 0);
> +		if (IS_ERR(regs))
> +			return dev_err_probe(dev, PTR_ERR(regs),
> +					     "failed to map registers\n");
> +		priv_data->regs = regs;
> +	}
>  	priv_data->dev = dev;
>  
>  	platform_set_drvdata(pdev, priv_data);
> -- 
> 2.43.0
> 

BR,
Thinh

^ permalink raw reply

* Re: [PATCH 00/40] arm64: dts: rockchip: Wire up frl-enable-gpios for RK3576/RK3588 boards
From: Heiko Stuebner @ 2026-04-17 23:18 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Cristian Ciocaltea
  Cc: kernel, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel
In-Reply-To: <70e9a8a0-414d-428f-8da8-9b65cc764849@collabora.com>

Hi Cristan,

Am Freitag, 17. April 2026, 19:55:17 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
> On 4/17/26 2:34 PM, Heiko Stuebner wrote:
> > Am Freitag, 17. April 2026, 11:24:34 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
> > 
> > [...]
> > 
> >> Cristian Ciocaltea (40):
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-100ask-dshanpi-a1
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-armsom-sige5
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-evb1-v10
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-evb2-v10
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-luckfox-core3576
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-nanopi-m5
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-nanopi-r76s
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-roc-pc
> >>       arm64: dts: rockchip: Add frl-enable-gpios to rk3576-rock-4d
> > 
> > I do think one patch per SoC (rk3576, rk3588, rk3588s) would make more
> > sense, because these patches really are mostly identical :-)
> 
> Yeah, apologies for the large number of patches, I went this way to allow
> per-board reviews.  As previously noted, I tried to identify the GPIO pins from
> multiple sources, so I'm not entirely sure about the accuracy in every case.
> 
> Would it be preferable to squash the patches per SoC and board vendor, instead?

I really would just do it per soc .. so 3 patches. That is a size that is
still reviewable for people, who can then check for their board.

If the patch is labeled "Add frl-enable-gpios for all RK3588s boards", I
do expect people to notice it the same as "oh _my_ board gets changed".
("all" could also be "most" :-) ).


Heiko




^ permalink raw reply

* Re: [PATCH 05/40] arm64: dts: rockchip: Add frl-enable-gpios to rk3576-luckfox-core3576
From: Heiko Stuebner @ 2026-04-17 23:12 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Cristian Ciocaltea
  Cc: kernel, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel
In-Reply-To: <62f51359-9d91-4107-917b-cd722c7321c2@collabora.com>

Hi Cristian,

Am Freitag, 17. April 2026, 18:34:17 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
> On 4/17/26 2:32 PM, Heiko Stuebner wrote:
> > the comments below apply sort of to all patches in that series.
> > 
> > Am Freitag, 17. April 2026, 11:24:39 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
> >> The board exposes the GPIO4_C6 line to control the voltage bias on the
> >> HDMI data lines.  It must be asserted when operating in HDMI 2.1 FRL
> >> mode and deasserted for HDMI 1.4/2.0 TMDS mode.
> >>
> >> Wire up the HDMI node to the GPIO line using the frl-enable-gpios
> >> property and drop the line from the vcc_5v0_hdmi regulator to allow
> >> adjusting the bias when transitioning between TMDS and FRL operating
> >> modes.
> >>
> >> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> >> ---
> >>  arch/arm64/boot/dts/rockchip/rk3576-luckfox-core3576.dtsi | 9 ++++-----
> >>  1 file changed, 4 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/arch/arm64/boot/dts/rockchip/rk3576-luckfox-core3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-luckfox-core3576.dtsi
> >> index 749f0a54b478..93ae37699366 100644
> >> --- a/arch/arm64/boot/dts/rockchip/rk3576-luckfox-core3576.dtsi
> >> +++ b/arch/arm64/boot/dts/rockchip/rk3576-luckfox-core3576.dtsi
> >> @@ -140,10 +140,7 @@ regulator-state-mem {
> >>  
> >>  	vcc_5v0_hdmi: regulator-vcc-5v0-hdmi {
> >>  		compatible = "regulator-fixed";
> >> -		enable-active-high;
> >> -		gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
> >> -		pinctrl-names = "default";
> >> -		pinctrl-0 = <&hdmi_con_en>;
> >> +		regulator-always-on;
> >>  		regulator-min-microvolt = <5000000>;
> >>  		regulator-max-microvolt = <5000000>;
> >>  		regulator-name = "vcc_5v0_hdmi";
> > 
> > I think this regulator was sort of a complete hack, to set that
> > gpio to some sort of default state, by declaring it as hdmi-pwr-supply.
> > 
> > Only 2 rk3576 boards seem, to use that hack, so I think as that "regulator"
> > is completely functionless now, the whole thing could be removed?
> 
> Ack, let's just drop it.
> 
> > 
> > 
> >> @@ -231,6 +228,8 @@ &gpu {
> >>  };
> >>  
> >>  &hdmi {
> >> +	pinctrl-0 = <&hdmi_txm0_pins &hdmi_tx_scl &hdmi_tx_sda &hdmi_frl_en>;
> >> +	frl-enable-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
> > 
> > this should be sorted the other way around I think.
> > 
> > Also please provide a pinctrl-names property too. If for whatever reason
> > the dw-hdmi aquires a 2nd pinctrl state in the future, this makes sure
> > board DTs are staying in the "old" compatible mode until they are adapted.
> 
> Just to make sure I fully understand, the convention is that 
> 
>   pinctrl-names = "default";
> 
> should be always provided, even when the node overrides an existing pinctrl-0
> property?
> 
> E.g. in rk3576.dtsi we have:
> 
>   hdmi: hdmi@27da0000 {
>     ...
>     pinctrl-names = "default";
>     pinctrl-0 = <&hdmi_txm0_pins &hdmi_tx_scl &hdmi_tx_sda>;
>     ...
>   }
> 
> Hence I omitted pinctrl-names which doesn't change and just appended
> &hdmi_frl_en to pinctrl-0's original value.

correct, please always provide a pinctrl-names entry when setting a new
pinctrl-0 .

The background is, imagine you have a base:

pinctrl-names = "default";
pinstrl-0 = <....>;

and override pinctrl-0 in a board.

Now a newer binding introduces a 2nd pinctrl state "foo". Of course
we're backwards compatible, and both are valid and the driver checks
what states are defined.

So the base sets:
pinctrl-names = "default", "foo";
pinctrl-0 = <...>;
pinctrl-1 = <...>;

in your (old) board you override pinctrl-0, but the driver still sees
the new variant with 2 pinctrl states, where it should've stayed with
the legacy 1-state, until the board-dts might get adapted in the future.


And I know, we're likely not doing that everywhere, and also in most
cases it won't really matter, but still it is safer and sets the better
precedent :-) .


> >>  	status = "okay";
> >>  };
> >>  
> >> @@ -655,7 +654,7 @@ &pcie0 {
> >>  
> >>  &pinctrl {
> >>  	hdmi {
> >> -		hdmi_con_en: hdmi-con-en {
> >> +		hdmi_frl_en: hdmi-frl-en {
> > 
> > pinctrl names should ideally match the naming in schematics, for example the
> > "HDMI0_TX_ON_H" for jaguar and tiger. This makes it way easier to> go from DT
> > to schematics and back.
> 
> I opted for a more descriptive name that could be used consistently across all
> boards, given that not all schematics are publicly available.
> 
> You make a fair point though, we should probably stick with the pretty terrible
> hdmi[N]_tx_on_h naming instead.

yep, we're doing that everywhere else already too, and sticking to the
schematics naming, also prevents any discussions about how something
should be named ;-) .


Heiko




^ permalink raw reply

* Re: [PATCH RFC 2/4] clk: rockchip: pll: use round-nearest in determine_rate
From: Heiko Stuebner @ 2026-04-17 22:59 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Michael Turquette,
	Stephen Boyd, Alexey Charkov
  Cc: Pavel Zhovner, Sebastian Reichel, Andy Yan, devicetree,
	linux-arm-kernel, linux-rockchip, linux-kernel, linux-clk,
	Alexey Charkov
In-Reply-To: <20260417-rk3576-dclk-v1-2-26a9d0dcb2de@flipper.net>

Hi Alexey,

Am Freitag, 17. April 2026, 17:11:45 Mitteleuropäische Sommerzeit schrieb Alexey Charkov:
> rockchip_pll_determine_rate() walks the rate table in descending order
> and picks the first entry <= the requested rate. This floor-rounding
> interacts poorly with consumers that use CLK_SET_RATE_PARENT: a divider
> iterating candidates asks the PLL for rate*div, and a tiny undershoot
> causes the PLL to snap to a much lower entry.
> 
> For example, requesting 1991.04 MHz (248.88 MHz * 8) causes the PLL to
> return 1968 MHz instead of 1992 MHz — a 24 MHz table gap that produces
> a 1.2% pixel clock error when divided back down.
> 
> Change to round-to-nearest: for each table entry compute the absolute
> distance from the request, and pick the entry with the smallest delta.
> The CCF's divider and composite logic handle over/undershoot preferences
> via their own ROUND_CLOSEST flags.
> 
> Signed-off-by: Alexey Charkov <alchark@flipper.net>

as Sebastian said, this could cause overclocking in a number of areas.
The rate you get should always be lower or equal to the requested rate.

Additionally, such a core behaviour change, would affect 13 years of
SoCs with unknown side-effects.

If you're missing specific clock rates, you can always add them to the
list :-) . The vendor-kernel does have code that can calculate the
rate params itself, so this could give you a hint where to start.

======= just to explain =======

Though I still don't think that code should be in the mainline-kernel,
as a curated PLL rates allows more control, where that algorithm
creates parameters that are programmatically correct, but essentially
untested.

On the two Chromebook projects, they actually measured things like
clock jitter, which got us more specific params for some rates.


Heiko





^ permalink raw reply

* Re: [PATCH v8 08/10] ASoC: mediatek: mt8196: add platform driver
From: Mark Brown @ 2026-04-17 22:52 UTC (permalink / raw)
  To: Cyril Chao (钞悦)
  Cc: linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	devicetree@vger.kernel.org, Darren Ye (叶飞),
	linux-sound@vger.kernel.org, conor+dt@kernel.org, tiwai@suse.com,
	robh@kernel.org, lgirdwood@gmail.com,
	linux-arm-kernel@lists.infradead.org,
	Project_Global_Chrome_Upstream_Group, matthias.bgg@gmail.com,
	krzk+dt@kernel.org, perex@perex.cz, AngeloGioacchino Del Regno
In-Reply-To: <da5752796e1774b6bbc24f5ef1ab2529e24a384f.camel@mediatek.com>

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

On Thu, Apr 16, 2026 at 05:53:25AM +0000, Cyril Chao (钞悦) wrote:
> Thank you for your assistance in reviewing. Could you please also
> review the modifications in the diff? If everything is okay, I will
> include them in v9 in the next update.

That looks OK from a scan through, though it's possible I'd see
something else if I review in full context.

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

^ permalink raw reply

* Re: [PATCH 1/6] drm/connector: report IRQ_HPD events to drm_connector_oob_hotplug_event()
From: Dmitry Baryshkov @ 2026-04-17 22:32 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: dri-devel, linux-kernel, linux-usb, intel-gfx, intel-xe,
	linux-amlogic, linux-arm-kernel, linux-arm-msm, freedreno,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Heikki Krogerus, Greg Kroah-Hartman, Andrzej Hajda,
	Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
	Jernej Skrabec, Adrien Grassein, Jani Nikula, Rodrigo Vivi,
	Joonas Lahtinen, Tvrtko Ursulin, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Bjorn Andersson,
	Konrad Dybcio, Pengyu Luo, Nikita Travkin, Yongxing Mou
In-Reply-To: <51b7c44e-36c9-461f-983a-eaa86eeb8cfd@ideasonboard.com>

On Thu, Apr 16, 2026 at 11:10:03AM +0300, Tomi Valkeinen wrote:
> Hi,
> 
> On 16/04/2026 02:22, Dmitry Baryshkov wrote:
> > The DisplayPort standard defines a special kind of events called IRQ.
> > These events are used to notify DP Source about the events on the Sink
> > side. It is extremely important for DP MST handling, where the MST
> > events are reported through this IRQ.
> > 
> > In case of the USB-C DP AltMode there is no actual HPD pulse, but the
> > events are ported through the bits in the AltMode VDOs.
> > 
> > Extend the drm_connector_oob_hotplug_event() interface and report IRQ
> > events to the DisplayPort Sink drivers.
> > 
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> > ---
> >   drivers/gpu/drm/drm_connector.c          |  4 +++-
> >   drivers/usb/typec/altmodes/displayport.c | 12 ++++++++----
> >   include/drm/drm_connector.h              |  3 ++-
> >   3 files changed, 13 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> > index 47dc53c4a738..5fdacbd84bd7 100644
> > --- a/drivers/gpu/drm/drm_connector.c
> > +++ b/drivers/gpu/drm/drm_connector.c
> > @@ -3510,6 +3510,7 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
> >    * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
> >    * @connector_fwnode: fwnode_handle to report the event on
> >    * @status: hot plug detect logical state
> > + * @irq_hpd: HPD pulse detected
> >    *
> >    * On some hardware a hotplug event notification may come from outside the display
> >    * driver / device. An example of this is some USB Type-C setups where the hardware
> > @@ -3520,7 +3521,8 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
> >    * a drm_connector reference through calling drm_connector_find_by_fwnode().
> >    */
> >   void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode,
> > -				     enum drm_connector_status status)
> > +				     enum drm_connector_status status,
> > +				     bool irq_hpd)
> I find the "IRQ HPD" naming always confusing, even if I'm somewhat familiar
> with DP, but if someone has mainly worked on HDMI, I'm sure it's even worse.
> 
> Can we define this a bit more precisely? Is 'irq_hpd' only for displayport?
> If so, perhaps 'dp_irq_hpd' or 'displayport_irq_hpd'. I might even call it
> 'dp_hpd_pulse', but maybe that's not good as the spec talks about HPD pulse
> for both short and long ones (although in the kernel doc you just write "HPD
> pulse")... The kernel doc could be expanded a bit to make it clear what this
> flag indicates.

I attempted to stay away from defining a DP-specific flag, keeping it
generic enough. HDMI is pretty close (IMO) to requiring separate flag in
Linux. Likewise I'd rather not use "pulse". The DP AltMode defines a bit
in the VDO rather than a pulse.

Anyway, if irq_hpd doesn't sound precise enough, what about "bool
extra_irq"? This would convey that this is the extra hpd-related IRQ,
but it would also be obvious that it's not related to the HPD pin
itself.


-- 
With best wishes
Dmitry


^ permalink raw reply

* Re: [PATCH RFC 0/4] arm64: rockchip: The hunt for exact pixel clocks on RK3576
From: Sebastian Reichel @ 2026-04-17 22:24 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Michael Turquette, Stephen Boyd, Pavel Zhovner, Andy Yan,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	linux-clk, Cristian Ciocaltea
In-Reply-To: <20260417-rk3576-dclk-v1-0-26a9d0dcb2de@flipper.net>

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

Hello Alexey,

On Fri, Apr 17, 2026 at 07:11:43PM +0400, Alexey Charkov wrote:
> Dear all,
> 
> Need the help of the collective wisdom of the community.
> 
> The problem I'm trying to solve is reliably obtaining the exact pixel
> clock for arbitrary display modes supported by the RK3576 SoC.
> 
> Rockchip RK3576 has three display output processors VP0~VP2, each
> supporting different ranges of display modes, roughly as follows:
> - VP0: 4K 120Hz
> - VP1: 2.5k 60Hz
> - VP2: 1080p 60Hz
> 
> Each one obviously needs a pixel clock. The required frequencies for the
> pixel clocks vary greatly depending on the display mode, and need to be
> matched within a tight tolerance, or else many displays will refuse to
> work. E.g. the preferred (maximum) display mode out of VP1 is particularly
> awkward, because it requires a pixel clock of 248.88 MHz, which cannot
> be obtained using integer dividers from its default clock source (GPLL
> at 1188 MHz), and the nearest approximation is 237.6 MHz, which is well
> outside the tolerance of e.g. DP specification, resulting in a blank
> screen on most displays by default.
> 
> The clock sources are of course configurable, in particular there are muxes
> connected to each VP for selecting the source of the pixel clock:
> - Each VP can take the clock either from the (single!) HDMI PHY or from
>   its dedicated dclk_vpX_src mux
> - The dclk_vpX_src mux can select the clock from a number of system PLLs
>   (GPLL, CPLL, VPLL, BPLL, LPLL)
> 
> While the system PLLs can be configured to output a wide range of
> frequencies, they are shared between many system components. E.g. on the
> current mainline kernel on one of my RK3576 boards I've got the following:
> GPLL: 1188 MHz, enable count 20
> CPLL: 1000 MHz, enable count 17
> VPLL: 594 MHz, enable count 0 (yaay!)
> BPLL, LPLL: 816 MHz, enable count 0 (but these last ones don't have
>             predividers, so are less flexible)
> 
> So ultimately there is exactly one free fractional PLL (VPLL) which can be
> used to generate arbitrary pixel clocks, but we have up to three consumers
> trying to drive different display modes from it (e.g. HDMI on VP0, DP on
> VP1 and MIPI DSI on VP2). We also want to be able to adjust the PLL output
> frequency on the fly to satisfy the requirements of the selected display
> mode.
> 
> And this is where I'm stuck. Trying to satisfy the requirements of up to
> three consumers while changing the PLL frequency on the fly sounds like
> a poorly tractable mathematical problem (is it 3-SAT?). We can take the
> HDMI output out of the equation, because it can be driven from the HDMI
> PHY (which is capable of arbitrary rates) instead of the mux, but that
> makes the decision of which dclk source to use for a VP block dependent on
> which downstream consumer is connected to it (HDMI vs. something else).

It becomes more messy: The HDMI PHY cannot be used as clock source
for modes exceeding 4K@60Hz.

> Even then we somehow need two devices to cooperate in picking a PLL
> frequency that satisfies the requirements of both of them, and change to it
> without display corruption. I'm not even sure if the CCF has mechanisms
> for that?..
> 
> What follows is a brief set of patches which illustrate a partial solution
> for the case of "I just need 2.5k60Hz on VP1 via DP and don't care about
> the rest". It switches the VP1 unconditionally to use VPLL as the source
> for its dclk mux, allows changing the VPLL frequency on the fly, and also
> changes the frequency calculation logic to allow for nearest-match
> frequencies which are not necessarily rounded down. These are not meant
> to be merged as-is, as I see the following issues:
> - The flag allowing the PLL to change rate is in the clock driver, while
>   the reparenting to an unused PLL is in the device tree. If these go out
>   of sync, we might end up trying to change the frequency of a PLL which
>   is used by other consumers (I presume that could be dangerous)

It is a problem, see e.g. this patch from Heiko removing the flag
for an RK3588 VOP source clock:

https://lore.kernel.org/linux-rockchip/20251008133135.3745785-1-heiko@sntech.de/

Also note, that there is some more general ongoing work regarding
this:

See: https://lore.kernel.org/linux-clk/20260327-clk-scaling-v8-0-86cd0aba3c5f@redhat.com/

> - If VP0 happens to be driving DP output, it won't be able to produce the
>   2560x1440@60Hz mode for the same reasons as VP1 - then it must also be
>   reparented to VPLL and allowed to change its frequency on the fly

There is also the problem that nearest match might be sensible for the
display, but is not generally safe. For other clocks you might
effectively overclock, which shouldn't be done by default.

> It does bring me from a state of "always blank screen on DP output until
> the mode is switched to something magically working" to a state of
> "most monitors work at the default preferred mode" though.
> 
> It is tempting to just reparent both VP0 and VP1 to VPLL and allow both of
> them to change its frequency, while leaving VP2 on the default (fixed)
> GPLL and relying on the fact that 148.5 MHz (the required frequency for
> its maximum supported mode of 1920x1080@60Hz) is conveniently 1188/8 MHz -
> just what GPLL can provide. Then also force whichever VP is driving HDMI
> output to use the HDMI PHY as its clock source. But we still have the
> problem of DT vs. driver coordination, and I'm not sure how to define
> the policy for "if you've got HDMI connected, you must use the HDMI PHY
> clock for the respective VP, whichever VP that is".

Sorry, I don't have any complete solutions - except that I can tell
you that the VOP2 driver already automatically switches the clock
source to the HDMI PHY for HDMI outputs if the pixel rates allows it:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c#n1757

Greetings,

-- Sebastian

> I would very much appreciate any thoughts on how to approach this.
> 
> Signed-off-by: Alexey Charkov <alchark@flipper.net>
> ---
> Alexey Charkov (4):
>       arm64: dts: rockchip: rk3576: assign dclk_vp1_src to VPLL
>       clk: rockchip: pll: use round-nearest in determine_rate
>       clk: rockchip: rk3576: allow dclk_vp1_src to propagate rate to parent PLL
>       clk: rockchip: rk3576: add ROUND_CLOSEST to dclk_vp1_src divider
> 
>  arch/arm64/boot/dts/rockchip/rk3576.dtsi |  2 ++
>  drivers/clk/rockchip/clk-pll.c           | 16 ++++++++--------
>  drivers/clk/rockchip/clk-rk3576.c        |  4 ++--
>  3 files changed, 12 insertions(+), 10 deletions(-)
> ---
> base-commit: c7275b05bc428c7373d97aa2da02d3a7fa6b9f66
> change-id: 20260417-rk3576-dclk-4c95bbb67581
> 
> Best regards,
> -- 
> Alexey Charkov <alchark@flipper.net>
> 

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

^ permalink raw reply

* Re: [PATCH 1/1] KVM: arm64: nv: Avoid full shadow s2 unmap
From: Wei-Lin Chang @ 2026-04-17 21:40 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, linux-kernel, Oliver Upton, Joey Gouly,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon
In-Reply-To: <867bq72n7l.wl-maz@kernel.org>

On Thu, Apr 16, 2026 at 11:50:38AM +0100, Marc Zyngier wrote:
> On Thu, 16 Apr 2026 00:05:40 +0100,
> Wei-Lin Chang <weilin.chang@arm.com> wrote:
> > 
> > On Wed, Apr 15, 2026 at 09:38:55AM +0100, Marc Zyngier wrote:
> 
> [...]
> 
> > > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > > > index 851f6171751c..a97bd461c1e1 100644
> > > > --- a/arch/arm64/include/asm/kvm_host.h
> > > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > > @@ -217,6 +217,10 @@ struct kvm_s2_mmu {
> > > >  	 */
> > > >  	bool	nested_stage2_enabled;
> > > >  
> > > > +	/* canonical IPA to nested IPA range lookup */
> > > > +	struct maple_tree nested_revmap_mt;
> > > > +	bool	nested_revmap_broken;
> > > > +
> > > 
> > > Consider moving this boolean next to the other ones so that you don't
> > > create too many holes in the kvm_s2_mmu structure (use pahole to find out).
> > > 
> > > But I have some misgivings about the way things are structured
> > > here. Only NV needs a revmap, yet this is present irrelevant of the
> > > nature of the VM and bloats the data structure a bit.
> > > 
> > > My naive approach would have been to only keep a pointer to the
> > > revmap, and make that pointer NULL when the tree is "broken", and
> > > freed under RCU if the context isn't the correct one.
> > 
> > Can you explain what you mean by "if the context isn't the correct one"?
> > If this refers to when selecting a specific kvm_s2_mmu instance for
> > another context, then IIUC refcnt would already be 0 and there would be
> > no other user of the tree.
> 
> Sorry, "context" is an overloaded word. I meant a situation in which
> you couldn't immediately free the maple-tree because you're holding
> locks and freeing (hypothetically) requires a sleeping "context". in
> this case, freeing under RCU, purely as a deferring mechanism, might
> be useful.

Oh ok! I get your point now.

> 
> [...]
> 
> > > > +/*
> > > > + * Per shadow S2 reverse map (IPA -> nested IPA range) maple tree payload
> > > > + * layout:
> > > > + *
> > > > + * bit 63: valid, 1 for non-polluted entries, prevents the case where the
> > > > + *         nested IPA is 0 and turns the whole value to 0
> > > > + * bits 55-12: nested IPA bits 55-12
> > > > + * bit 0: polluted, 1 for polluted, 0 for not
> > > > + */
> > > > +#define VALID_ENTRY		BIT(63)
> > > > +#define NESTED_IPA_MASK		GENMASK_ULL(55, 12)
> > > > +#define UNKNOWN_IPA		BIT(0)
> > > > +
> > > 
> > > This only works because you are using the "advanced" API, right?
> > > Otherwise, you'd be losing the high bit. It'd be good to add a comment
> > > so that people keep that in mind.
> > 
> > Sorry, I can't find any relationship between the advanced API and the
> > top most bit of the maple tree value, what am I missing?
> 
> From Documentation/core-api/maple_tree.rst:
> 
> <quote>
> The Maple Tree can store values between ``0`` and ``ULONG_MAX``.  The Maple
> Tree reserves values with the bottom two bits set to '10' which are below 4096
> (ie 2, 6, 10 .. 4094) for internal use.  If the entries may use reserved
> entries then the users can convert the entries using xa_mk_value() and convert
> them back by calling xa_to_value().  If the user needs to use a reserved
> value, then the user can convert the value when using the
> :ref:`maple-tree-advanced-api`, but are blocked by the normal API.
> </quote>
> 
> So depending how you read this, you can conclude that the bit patterns
> you encode in the MT may be considered as invalid. xa_mk_value() would
> make things always work, but that shifts the value left by one bit,
> hence you'd lose bit 63 (see how we use trap_config in
> emulate-nested.c to deal with this).

Thanks! I haven't looked at what xa_{mk, to}_value do until now.

> 
> I think you are lucky that bits [11:1] are always 0 here, but that
> looks extremely fragile to me, so you never hit the [1:0]==10
> condition, but that's really fragile.

I'll change the bits and switch to using xa_{mk, to}_value consistently.

> 
> > 
> > > 
> > > >  void kvm_init_nested(struct kvm *kvm)
> > > >  {
> > > >  	kvm->arch.nested_mmus = NULL;
> > > > @@ -769,12 +783,57 @@ static struct kvm_s2_mmu *get_s2_mmu_nested(struct kvm_vcpu *vcpu)
> > > >  	return s2_mmu;
> > > >  }
> > > >  
> > > > +void kvm_record_nested_revmap(gpa_t ipa, struct kvm_s2_mmu *mmu,
> > > > +			      gpa_t fault_ipa, size_t map_size)
> > > > +{
> > > > +	struct maple_tree *mt = &mmu->nested_revmap_mt;
> > > > +	gpa_t start = ipa;
> > > > +	gpa_t end = ipa + map_size - 1;
> > > > +	u64 entry, new_entry = 0;
> > > > +	MA_STATE(mas, mt, start, end);
> > > > +
> > > > +	if (mmu->nested_revmap_broken)
> > > > +		return;
> > > > +
> > > > +	mtree_lock(mt);
> > > > +	entry = (u64)mas_find_range(&mas, end);
> > > > +
> > > > +	if (entry) {
> > > > +		/* maybe just a perm update... */
> > > > +		if (!(entry & UNKNOWN_IPA) && mas.index == start &&
> > > > +		    mas.last == end &&
> > > > +		    fault_ipa == (entry & NESTED_IPA_MASK))
> > > > +			goto unlock;
> > > > +		/*
> > > > +		 * Create a "polluted" range that spans all the overlapping
> > > > +		 * ranges and store it.
> > > > +		 */
> > > > +		while (entry && mas.index <= end) {
> > > > +			start = min(mas.index, start);
> > > > +			end = max(mas.last, end);
> > > > +			entry = (u64)mas_find_range(&mas, end);
> > > > +		}
> > > > +		new_entry |= UNKNOWN_IPA;
> > > > +	} else {
> > > > +		new_entry |= fault_ipa;
> > > > +		new_entry |= VALID_ENTRY;
> > > > +	}
> > > > +
> > > > +	mas_set_range(&mas, start, end);
> > > > +	if (mas_store_gfp(&mas, (void *)new_entry, GFP_NOWAIT | __GFP_ACCOUNT))
> > > > +		mmu->nested_revmap_broken = true;
> > > 
> > > Can we try and minimise the risk of allocation failure here?
> > > 
> > > user_mem_abort() tries very hard to pre-allocate pages for page
> > > tables by maintaining an memcache. Can we have a similar approach for
> > > the revmap?
> > 
> > Unfortunately, as I understand the maple tree can only pre-allocate for
> > a store when the range and the entry to be stored is given, but in this
> > case we must inspect the tree to get that information after we hold the
> > mmu and maple tree locks. It is possible to do a two pass approach:
> > 
> > pre-allocate -> take MMU lock -> take maple tree lock -> revalidate what
> > we pre-allocated is still usable (nobody changed the tree before we took
> > the maple tree lock)
> > 
> > But I am not fond of this extra complexity..
> 
> Fair enough. It would at least be interesting to get a feel for how
> often this happens, because if we fail often, it won't help much.

Ack. I agree.

Thanks,
Wei-Lin Chang

> 
> [...]
> 
> > > My other concern here is related to TLB invalidation. As the guest
> > > performs TLB invalidations that remove entries from the shadow S2,
> > > there is no way to update the revmap to account for this.
> > > 
> > > This obviously means that the revmap becomes more and more inaccurate
> > > over time, and that is likely to accumulate conflicting entries.
> > > 
> > > What is the plan to improve the situation on this front?
> > 
> > Right now I think using a direct map which goes from nested IPA to
> > canonical IPA could work while not generating too much complexity, if we
> > keep the reverse map and direct map in lockstep (direct map keeping the
> > same mappings as the reverse map but just in reverse).
> 
> Right, so that'd effectively a mirror of the guest's page tables at
> the point of taking the fault.
> 
> > I'll try to do that and include it in the next iteration.
> 
> Thanks,
> 
> 	M.
> 
> -- 
> Without deviation from the norm, progress is not possible.


^ permalink raw reply

* Re: [PATCH v6 3/3] dts: s32g: Add GPR syscon region
From: Jared Kangas @ 2026-04-17 21:36 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Chester Lin, Matthias Brugger, Ghennadi Procopciuc,
	NXP S32 Linux Team, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-arm-kernel, imx,
	devicetree, linux-kernel, linaro-s32, netdev
In-Reply-To: <0e922537c02d1c47734142090f98eb78e921ed34.1769764941.git.dan.carpenter@linaro.org>

Hi Dan,

On Fri, Jan 30, 2026 at 04:19:52PM +0300, Dan Carpenter wrote:
> Add the GPR syscon region for the s32 chipset.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
> ---
>
> [snip]
>
> diff --git a/arch/arm64/boot/dts/freescale/s32g3.dtsi b/arch/arm64/boot/dts/freescale/s32g3.dtsi
> index e314f3c7d61d..be03db737384 100644
> --- a/arch/arm64/boot/dts/freescale/s32g3.dtsi
> +++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi
> @@ -383,6 +383,11 @@ usdhc0-200mhz-grp4 {
>  			};
>  		};
>  
> +		gpr: syscon@4007c000 {
> +			compatible = "nxp,s32g3-gpr", "syscon";
> +			reg = <0x4007c000 0x3000>;
> +		};
> +
>  		ocotp: nvmem@400a4000 {
>  			compatible = "nxp,s32g3-ocotp", "nxp,s32g2-ocotp";
>  			reg = <0x400a4000 0x400>;
> @@ -808,6 +813,7 @@ gmac0: ethernet@4033c000 {
>  			compatible = "nxp,s32g2-dwmac";
>  			reg = <0x4033c000 0x2000>, /* gmac IP */
>  			      <0x4007c004 0x4>;    /* GMAC_0_CTRL_STS */
> +			nxp,phy-sel = <&gpr 0x4>;
>  			interrupt-parent = <&gic>;
>  			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
>  			interrupt-names = "macirq";

I gave this a test on an S32G-VNP-RDB3 and didn't see any issues on the
dwmac-s32 side, but this appears to trigger a panic when reading the new
debugfs regmap/*/registers file for the syscon node:

    # grep 4007c000 /proc/vmallocinfo
    0xffff800083da8000-0xffff800083dac000   16384 ioremap_prot+0x74/0xe0 phys=0x000000004007c000 ioremap
    # cat /sys/kernel/debug/regmap/dummy-syscon@0x000000004007c000/registers
    Internal error: synchronous external abort: 0000000096000210 [#1]  SMP
    [...]
    CPU: 0 UID: 0 PID: 4344 Comm: cat Tainted: G   M        E  X   ------  ---  6.12.0+ #226 PREEMPT_RT
    Tainted: [M]=MACHINE_CHECK, [E]=UNSIGNED_MODULE, [X]=AUX
    [...]
    pc : regmap_mmio_read32le+0x44/0xa0
    lr : regmap_mmio_read32le+0x44/0xa0
    [...]
    x23: ffff00080c080000 x22: ffff000802ac4c00 x21: ffff800087b13c9c
    x20: ffff800080a46494 x19: ffff800083da810c x18: 0000000000000004
    [...]
    x5 : ffff800080a46448 x4 : ffff800083da8000 x3 : ffff800080a46494
    x2 : ffff800080a47230 x1 : ffff800083da810c x0 : 0000000000000020
    Call trace:
     regmap_mmio_read32le+0x44/0xa0 (P)
     regmap_mmio_read+0x4c/0x80
     [...]
    Code: 52800400 8b214093 aa1303e1 97f4caf0 (b9400275)
    ---[ end trace 0000000000000000 ]---
    Kernel panic - not syncing: synchronous external abort: Fatal exception

Running this through decodecode gives:

    All code
    ========
       0:   52800400        mov     w0, #0x20                       // #32
       4:   8b214093        add     x19, x4, w1, uxtw
       8:   aa1303e1        mov     x1, x19
       c:   97f4caf0        bl      0xffffffffffd32bcc
      10:*  b9400275        ldr     w21, [x19]              <-- trapping instruction

    Code starting with the faulting instruction
    ===========================================
       0:   b9400275        ldr     w21, [x19]

x19's offset from the base address in /proc/vmallocinfo is 0x10c, which
points to a bad read at physical address 0x4007c10c; I also confirmed
that the preceding memory reads back without issues:

    # head -c 990 /sys/kernel/debug/regmap/dummy-syscon@0x000000004007c000/registers | tail -1
    0104: 00000000
    # head -c 1005 /sys/kernel/debug/regmap/dummy-syscon@0x000000004007c000/registers | tail -1
    0108: 00000000
    # head -c 1020 /sys/kernel/debug/regmap/dummy-syscon@0x000000004007c000/registers | tail -1
    <panic>

Best,
Jared



^ permalink raw reply

* Re: [PATCH v4 2/8] dt-bindings: arm: Add zx297520v3 board binding
From: Rob Herring (Arm) @ 2026-04-17 21:08 UTC (permalink / raw)
  To: Stefan Dösinger
  Cc: linux-kernel, Conor Dooley, Jonathan Corbet, Alexandre Belloni,
	Greg Kroah-Hartman, linux-doc, devicetree, Drew Fustini,
	Linus Walleij, Jiri Slaby, Russell King, soc, Arnd Bergmann,
	Krzysztof Kozlowski, Krzysztof Kozlowski, linux-arm-kernel,
	linux-serial, Shuah Khan
In-Reply-To: <20260416-send-v4-2-e19d02b944ec@gmail.com>


On Thu, 16 Apr 2026 23:19:10 +0300, Stefan Dösinger wrote:
> Add a compatible for boards based on the ZTE zx297520v3 SoC.
> 
> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
> 
> ---
> 
> The list of devices is the devices I have access to for testing. There
> are many more devices based on this board and it is not always easy to
> identify them. Often they are sold without any branding ("4G home
> router") or with mobile carrier branding.
> ---
>  Documentation/devicetree/bindings/arm/zte.yaml | 25 +++++++++++++++++++++++++
>  MAINTAINERS                                    |  1 +
>  2 files changed, 26 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/arm/zte.yaml:19:13: [warning] wrong indentation: expected 14 but found 12 (indentation)

dtschema/dtc warnings/errors:

doc reference errors (make refcheckdocs):

See https://patchwork.kernel.org/project/devicetree/patch/20260416-send-v4-2-e19d02b944ec@gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.



^ permalink raw reply

* Re: [PATCH V13 02/12] PCI: host-generic: Add common helpers for parsing Root Port properties
From: Bjorn Helgaas @ 2026-04-17 19:55 UTC (permalink / raw)
  To: Sherry Sun
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	Frank Li, s.hauer@pengutronix.de, kernel@pengutronix.de,
	festevam@gmail.com, lpieralisi@kernel.org, kwilczynski@kernel.org,
	mani@kernel.org, bhelgaas@google.com, Hongxing Zhu,
	l.stach@pengutronix.de, imx@lists.linux.dev,
	linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <VI0PR04MB1211449884AC3BC8E3711F1AB92202@VI0PR04MB12114.eurprd04.prod.outlook.com>

On Fri, Apr 17, 2026 at 03:17:16AM +0000, Sherry Sun wrote:
> > On Thu, Apr 16, 2026 at 07:14:12PM +0800, Sherry Sun wrote:
> > > Introduce generic helper functions to parse Root Port device
> > > tree nodes and extract common properties like reset GPIOs. This
> > > allows multiple PCI host controller drivers to share the same
> > > parsing logic.
> > >
> > > Define struct pci_host_port to hold common Root Port properties
> > > (currently only reset GPIO descriptor) and add
> > > pci_host_common_parse_ports() to parse Root Port nodes from
> > > device tree.
> > 
> > Are the Root Port and the RC the only possible places for 'reset'
> > GPIO descriptions in DT?  I think PERST# routing is outside the
> > PCIe spec, so it seems like a system could provide a PERST# GPIO
> > routed to any Switch Upstream Port or Endpoint (I assume a PERST#
> > connected to a switch would apply to both the upstream port and
> > the downstream ports).
> 
> Thanks for the feedback. You're right that PERST# routing could
> theoretically be connected to any device in the hierarchy. However,
> for this patch series, I've focused on the most common use case in
> practice: use Root Port level PERST# instead of the legacy Root
> Complex level PERST#.
> 
> Root Port level PERST# - This is the primary target, where each Root
> Port has individual control over devices connected to it.  RC level
> PERST# - Legacy binding support, where a single GPIO controls all
> ports.
> 
> We can extend this framework later if real hardware emerges that
> needs Switch or EP-level PERST# control. I can add a comment
> documenting this limitation if needed.
> 
> BTW, Mani and Rob had some great discussions in dt-schema about
> PERST# and WAKE# sideband signals settings.

> You can check here:
> https://github.com/devicetree-org/dt-schema/issues/168
> https://github.com/devicetree-org/dt-schema/pull/126
> https://github.com/devicetree-org/dt-schema/pull/170

The upshot of all those conversations is that WAKE# and PERST# can be
routed to arbitrary devices independent of the PCI topology.

I think extending host-generic to look for 'reset' in Root Port nodes
is the right thing.  My concern is more about where we store it.  This
patch saves it in a new "pci_host_port" struct, but someday we'll want
a place to save the PERST# GPIOs for several slots behind a switch.
Then we'll have two different ways to save the same information.

WAKE# signals might be more pertinent -- we definitely need to support
multiple WAKE# signals below a single Root Port, and it seems like
PERST# and WAKE# GPIOs should be saved the same place.

I'm wondering if both should go in the pci_dev itself.  I guess the
implication is that a pci_dev->reset GPIO would describe a PERST#
connected to the device *below* the pci_dev, at least for Downstream
Ports.

I don't know about WAKE# signals.  When it's in a connector, there's
probably only a single possible WAKE# per Downstream Port.  But is it
possible have multiple WAKE# signals from a multi-function device
that's on the motherboard?  Saving the WAKE# GPIO in the Downstream
Port wouldn't accommodate that case.


^ permalink raw reply

* Re: [PATCH bpf-next v2] arm32, bpf: Reject BPF-to-BPF calls and callbacks in the JIT
From: patchwork-bot+netdevbpf @ 2026-04-17 19:10 UTC (permalink / raw)
  To: Puranjay Mohan
  Cc: bpf, linux-arm-kernel, jre, ast, daniel, andrii, martin.lau,
	eddyz87, memxor, song, linux, kernel
In-Reply-To: <20260417143353.838911-1-puranjay@kernel.org>

Hello:

This patch was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Fri, 17 Apr 2026 07:33:52 -0700 you wrote:
> The ARM32 BPF JIT does not support BPF-to-BPF function calls
> (BPF_PSEUDO_CALL) or callbacks (BPF_PSEUDO_FUNC), but it does
> not reject them either.
> 
> When a program with subprograms is loaded (e.g. libxdp's XDP
> dispatcher uses __noinline__ subprograms, or any program using
> callbacks like bpf_loop or bpf_for_each_map_elem), the verifier
> invokes bpf_jit_subprogs() which calls bpf_int_jit_compile()
> for each subprogram.
> 
> [...]

Here is the summary with links:
  - [bpf-next,v2] arm32, bpf: Reject BPF-to-BPF calls and callbacks in the JIT
    https://git.kernel.org/bpf/bpf/c/e1d486445af3

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




^ permalink raw reply

* Re: [PATCH] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
From: kernel test robot @ 2026-04-17 18:40 UTC (permalink / raw)
  To: Besar Wicaksono, will, mark.rutland, james.clark
  Cc: oe-kbuild-all, linux-arm-kernel, linux-kernel, linux-tegra,
	treding, jonathanh, vsethi, rwiley, sdonthineni, mochs, nirmoyd,
	skelley, Besar Wicaksono
In-Reply-To: <20260406232034.2566133-1-bwicaksono@nvidia.com>

Hi Besar,

kernel test robot noticed the following build errors:

[auto build test ERROR on soc/for-next]
[also build test ERROR on linus/master v7.0 next-20260416]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Besar-Wicaksono/perf-arm_pmu-Skip-PMCCNTR_EL0-on-NVIDIA-Olympus/20260417-021859
base:   https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next
patch link:    https://lore.kernel.org/r/20260406232034.2566133-1-bwicaksono%40nvidia.com
patch subject: [PATCH] perf/arm_pmu: Skip PMCCNTR_EL0 on NVIDIA Olympus
config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20260418/202604180247.SBxRBqqS-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260418/202604180247.SBxRBqqS-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604180247.SBxRBqqS-lkp@intel.com/

All errors (new ones prefixed by >>):

         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:145:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD'
     145 |         [C(L1D)][C(OP_READ)][C(RESULT_MISS)]    = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:123:65: warning: initialized field overwritten [-Woverride-init]
     123 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR                       0x0041
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:146:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR'
     146 |         [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:123:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[0][1][0]')
     123 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR                       0x0041
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:146:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR'
     146 |         [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:125:65: warning: initialized field overwritten [-Woverride-init]
     125 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR                0x0043
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:147:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR'
     147 |         [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:125:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[0][1][1]')
     125 | #define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR                0x0043
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:147:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR'
     147 |         [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:134:65: warning: initialized field overwritten [-Woverride-init]
     134 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD                         0x004E
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:149:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD'
     149 |         [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:134:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][0][0]')
     134 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD                         0x004E
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:149:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD'
     149 |         [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:135:65: warning: initialized field overwritten [-Woverride-init]
     135 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR                         0x004F
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:150:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR'
     150 |         [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
         |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:135:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][1][0]')
     135 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR                         0x004F
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:150:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR'
     150 |         [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
         |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:132:65: warning: initialized field overwritten [-Woverride-init]
     132 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD                  0x004C
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:151:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD'
     151 |         [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:132:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][0][1]')
     132 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD                  0x004C
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:151:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD'
     151 |         [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:133:65: warning: initialized field overwritten [-Woverride-init]
     133 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR                  0x004D
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:152:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR'
     152 |         [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:133:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[3][1][1]')
     133 | #define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR                  0x004D
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:152:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR'
     152 |         [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:149:65: warning: initialized field overwritten [-Woverride-init]
     149 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD                      0x0060
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:154:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD'
     154 |         [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:149:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[6][0][0]')
     149 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD                      0x0060
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:154:51: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD'
     154 |         [C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
         |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:150:65: warning: initialized field overwritten [-Woverride-init]
     150 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR                      0x0061
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:155:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR'
     155 |         [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
         |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/perf/arm_pmuv3.h:150:65: note: (near initialization for 'armv8_vulcan_perf_cache_map[6][1][0]')
     150 | #define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR                      0x0061
         |                                                                 ^~~~~~
   drivers/perf/arm_pmuv3.c:155:52: note: in expansion of macro 'ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR'
     155 |         [C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
         |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/perf/arm_pmuv3.c:984:26: error: array type has incomplete element type 'struct midr_range'
     984 | static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/perf/arm_pmuv3.c:1000:9: error: implicit declaration of function 'MIDR_ALL_VERSIONS'; did you mean 'MODULE_VERSION'? [-Wimplicit-function-declaration]
    1000 |         MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
         |         ^~~~~~~~~~~~~~~~~
         |         MODULE_VERSION
>> drivers/perf/arm_pmuv3.c:1000:27: error: 'MIDR_NVIDIA_OLYMPUS' undeclared here (not in a function)
    1000 |         MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
         |                           ^~~~~~~~~~~~~~~~~~~
   drivers/perf/arm_pmuv3.c: In function 'armv8pmu_can_use_pmccntr':
>> drivers/perf/arm_pmuv3.c:1042:13: error: implicit declaration of function 'is_midr_in_range_list' [-Wimplicit-function-declaration]
    1042 |         if (is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus))
         |             ^~~~~~~~~~~~~~~~~~~~~
   drivers/perf/arm_pmuv3.c: At top level:
   drivers/perf/arm_pmuv3.c:984:26: warning: 'armv8pmu_avoid_pmccntr_cpus' defined but not used [-Wunused-variable]
     984 | static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +984 drivers/perf/arm_pmuv3.c

   980	
   981	/*
   982	 * List of CPUs that should avoid using PMCCNTR_EL0.
   983	 */
 > 984	static struct midr_range armv8pmu_avoid_pmccntr_cpus[] = {
   985		/*
   986		 * The PMCCNTR_EL0 in Olympus CPU may still increment while in WFI/WFE state.
   987		 * This is an implementation specific behavior and not an erratum.
   988		 *
   989		 * From ARM DDI0487 D14.4:
   990		 *   It is IMPLEMENTATION SPECIFIC whether CPU_CYCLES and PMCCNTR count
   991		 *   when the PE is in WFI or WFE state, even if the clocks are not stopped.
   992		 *
   993		 * From ARM DDI0487 D24.5.2:
   994		 *   All counters are subject to any changes in clock frequency, including
   995		 *   clock stopping caused by the WFI and WFE instructions.
   996		 *   This means that it is CONSTRAINED UNPREDICTABLE whether or not
   997		 *   PMCCNTR_EL0 continues to increment when clocks are stopped by WFI and
   998		 *   WFE instructions.
   999		 */
> 1000		MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
  1001		{}
  1002	};
  1003	
  1004	static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc,
  1005					     struct perf_event *event)
  1006	{
  1007		struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  1008		struct hw_perf_event *hwc = &event->hw;
  1009		unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT;
  1010	
  1011		if (evtype != ARMV8_PMUV3_PERFCTR_CPU_CYCLES)
  1012			return false;
  1013	
  1014		/*
  1015		 * A CPU_CYCLES event with threshold counting cannot use PMCCNTR_EL0
  1016		 * since it lacks threshold support.
  1017		 */
  1018		if (armv8pmu_event_get_threshold(&event->attr))
  1019			return false;
  1020	
  1021		/*
  1022		 * PMCCNTR_EL0 is not affected by BRBE controls like BRBCR_ELx.FZP.
  1023		 * So don't use it for branch events.
  1024		 */
  1025		if (has_branch_stack(event))
  1026			return false;
  1027	
  1028		/*
  1029		 * The PMCCNTR_EL0 increments from the processor clock rather than
  1030		 * the PE clock (ARM DDI0487 L.b D13.1.3) which means it'll continue
  1031		 * counting on a WFI PE if one of its SMT sibling is not idle on a
  1032		 * multi-threaded implementation. So don't use it on SMT cores.
  1033		 */
  1034		if (cpu_pmu->has_smt)
  1035			return false;
  1036	
  1037		/*
  1038		 * On some CPUs, PMCCNTR_EL0 does not match the behavior of CPU_CYCLES
  1039		 * programmable counter, so avoid routing cycles through PMCCNTR_EL0 to
  1040		 * prevent inconsistency in the results.
  1041		 */
> 1042		if (is_midr_in_range_list(armv8pmu_avoid_pmccntr_cpus))
  1043			return false;
  1044	
  1045		return true;
  1046	}
  1047	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply

* Re: [PATCH] pmdomain: core: Fix detach procedure for virtual devices in genpd
From: Geert Uytterhoeven @ 2026-04-17 18:36 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Ulf Hansson, linux-pm, Frank Binns, Matt Coster, Marek Vasut,
	Rafael J . Wysocki, linux-arm-kernel, linux-kernel, stable
In-Reply-To: <20260417111331.158190-1-ulf.hansson@linaro.org>

Hi Ulf,

On Fri, 17 Apr 2026 at 13:13, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> If a device is attached to a PM domain through genpd_dev_pm_attach_by_id(),
> genpd calls pm_runtime_enable() for the corresponding virtual device that
> it registers. While this avoids boilerplate code in drivers, there is no
> corresponding call to pm_runtime_disable() in genpd_dev_pm_detach().
>
> This means these virtual devices are typically detached from its genpd,
> while runtime PM remains enabled for them, which is not how things are
> designed to work. In worst cases it may lead to critical errors, like a
> NULL pointer dereference bug in genpd_runtime_suspend(), which was recently
> reported. For another case, we may end up keeping an unnecessary vote for a
> performance state for the device.
>
> To fix these problems, let's add this missing call to pm_runtime_disable()
> in genpd_dev_pm_detach().
>
> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Fixes: 3c095f32a92b ("PM / Domains: Add support for multi PM domains per device to genpd")
> Cc: stable@vger.kernel.org
> Closes: https://lore.kernel.org/all/CAMuHMdWapT40hV3c+CSBqFOW05aWcV1a6v_NiJYgoYi0i9_PDQ@mail.gmail.com/
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

Thanks for your patch!

This survived more than 160000 bind/unbind attempts[1] on R-Car M3-W
and M3-N, so
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>

> --- a/drivers/pmdomain/core.c
> +++ b/drivers/pmdomain/core.c
> @@ -3089,6 +3089,7 @@ static const struct bus_type genpd_bus_type = {
>  static void genpd_dev_pm_detach(struct device *dev, bool power_off)
>  {
>         struct generic_pm_domain *pd;
> +       bool is_virt_dev;
>         unsigned int i;
>         int ret = 0;
>
> @@ -3098,6 +3099,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
>
>         dev_dbg(dev, "removing from PM domain %s\n", pd->name);
>
> +       /* Check if the device was created by genpd at attach. */
> +       is_virt_dev = dev->bus == &genpd_bus_type;
> +
> +       /* Disable runtime PM if we enabled it at attach. */
> +       if (is_virt_dev)
> +               pm_runtime_disable(dev);
> +
>         /* Drop the default performance state */
>         if (dev_gpd_data(dev)->default_pstate) {
>                 dev_pm_genpd_set_performance_state(dev, 0);
> @@ -3123,7 +3131,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)

Above, out of context, there is an error return.
Should we call pm_runtime_enable() again, to keep the reference count
balanced? Or can we just ignore this? It's probably futile anyway.

>         genpd_queue_power_off_work(pd);
>
>         /* Unregister the device if it was created by genpd. */
> -       if (dev->bus == &genpd_bus_type)
> +       if (is_virt_dev)
>                 device_unregister(dev);
>  }
>
> --
> 2.43.0
>

[1] https://lore.kernel.org/15510cee649959281d9554965cacd0c06531c1f3.1773308898.git.geert+renesas@glider.be/

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


^ permalink raw reply

* Re: [PATCH net] net: dsa: mt7530: fix .get_stats64 sleeping in atomic context
From: Daniel Golle @ 2026-04-17 18:03 UTC (permalink / raw)
  To: Breno Leitao
  Cc: Chester A. Unal, Andrew Lunn, Vladimir Oltean, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
	AngeloGioacchino Del Regno, Russell King, Christian Marangi,
	netdev, linux-kernel, linux-arm-kernel, linux-mediatek,
	Frank Wunderlich, John Crispin
In-Reply-To: <aeJjcoHyezEgUG_Q@gmail.com>

On Fri, Apr 17, 2026 at 10:46:29AM -0700, Breno Leitao wrote:
> On Fri, Apr 17, 2026 at 04:55:57AM +0100, Daniel Golle wrote:
> > @@ -3404,6 +3449,9 @@ EXPORT_SYMBOL_GPL(mt7530_probe_common);
> >  void
> >  mt7530_remove_common(struct mt7530_priv *priv)
> >  {
> > +	if (priv->bus)
> > +		cancel_delayed_work_sync(&priv->stats_work);
> > +
> 
> Shouldn't you cancel the work later, after dsa_unregister_switch()?
> 
> I am wondering if the following race cannot happen:
> 
>  mt7530_remove_common()                  someone reading /proc/net/dev
>     cancel_delayed_work_sync()
>       /* returns: work neither pending
>          nor executing - true at this
>          instant */
>                                           mt7530_get_stats64()
>                                             mod_delayed_work(...)
>                                             /* work is queued again */
>     dsa_unregister_switch()
>     return

Thanks you for pointing this out.
cancel_delayed_work_sync() should be moved after dsa_unregister_switch()
to avoid this kind of race.


^ permalink raw reply

* [PATCH v2 2/2] gpio: xilinx: drop bitmap_complement() where feasible
From: Yury Norov @ 2026-04-17 17:59 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Bartosz Golaszewski,
	Shubhrajyoti Datta, Srinivas Neeli, Michal Simek, Yury Norov,
	linux-gpio, linux-kernel, linux-arm-kernel
  Cc: Yury Norov
In-Reply-To: <20260417175955.375275-1-ynorov@nvidia.com>

The drivers reproduces the following pattern:

	bitmap_complement(tmp, data1, nbits);
	bitmap_and(dst, data2, tmp, nbits);

This can be done in a single pass:

	bitmap_andnot(dst, data2, data1, nbits);

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
 drivers/gpio/gpio-xilinx.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index be4b4d730547..532205175827 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -495,13 +495,11 @@ static void xgpio_irqhandler(struct irq_desc *desc)
 
 	xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, hw);
 
-	bitmap_complement(rising, chip->last_irq_read, 64);
-	bitmap_and(rising, rising, hw, 64);
+	bitmap_andnot(rising, hw, chip->last_irq_read, 64);
 	bitmap_and(rising, rising, chip->enable, 64);
 	bitmap_and(rising, rising, chip->rising_edge, 64);
 
-	bitmap_complement(falling, hw, 64);
-	bitmap_and(falling, falling, chip->last_irq_read, 64);
+	bitmap_andnot(falling, chip->last_irq_read, hw, 64);
 	bitmap_and(falling, falling, chip->enable, 64);
 	bitmap_and(falling, falling, chip->falling_edge, 64);
 
-- 
2.51.0



^ permalink raw reply related

* [PATCH v2 0/2] gpio: drop bitmap_complement() where feasible
From: Yury Norov @ 2026-04-17 17:59 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Bartosz Golaszewski,
	Shubhrajyoti Datta, Srinivas Neeli, Michal Simek, Yury Norov,
	linux-gpio, linux-kernel, linux-arm-kernel
  Cc: Yury Norov

The gpio drivers reproduce the following pattern:

	bitmap_complement(tmp, data1, nbits);
	bitmap_and(dst, data2, tmp, nbits);

This can be done in a single pass:

	bitmap_andnot(dst, data2, data1, nbits);

v1: https://lore.kernel.org/all/20260417033439.318930-1-ynorov@nvidia.com/
v2: 
 - cleanup typos (Michal);
 - split per individual drivers (Andy).

Yury Norov (2):
  gpio: pca953x: drop bitmap_complement() where feasible
  gpio: xilinx: drop bitmap_complement() where feasible

 drivers/gpio/gpio-pca953x.c | 7 ++-----
 drivers/gpio/gpio-xilinx.c  | 6 ++----
 2 files changed, 4 insertions(+), 9 deletions(-)

-- 
2.51.0



^ permalink raw reply

* [PATCH v2 1/2] gpio: pca953x: drop bitmap_complement() where feasible
From: Yury Norov @ 2026-04-17 17:59 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Bartosz Golaszewski,
	Shubhrajyoti Datta, Srinivas Neeli, Michal Simek, Yury Norov,
	linux-gpio, linux-kernel, linux-arm-kernel
  Cc: Yury Norov
In-Reply-To: <20260417175955.375275-1-ynorov@nvidia.com>

The driver reproduces the following pattern:

	bitmap_complement(tmp, data1, nbits);
	bitmap_and(dst, data2, tmp, nbits);

This can be done in a single pass:

	bitmap_andnot(dst, data2, data1, nbits);

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Yury Norov <ynorov@nvidia.com>
---
 drivers/gpio/gpio-pca953x.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 52e96cc5f67b..1fef733fe1f0 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -877,11 +877,9 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 	bitmap_or(irq_mask, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio);
 	bitmap_or(irq_mask, irq_mask, chip->irq_trig_level_high, gc->ngpio);
 	bitmap_or(irq_mask, irq_mask, chip->irq_trig_level_low, gc->ngpio);
-	bitmap_complement(reg_direction, reg_direction, gc->ngpio);
-	bitmap_and(irq_mask, irq_mask, reg_direction, gc->ngpio);
 
 	/* Look for any newly setup interrupt */
-	for_each_set_bit(level, irq_mask, gc->ngpio)
+	for_each_andnot_bit(level, irq_mask, reg_direction, gc->ngpio)
 		pca953x_gpio_direction_input(&chip->gpio_chip, level);
 
 	mutex_unlock(&chip->irq_lock);
@@ -1005,8 +1003,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin
 	bitmap_and(cur_stat, cur_stat, chip->irq_mask, gc->ngpio);
 	bitmap_or(pending, pending, cur_stat, gc->ngpio);
 
-	bitmap_complement(cur_stat, new_stat, gc->ngpio);
-	bitmap_and(cur_stat, cur_stat, reg_direction, gc->ngpio);
+	bitmap_andnot(cur_stat, reg_direction, new_stat, gc->ngpio);
 	bitmap_and(old_stat, cur_stat, chip->irq_trig_level_low, gc->ngpio);
 	bitmap_and(old_stat, old_stat, chip->irq_mask, gc->ngpio);
 	bitmap_or(pending, pending, old_stat, gc->ngpio);
-- 
2.51.0



^ permalink raw reply related

* [RFC PATCH 4/4] firmware: arm_ffa: check pkvm initailised when initailise ffa driver
From: Yeoreum Yun @ 2026-04-17 17:57 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, peterhuewe, jarkko, jgg, sudeep.holla, maz, oupton,
	joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas, will,
	Yeoreum Yun
In-Reply-To: <20260417175759.3191279-1-yeoreum.yun@arm.com>

When pKVM is enabled, the FF-A driver must be initialized after pKVM.
Otherwise, pKVM cannot negotiate the FF-A version or
obtain RX/TX buffer information, leading to failures in FF-A calls.

During FF-A driver initialization, check whether pKVM has been initialized.
If not, defer probing of the FF-A driver.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
 arch/arm64/kvm/arm.c              |  1 +
 drivers/firmware/arm_ffa/driver.c | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 410ffd41fd73..0f517b1c05cd 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -119,6 +119,7 @@ bool is_kvm_arm_initialised(void)
 {
 	return kvm_arm_initialised;
 }
+EXPORT_SYMBOL(is_kvm_arm_initialised);

 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 02c76ac1570b..2647d6554afd 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -42,6 +42,8 @@
 #include <linux/uuid.h>
 #include <linux/xarray.h>

+#include <asm/virt.h>
+
 #include "common.h"

 #define FFA_DRIVER_VERSION	FFA_VERSION_1_2
@@ -2035,6 +2037,16 @@ static int __init ffa_init(void)
 	u32 buf_sz;
 	size_t rxtx_bufsz = SZ_4K;

+	/*
+	 * When pKVM is enabled, the FF-A driver must be initialized
+	 * after pKVM initialization. Otherwise, pKVM cannot negotiate
+	 * the FF-A version or obtain RX/TX buffer information,
+	 * which leads to failures in FF-A calls.
+	 */
+	if (IS_ENABLED(CONFIG_KVM) && is_protected_kvm_enabled() &&
+	    !is_kvm_arm_initialised())
+		return -EPROBE_DEFER;
+
 	ret = ffa_transport_init(&invoke_ffa_fn);
 	if (ret)
 		return ret;
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



^ permalink raw reply related

* [RFC PATCH 3/4] firmware: arm_ffa: revert ffa_init() initcall level to device_initcall
From: Yeoreum Yun @ 2026-04-17 17:57 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, peterhuewe, jarkko, jgg, sudeep.holla, maz, oupton,
	joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas, will,
	Yeoreum Yun
In-Reply-To: <20260417175759.3191279-1-yeoreum.yun@arm.com>

commit 0e0546eabcd6 ("firmware: arm_ffa: Change initcall level of ffa_init() to rootfs_initcall")
changed the initcall level of ffa_init() to rootfs_initcall to address
an issue where IMA could not properly recognize the TPM device.

However, this introduces a problem: pKVM fails to handle any FF-A calls
because it cannot trap the FFA_VERSION call invoked by ffa_init().

Since the IMA init function level has been changed to late_initcall_sync,
there is no longer a need to keep ffa_init() at rootfs_initcall.
Revert it back to device_initcall.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
 drivers/firmware/arm_ffa/driver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index f2f94d4d533e..02c76ac1570b 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -2106,7 +2106,7 @@ static int __init ffa_init(void)
 	kfree(drv_info);
 	return ret;
 }
-rootfs_initcall(ffa_init);
+device_initcall(ffa_init);

 static void __exit ffa_exit(void)
 {
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



^ permalink raw reply related

* [RFC PATCH 2/4] tpm: tpm_crb_ffa: revert defered_probed when tpm_crb_ffa is built-in
From: Yeoreum Yun @ 2026-04-17 17:57 UTC (permalink / raw)
  To: linux-security-module, linux-kernel, linux-integrity,
	linux-arm-kernel, kvmarm
  Cc: paul, jmorris, serge, zohar, roberto.sassu, dmitry.kasatkin,
	eric.snowberg, peterhuewe, jarkko, jgg, sudeep.holla, maz, oupton,
	joey.gouly, suzuki.poulose, yuzenghui, catalin.marinas, will,
	Yeoreum Yun
In-Reply-To: <20260417175759.3191279-1-yeoreum.yun@arm.com>

commit 746d9e9f62a6 ("tpm: tpm_crb_ffa: try to probe tpm_crb_ffa when it's build_in")
probe tpm_crb_ffa forcefully when it's built-in to integrate with IMA.

However, as IMA init function is changed to late_initcall_sync level.
So, this change isn't required anymore.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
 drivers/char/tpm/tpm_crb_ffa.c | 18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
index 99f1c1e5644b..025c4d4b17ca 100644
--- a/drivers/char/tpm/tpm_crb_ffa.c
+++ b/drivers/char/tpm/tpm_crb_ffa.c
@@ -177,23 +177,13 @@ static int tpm_crb_ffa_to_linux_errno(int errno)
  */
 int tpm_crb_ffa_init(void)
 {
-	int ret = 0;
-
-	if (!IS_MODULE(CONFIG_TCG_ARM_CRB_FFA)) {
-		ret = ffa_register(&tpm_crb_ffa_driver);
-		if (ret) {
-			tpm_crb_ffa = ERR_PTR(-ENODEV);
-			return ret;
-		}
-	}
-
 	if (!tpm_crb_ffa)
-		ret = -ENOENT;
+		return -ENOENT;

 	if (IS_ERR_VALUE(tpm_crb_ffa))
-		ret = -ENODEV;
+		return -ENODEV;

-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_crb_ffa_init);

@@ -405,9 +395,7 @@ static struct ffa_driver tpm_crb_ffa_driver = {
 	.id_table = tpm_crb_ffa_device_id,
 };

-#ifdef MODULE
 module_ffa_driver(tpm_crb_ffa_driver);
-#endif

 MODULE_AUTHOR("Arm");
 MODULE_DESCRIPTION("TPM CRB FFA driver");
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}



^ 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