* Re: [PATCH] coresight: ultrasoc-smb: Fix OOB write in smb_sync_perf_buffer()
From: Suzuki K Poulose @ 2026-06-04 9:16 UTC (permalink / raw)
To: Mike Leach, James Clark, Leo Yan, Alexander Shishkin, Qi Liu,
Junhao He, Jonathan Cameron, Junrui Luo
Cc: Suzuki K Poulose, coresight, linux-arm-kernel, linux-kernel,
Yuhao Jiang, stable
In-Reply-To: <SYBPR01MB788156B3380A36835DB22290AF102@SYBPR01MB7881.ausprd01.prod.outlook.com>
On Thu, 04 Jun 2026 15:34:25 +0800, Junrui Luo wrote:
> When the SMB sink is used as a perf AUX sink, smb_update_buffer() calls
> smb_sync_perf_buffer() to copy hardware trace data into the perf AUX ring
> buffer pages. It derives pg_idx = head >> PAGE_SHIFT from @head, which is
> handle->head, and indexes dst_pages[pg_idx]. The pg_idx %= nr_pages
> normalization is only applied after the first loop iteration.
>
> This leaves the initial page index underived from the buffer size, which
> can result in an out-of-bounds write past dst_pages[] when head exceeds
> the AUX buffer size.
>
> [...]
Applied, thanks!
[1/1] coresight: ultrasoc-smb: Fix OOB write in smb_sync_perf_buffer()
https://git.kernel.org/coresight/c/98495b5a4d77
Best regards,
--
Suzuki K Poulose <suzuki.poulose@arm.com>
^ permalink raw reply
* Re: [PATCH v7 05/13] coresight: etm4x: exclude ss_status from drvdata->config
From: Suzuki K Poulose @ 2026-06-04 9:15 UTC (permalink / raw)
To: Yeoreum Yun
Cc: coresight, linux-arm-kernel, linux-kernel, mike.leach,
james.clark, alexander.shishkin, leo.yan, jie.gan
In-Reply-To: <ah1yhaZgddq+8fCW@e129823.arm.com>
On 01/06/2026 12:52, Yeoreum Yun wrote:
> Hi Suzuki,
>
>> On 19/05/2026 16:48, Yeoreum Yun wrote:
>>> The purpose of TRCSSCSRn register is to show status of
>>> the corresponding Single-shot Comparator Control and input supports.
>>> That means writable field's purpose for reset or restore from idle status
>>> not for configuration.
>>>
>>> Therefore, exclude ss_status from drvdata->config and move it to drvdata.
>>
>> TRCSSCSRn has two different types of fields.
>>
>> 1. Capability
>> 2. Status
>>
>> Moving the entire register from "config" to a common dangling place looks
>> like shifting the problem to me.
>>
>> Could we do something like :
>>
>> 1. Split the fields to two.
>> a. Store only the capability information in etmv4_caps. Bits[4:0]
>> b. Store the Status bit in drvdata->config , as it is really matters
>> to the session ? Bits[31:30]
>>
>> Add a helper to write/read the TRCSSSRn which would apply/mask the bits from
>> drvdata->etmv4_caps->fields to the Status/Pending
>
> Well. I'm not sure about whether we need to this.
> When I remind of discussion with Leo, The Status and Pending bits should
> be preserved in the *same* session theoretically However, Unitil today
> In case of *perf* it doesn't keep but always cleared at the time of
> resuming session and this behavior haven't reported any issue yet.
>
> TBH, I don't have any idea how perf could utilise those bits except
> the current use case for the sysfs to show the bit via *status* file.
>
> Futhermore, IMHO, config isn't good place for the Status/Pending bits
> since those fields are not *configrable* fields so I think it would be
> better to locate saving information for the status and pending bits on
> drvdata or by defining other fields.
>
> But, until we find some usage of those bits in perf, I think we can
> delay this separation you suggest and it might be better to keep as-is
> for the purpose of showing the status/pending bits when sysfs session is
> finished.
>
> Am I missing something?
Agreed, this can be cleaned up in a separate series.
Suzuki
>
>>
>> Suzuki
>>
>>>
>>> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
>>> ---
>>> .../hwtracing/coresight/coresight-etm4x-cfg.c | 1 -
>>> .../hwtracing/coresight/coresight-etm4x-core.c | 16 +++++++++-------
>>> .../hwtracing/coresight/coresight-etm4x-sysfs.c | 10 +++++-----
>>> drivers/hwtracing/coresight/coresight-etm4x.h | 7 ++++++-
>>> 4 files changed, 20 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
>>> index e1a59b434505..9b4947d75fde 100644
>>> --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
>>> @@ -86,7 +86,6 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
>>> off_mask = (offset & GENMASK(11, 5));
>>> do {
>>> CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask);
>>> - CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask);
>>> CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask);
>>> } while (0);
>>> } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> index 53fbc4826628..7783c97b53e8 100644
>>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> @@ -95,7 +95,7 @@ static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
>>> const struct etmv4_caps *caps = &drvdata->caps;
>>> return (n < caps->nr_ss_cmp) && caps->nr_pe_cmp &&
>>> - (drvdata->config.ss_status[n] & TRCSSCSRn_PC);
>>> + (drvdata->ss_status[n] & TRCSSCSRn_PC);
>>> }
>>> u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit)
>>> @@ -571,11 +571,11 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>>> etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i));
>>> for (i = 0; i < caps->nr_ss_cmp; i++) {
>>> - /* always clear status bit on restart if using single-shot */
>>> + /* always clear status and pending bits on restart if using single-shot */
>>> if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
>>> - config->ss_status[i] &= ~TRCSSCSRn_STATUS;
>>> + drvdata->ss_status[i] &= ~(TRCSSCSRn_STATUS | TRCSSCSRn_PENDING);
>>> etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
>>> - etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
>>> + etm4x_relaxed_write32(csa, drvdata->ss_status[i], TRCSSCSRn(i));
>>> if (etm4x_sspcicrn_present(drvdata, i))
>>> etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
>>> }
>>> @@ -772,6 +772,7 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
>>> /* Clear configuration from previous run */
>>> memset(config, 0, sizeof(struct etmv4_config));
>>> +
>>> if (attr->exclude_kernel)
>>> config->mode = ETM_MODE_EXCL_KERN;
>>> @@ -1064,7 +1065,7 @@ static void etm4_disable_hw(struct etmv4_drvdata *drvdata)
>>> /* read the status of the single shot comparators */
>>> for (i = 0; i < caps->nr_ss_cmp; i++) {
>>> - config->ss_status[i] =
>>> + drvdata->ss_status[i] =
>>> etm4x_relaxed_read32(csa, TRCSSCSRn(i));
>>> }
>>> @@ -1497,8 +1498,9 @@ static void etm4_init_arch_data(void *info)
>>> */
>>> caps->nr_ss_cmp = FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4);
>>> for (i = 0; i < caps->nr_ss_cmp; i++) {
>>> - drvdata->config.ss_status[i] =
>>> - etm4x_relaxed_read32(csa, TRCSSCSRn(i));
>>> + drvdata->ss_status[i] = etm4x_relaxed_read32(csa, TRCSSCSRn(i));
>>> + drvdata->ss_status[i] &= (TRCSSCSRn_PC | TRCSSCSRn_DV |
>>> + TRCSSCSRn_DA | TRCSSCSRn_INST);
>>> }
>>> /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */
>>> caps->numcidc = FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4);
>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
>>> index 7de3c58a47b4..71e95d152ee6 100644
>>> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
>>> @@ -1829,8 +1829,8 @@ static ssize_t sshot_ctrl_store(struct device *dev,
>>> raw_spin_lock(&drvdata->spinlock);
>>> idx = config->ss_idx;
>>> config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
>>> - /* must clear bit 31 in related status register on programming */
>>> - config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
>>> + /* must clear bit 31 and 30 in related status register on programming */
>>> + drvdata->ss_status[idx] &= ~(TRCSSCSRn_STATUS | TRCSSCSRn_PENDING);
>>> raw_spin_unlock(&drvdata->spinlock);
>>> return size;
>>> }
>>> @@ -1844,7 +1844,7 @@ static ssize_t sshot_status_show(struct device *dev,
>>> struct etmv4_config *config = &drvdata->config;
>>> raw_spin_lock(&drvdata->spinlock);
>>> - val = config->ss_status[config->ss_idx];
>>> + val = drvdata->ss_status[config->ss_idx];
>>> raw_spin_unlock(&drvdata->spinlock);
>>> return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>>> }
>>> @@ -1879,8 +1879,8 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
>>> raw_spin_lock(&drvdata->spinlock);
>>> idx = config->ss_idx;
>>> config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
>>> - /* must clear bit 31 in related status register on programming */
>>> - config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
>>> + /* must clear bit 31 and 30 in related status register on programming */
>>> + drvdata->ss_status[idx] &= ~(TRCSSCSRn_STATUS | TRCSSCSRn_PENDING);
>>> raw_spin_unlock(&drvdata->spinlock);
>>> return size;
>>> }
>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
>>> index 6d4fbae78448..43db1eb6f8cd 100644
>>> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
>>> @@ -213,6 +213,7 @@
>>> #define TRCACATRn_EXLEVEL_MASK GENMASK(14, 8)
>>> #define TRCSSCSRn_STATUS BIT(31)
>>> +#define TRCSSCSRn_PENDING BIT(30)
>>> #define TRCSSCCRn_SAC_ARC_RST_MASK GENMASK(24, 0)
>>> #define TRCSSPCICRn_PC_MASK GENMASK(7, 0)
>>> @@ -730,6 +731,9 @@ static inline u32 etm4_res_sel_pair(u8 res_sel_idx)
>>> #define ETM_DEFAULT_ADDR_COMP 0
>>> #define TRCSSCSRn_PC BIT(3)
>>> +#define TRCSSCSRn_DV BIT(2)
>>> +#define TRCSSCSRn_DA BIT(1)
>>> +#define TRCSSCSRn_INST BIT(0)
>>> /* PowerDown Control Register bits */
>>> #define TRCPDCR_PU BIT(3)
>>> @@ -978,7 +982,6 @@ struct etmv4_config {
>>> u32 res_ctrl[ETM_MAX_RES_SEL]; /* TRCRSCTLRn */
>>> u8 ss_idx;
>>> u32 ss_ctrl[ETM_MAX_SS_CMP];
>>> - u32 ss_status[ETM_MAX_SS_CMP];
>>> u32 ss_pe_cmp[ETM_MAX_SS_CMP];
>>> u8 addr_idx;
>>> u64 addr_val[ETM_MAX_SINGLE_ADDR_CMP];
>>> @@ -1073,6 +1076,7 @@ struct etmv4_save_state {
>>> * @config: structure holding configuration parameters.
>>> * @save_state: State to be preserved across power loss
>>> * @paused: Indicates if the trace unit is paused.
>>> + * @ss_status: The status of the corresponding single-shot comparator.
>>> * @arch_features: Bitmap of arch features of etmv4 devices.
>>> */
>>> struct etmv4_drvdata {
>>> @@ -1092,6 +1096,7 @@ struct etmv4_drvdata {
>>> u64 trfcr;
>>> struct etmv4_config config;
>>> struct etmv4_save_state *save_state;
>>> + u32 ss_status[ETM_MAX_SS_CMP];
>>> DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
>>> };
>>
>
^ permalink raw reply
* Re: [PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Suzuki K Poulose @ 2026-06-04 9:18 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm), linux-coco, linux-arm-kernel,
linux-kernel
Cc: Catalin Marinas, Greg KH, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Will Deacon,
Steven Price
In-Reply-To: <20260527100233.428018-4-aneesh.kumar@kernel.org>
On 27/05/2026 11:02, Aneesh Kumar K.V (Arm) wrote:
> The Arm CCA guest TSM provider currently binds through the arm-cca-dev
> platform device. Like arm-smccc-trng, this device is not an independent
> platform resource; it is a software representation of the RSI firmware
> service discovered through SMCCC.
>
> Move RSI discovery into the SMCCC firmware driver. When the SMCCC conduit
> is SMC and the RSI ABI version check succeeds, create an arm-rsi-dev SMCCC
> device. Convert the Arm CCA guest TSM provider to an SMCCC driver so it
> binds to that discovered RSI service and keeps module autoloading through
> the SMCCC device id table.
>
> Keep the old arm-cca-dev platform-device registration for now. Userspace
> has used that device as a Realm-guest indicator, so removing it is left to
> a follow-up patch that adds a replacement sysfs ABI.
>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> arch/arm64/include/asm/rsi.h | 2 +-
> arch/arm64/kernel/rsi.c | 2 +-
> drivers/firmware/smccc/Makefile | 4 ++
> drivers/firmware/smccc/rmm.c | 25 ++++++++
> drivers/firmware/smccc/rmm.h | 17 ++++++
> drivers/firmware/smccc/smccc.c | 8 +++
> drivers/virt/coco/arm-cca-guest/Kconfig | 1 +
> drivers/virt/coco/arm-cca-guest/Makefile | 2 +
> .../{arm-cca-guest.c => arm-cca.c} | 60 +++++++++----------
> 9 files changed, 89 insertions(+), 32 deletions(-)
> create mode 100644 drivers/firmware/smccc/rmm.c
> create mode 100644 drivers/firmware/smccc/rmm.h
> rename drivers/virt/coco/arm-cca-guest/{arm-cca-guest.c => arm-cca.c} (85%)
>
> diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
> index 88b50d660e85..2d2d363aaaee 100644
> --- a/arch/arm64/include/asm/rsi.h
> +++ b/arch/arm64/include/asm/rsi.h
> @@ -10,7 +10,7 @@
> #include <linux/jump_label.h>
> #include <asm/rsi_cmds.h>
>
> -#define RSI_PDEV_NAME "arm-cca-dev"
> +#define RSI_DEV_NAME "arm-rsi-dev"
>
> DECLARE_STATIC_KEY_FALSE(rsi_present);
>
> diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
> index 92160f2e57ff..da440f71bb64 100644
> --- a/arch/arm64/kernel/rsi.c
> +++ b/arch/arm64/kernel/rsi.c
> @@ -161,7 +161,7 @@ void __init arm64_rsi_init(void)
> }
>
> static struct platform_device rsi_dev = {
> - .name = RSI_PDEV_NAME,
> + .name = "arm-cca-dev",
> .id = PLATFORM_DEVID_NONE
> };
>
> diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile
> index 40d19144a860..33c850aaff4d 100644
> --- a/drivers/firmware/smccc/Makefile
> +++ b/drivers/firmware/smccc/Makefile
> @@ -2,3 +2,7 @@
> #
> obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o
> obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o
> +
> +ifeq ($(CONFIG_HAVE_ARM_SMCCC_DISCOVERY),y)
> +obj-$(CONFIG_ARM64) += rmm.o
> +endif
> diff --git a/drivers/firmware/smccc/rmm.c b/drivers/firmware/smccc/rmm.c
> new file mode 100644
> index 000000000000..d572f47e955c
> --- /dev/null
> +++ b/drivers/firmware/smccc/rmm.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Arm Limited
> + */
> +
> +#include <linux/arm-smccc-bus.h>
> +#include <linux/err.h>
> +#include <linux/printk.h>
> +
> +#include "rmm.h"
> +
> +void __init register_rsi_device(void)
minor nit: Could we rename this global symbol to scope it under rmm ?
perhaps, rmm_register_rsi_device()?
> +{
> + unsigned long ret;
> +
> + if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
> + return;
> +
> + ret = rsi_request_version(RSI_ABI_VERSION, NULL, NULL);
> + if (ret != RSI_SUCCESS)
> + return;
> +
> + if (IS_ERR(arm_smccc_device_register(RSI_DEV_NAME)))
> + pr_err("%s: could not register device\n", RSI_DEV_NAME);
> +}
> diff --git a/drivers/firmware/smccc/rmm.h b/drivers/firmware/smccc/rmm.h
> new file mode 100644
> index 000000000000..627098e2ae1f
> --- /dev/null
> +++ b/drivers/firmware/smccc/rmm.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _SMCCC_RMM_H
> +#define _SMCCC_RMM_H
> +
> +#include <linux/init.h>
> +
> +#ifdef CONFIG_ARM64
> +#include <linux/arm-smccc-bus.h>
> +#include <asm/rsi_cmds.h>
minor nit: Could the header files be moved to rmm.c ?
> +void __init register_rsi_device(void);
> +#else
> +
> +static inline void __init register_rsi_device(void)
> +{
> +}
> +#endif
> +#endif
> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index 6d260354d0f9..888e7f1d6f86 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
> @@ -15,6 +15,8 @@
>
> #include <asm/archrandom.h>
>
> +#include "rmm.h"
> +
> static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
> static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
> static DEFINE_IDA(arm_smccc_bus_id);
> @@ -240,6 +242,12 @@ subsys_initcall(arm_smccc_bus_init);
>
> static int __init smccc_devices_init(void)
> {
> + /*
> + * Register the RMI and RSI devices only when firmware exposes
> + * the required SMCCC function IDs at a supported revision.
> + */
> + register_rsi_device();
nit: We don't have RMI devices yet ? Do we want to make it
rmm_register_devices();
instead ?
> +
> if (smccc_trng_available) {
> struct arm_smccc_device *sdev;
>
> diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/arm-cca-guest/Kconfig
> index 3f0f013f03f1..ad7538750c5a 100644
> --- a/drivers/virt/coco/arm-cca-guest/Kconfig
> +++ b/drivers/virt/coco/arm-cca-guest/Kconfig
> @@ -1,6 +1,7 @@
> config ARM_CCA_GUEST
> tristate "Arm CCA Guest driver"
> depends on ARM64
> + depends on HAVE_ARM_SMCCC_DISCOVERY
> select TSM_REPORTS
> help
> The driver provides userspace interface to request and
> diff --git a/drivers/virt/coco/arm-cca-guest/Makefile b/drivers/virt/coco/arm-cca-guest/Makefile
> index 69eeba08e98a..75a120e24fda 100644
> --- a/drivers/virt/coco/arm-cca-guest/Makefile
> +++ b/drivers/virt/coco/arm-cca-guest/Makefile
> @@ -1,2 +1,4 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-$(CONFIG_ARM_CCA_GUEST) += arm-cca-guest.o
> +
> +arm-cca-guest-y += arm-cca.o
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca.c
> similarity index 85%
> rename from drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> rename to drivers/virt/coco/arm-cca-guest/arm-cca.c
> index 66d00b6ceb78..8d5a09bd772a 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/arm-smccc.h>
> +#include <linux/arm-smccc-bus.h>
> #include <linux/cc_platform.h>
> #include <linux/kernel.h>
> #include <linux/mod_devicetable.h>
> @@ -182,52 +183,51 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
> return ret;
> }
>
> -static const struct tsm_report_ops arm_cca_tsm_ops = {
> +static const struct tsm_report_ops arm_cca_tsm_report_ops = {
> .name = KBUILD_MODNAME,
> .report_new = arm_cca_report_new,
> };
>
Would you like to either :
1) Call out renaming the existing cca_tsm to reflect cca_tsm_report
in the commit description ?
OR
2) Split the renaming of the "report" stuff in a follow up patch ?
Rest looks fine by me.
Suzuki
> -/**
> - * arm_cca_guest_init - Register with the Trusted Security Module (TSM)
> - * interface.
> - *
> - * Return:
> - * * %0 - Registered successfully with the TSM interface.
> - * * %-ENODEV - The execution context is not an Arm Realm.
> - * * %-EBUSY - Already registered.
> - */
> -static int __init arm_cca_guest_init(void)
> +static void unregister_cca_tsm_report(void *data)
> +{
> + tsm_report_unregister(&arm_cca_tsm_report_ops);
> +}
> +
> +static int cca_tsm_probe(struct arm_smccc_device *sdev)
> {
> int ret;
>
> if (!is_realm_world())
> return -ENODEV;
>
> - ret = tsm_report_register(&arm_cca_tsm_ops, NULL);
> - if (ret < 0)
> - pr_err("Error %d registering with TSM\n", ret);
> + ret = tsm_report_register(&arm_cca_tsm_report_ops, NULL);
> + if (ret < 0) {
> + dev_err_probe(&sdev->dev, ret, "Error registering with TSM\n");
> + return ret;
> + }
>
> - return ret;
> -}
> -module_init(arm_cca_guest_init);
> + ret = devm_add_action_or_reset(&sdev->dev, unregister_cca_tsm_report,
> + NULL);
> + if (ret < 0) {
> + dev_err_probe(&sdev->dev, ret, "Error registering devm action\n");
> + return ret;
> + }
>
> -/**
> - * arm_cca_guest_exit - unregister with the Trusted Security Module (TSM)
> - * interface.
> - */
> -static void __exit arm_cca_guest_exit(void)
> -{
> - tsm_report_unregister(&arm_cca_tsm_ops);
> + return 0;
> }
> -module_exit(arm_cca_guest_exit);
>
> -/* modalias, so userspace can autoload this module when RSI is available */
> -static const struct platform_device_id arm_cca_match[] __maybe_unused = {
> - { RSI_PDEV_NAME, 0},
> - { }
> +static const struct arm_smccc_device_id cca_tsm_id_table[] = {
> + { .name = RSI_DEV_NAME },
> + {}
> };
> +MODULE_DEVICE_TABLE(arm_smccc, cca_tsm_id_table);
>
> -MODULE_DEVICE_TABLE(platform, arm_cca_match);
> +static struct arm_smccc_driver cca_tsm_driver = {
> + .name = KBUILD_MODNAME,
> + .probe = cca_tsm_probe,
> + .id_table = cca_tsm_id_table,
> +};
> +module_arm_smccc_driver(cca_tsm_driver);
> MODULE_AUTHOR("Sami Mujawar <sami.mujawar@arm.com>");
> MODULE_DESCRIPTION("Arm CCA Guest TSM Driver");
> MODULE_LICENSE("GPL");
^ permalink raw reply
* Re: [PATCH 3/4] arm64: mte: Disregard the zero page explicitly for manipulating tags
From: Catalin Marinas @ 2026-06-04 9:19 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, linux-kernel, will, maz, Ard Biesheuvel,
Kevin Brodsky, Mark Brown, David Hildenbrand
In-Reply-To: <20260603160949.3372482-9-ardb+git@google.com>
On Wed, Jun 03, 2026 at 06:09:53PM +0200, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
>
> The zero page is conceptually immutable, and will be moved into .rodata
> to prevent inadvertent corruption.
>
> Prepare the MTE code for this, by ensuring that the zero page is never
> taken into account for tag manipulation, given that those actions will
> no longer be permitted on the read-only alias of .rodata in the linear
> map.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
> arch/arm64/include/asm/mte.h | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
> index 7f7b97e09996..093b34944aee 100644
> --- a/arch/arm64/include/asm/mte.h
> +++ b/arch/arm64/include/asm/mte.h
> @@ -80,6 +80,11 @@ static inline bool page_mte_tagged(struct page *page)
> */
> static inline bool try_page_mte_tagging(struct page *page)
> {
> + extern struct page *__zero_page;
> +
> + if (page == __zero_page)
> + return false;
Better as is_zero_page()
> +
> VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));
>
> if (!test_and_set_bit(PG_mte_lock, &page->flags.f))
Some form of this fix should have:
Fixes: f620d66af316 ("arm64: mte: Do not flag the zero page as PG_mte_tagged")
Cc: <stable@vger.kernel.org> # 5.10.x
The current mainline assumption is that mapping the zero page in user
space is always mapped with pte_special() and we skip the MTE tag
zeroing (and PG flag setting). However, the above commit missed the KVM
kvm_s2_fault_map() -> sanitise_mte_tags() path and we don't have a form
of pte_special() for stage 2 mappings.
I'm more inclined to go with a specific test in the KVM path. It matches
the stage 1 where we skip the actual tagging. We could add a
VM_WARN_ONCE in try_page_mte_tagging() to trap future changes.
-------------8<-----------------------
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index d089c107d9b7..445d6cf035c9 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1479,6 +1479,11 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,
if (!kvm_has_mte(kvm))
return;
+ if (is_zero_pfn(pfn)) {
+ WARN_ON_ONCE(nr_pages != 1);
+ return;
+ }
+
if (folio_test_hugetlb(folio)) {
/* Hugetlb has MTE flags set on head page only */
if (folio_try_hugetlb_mte_tagging(folio)) {
--
Catalin
^ permalink raw reply related
* Re: [PATCH net-next v9 6/6] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration
From: Lorenzo Bianconi @ 2026-06-04 9:20 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Madhur Agrawal
In-Reply-To: <20260603-airoha-eth-multi-serdes-v9-6-5d476bc2f426@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 7479 bytes --]
On Jun 03, Lorenzo Bianconi wrote:
> The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN
> MAC addresses. These registers are used during FE hw acceleration to
> determine whether received traffic is destined to this host (L3 traffic)
> or should be switched to another device (L2 traffic).
> The SoC hardware design assumes all interfaces configured as LAN (or WAN)
> share the MAC address MSBs, which are programmed into the
> REG_FE_{LAN,WAN}_MAC_H register. The LSBs of 'local' mac addresses can be
> expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX
> registers. In order to properly accelerate the traffic, FE module requires
> the user to configure the REG_FE_{LAN,WAN}_MAC_H register respecting this
> limitation. Please note a misconfiguration in REG_FE_{LAN,WAN}_MAC_H
> will still allow the user to log into the device for debugging.
> Previously, only a single interface was considered when programming these
> registers. Extend the logic to derive the correct minimum and maximum
> values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are
> configured as LAN or WAN. Since this functionality was not available
> before this series, no regression is introduced.
Commenting on sashiko's report:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260603-airoha-eth-multi-serdes-v9-0-5d476bc2f426%40kernel.org
- How does this validation interact with the init path?
In airoha_alloc_gdm_device(), interfaces lacking a DT MAC fall back to
eth_hw_addr_random(), and airoha_dev_init() calls airoha_set_macaddr()
but discards the int return, so a netdev whose initial MAC would fail
the new MSB check still proceeds to register and reaches NETREG_REGISTERED.
- This is done on purpose to not block the device probe and allow the user
to log into the system, and based on the syslog, fix the issue manually.
Regards,
Lorenzo
>
> Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 77 ++++++++++++++++++++++++++++----
> drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
> drivers/net/ethernet/airoha/airoha_ppe.c | 4 +-
> 3 files changed, 71 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 64ee526da241..8f2608293bb7 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -71,20 +71,76 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
> airoha_qdma_set_irqmask(irq_bank, index, mask, 0);
> }
>
> -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> {
> + u8 ref_addr[ETH_ALEN] __aligned(2);
> struct airoha_eth *eth = dev->eth;
> - u32 val, reg;
> + u32 reg, val, lmin, lmax;
> + int i;
> +
> + eth_zero_addr(ref_addr);
> + lmin = (addr[3] << 16) | (addr[4] << 8) | addr[5];
> + lmax = lmin;
> +
> + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> + struct airoha_gdm_port *port = eth->ports[i];
> + int j;
> +
> + if (!port)
> + continue;
> +
> + for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
> + struct airoha_gdm_dev *iter_dev;
> + struct net_device *netdev;
> +
> + iter_dev = port->devs[j];
> + if (!iter_dev || iter_dev == dev)
> + continue;
> +
> + if (airoha_is_lan_gdm_dev(iter_dev) !=
> + airoha_is_lan_gdm_dev(dev))
> + continue;
> +
> + netdev = netdev_from_priv(iter_dev);
> + if (netdev->reg_state != NETREG_REGISTERED)
> + continue;
> +
> + ether_addr_copy(ref_addr, netdev->dev_addr);
> + val = (netdev->dev_addr[3] << 16) |
> + (netdev->dev_addr[4] << 8) | netdev->dev_addr[5];
> + if (val < lmin)
> + lmin = val;
> + if (val > lmax)
> + lmax = val;
> + }
> + }
> +
> + if (!is_zero_ether_addr(ref_addr) && memcmp(ref_addr, addr, 3)) {
> + /* According to the HW design, hw mac address MSBs must be
> + * the same for each net_device with the same LAN/WAN
> + * configuration.
> + */
> + struct net_device *netdev = netdev_from_priv(dev);
> +
> + dev_warn(eth->dev,
> + "%s: wrong mac addr, MSBs must be %02x:%02x:%02x\n",
> + netdev->name, ref_addr[0], ref_addr[1],
> + ref_addr[2]);
> + dev_warn(eth->dev, "FE hw forwarding won't work properly\n");
> +
> + return -EINVAL;
> + }
>
> reg = airoha_is_lan_gdm_dev(dev) ? REG_FE_LAN_MAC_H : REG_FE_WAN_MAC_H;
> val = (addr[0] << 16) | (addr[1] << 8) | addr[2];
> airoha_fe_wr(eth, reg, val);
>
> - val = (addr[3] << 16) | (addr[4] << 8) | addr[5];
> - airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val);
> - airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val);
> + airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), lmin);
> + airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), lmax);
>
> - airoha_ppe_init_upd_mem(dev);
> + airoha_ppe_init_upd_mem(dev, addr);
> +
> + return 0;
> }
>
> static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
> @@ -1826,13 +1882,18 @@ static int airoha_dev_stop(struct net_device *netdev)
> static int airoha_dev_set_macaddr(struct net_device *netdev, void *p)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct sockaddr *addr = p;
> int err;
>
> - err = eth_mac_addr(netdev, p);
> + err = eth_prepare_mac_addr_change(netdev, p);
> if (err)
> return err;
>
> - airoha_set_macaddr(dev, netdev->dev_addr);
> + err = airoha_set_macaddr(dev, addr->sa_data);
> + if (err)
> + return err;
> +
> + eth_commit_mac_addr_change(netdev, p);
>
> return 0;
> }
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 3e8262f583a7..8f42973f9cf5 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -683,7 +683,7 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data);
> int airoha_ppe_init(struct airoha_eth *eth);
> void airoha_ppe_deinit(struct airoha_eth *eth);
> -void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev);
> +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr);
> u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe);
> struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
> u32 hash);
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index f54622904733..91bcc55a6ac6 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -1487,12 +1487,10 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan);
> }
>
> -void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev)
> +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr)
> {
> - struct net_device *netdev = netdev_from_priv(dev);
> struct airoha_gdm_port *port = dev->port;
> struct airoha_eth *eth = dev->eth;
> - const u8 *addr = netdev->dev_addr;
> u32 val;
>
> val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
>
> --
> 2.54.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Sudeep Holla @ 2026-06-04 9:21 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: linux-coco, linux-arm-kernel, linux-kernel, Catalin Marinas,
Sudeep Holla, Greg KH, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Will Deacon, Steven Price,
Suzuki K Poulose
In-Reply-To: <20260527100233.428018-4-aneesh.kumar@kernel.org>
On Wed, May 27, 2026 at 03:32:32PM +0530, Aneesh Kumar K.V (Arm) wrote:
> The Arm CCA guest TSM provider currently binds through the arm-cca-dev
> platform device. Like arm-smccc-trng, this device is not an independent
> platform resource; it is a software representation of the RSI firmware
> service discovered through SMCCC.
>
> Move RSI discovery into the SMCCC firmware driver. When the SMCCC conduit
> is SMC and the RSI ABI version check succeeds, create an arm-rsi-dev SMCCC
> device. Convert the Arm CCA guest TSM provider to an SMCCC driver so it
> binds to that discovered RSI service and keeps module autoloading through
> the SMCCC device id table.
>
> Keep the old arm-cca-dev platform-device registration for now. Userspace
> has used that device as a Realm-guest indicator, so removing it is left to
> a follow-up patch that adds a replacement sysfs ABI.
>
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> arch/arm64/include/asm/rsi.h | 2 +-
> arch/arm64/kernel/rsi.c | 2 +-
> drivers/firmware/smccc/Makefile | 4 ++
> drivers/firmware/smccc/rmm.c | 25 ++++++++
> drivers/firmware/smccc/rmm.h | 17 ++++++
> drivers/firmware/smccc/smccc.c | 8 +++
> drivers/virt/coco/arm-cca-guest/Kconfig | 1 +
> drivers/virt/coco/arm-cca-guest/Makefile | 2 +
> .../{arm-cca-guest.c => arm-cca.c} | 60 +++++++++----------
> 9 files changed, 89 insertions(+), 32 deletions(-)
> create mode 100644 drivers/firmware/smccc/rmm.c
> create mode 100644 drivers/firmware/smccc/rmm.h
> rename drivers/virt/coco/arm-cca-guest/{arm-cca-guest.c => arm-cca.c} (85%)
>
> diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
> index 88b50d660e85..2d2d363aaaee 100644
> --- a/arch/arm64/include/asm/rsi.h
> +++ b/arch/arm64/include/asm/rsi.h
> @@ -10,7 +10,7 @@
> #include <linux/jump_label.h>
> #include <asm/rsi_cmds.h>
>
> -#define RSI_PDEV_NAME "arm-cca-dev"
> +#define RSI_DEV_NAME "arm-rsi-dev"
>
> DECLARE_STATIC_KEY_FALSE(rsi_present);
>
> diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
> index 92160f2e57ff..da440f71bb64 100644
> --- a/arch/arm64/kernel/rsi.c
> +++ b/arch/arm64/kernel/rsi.c
> @@ -161,7 +161,7 @@ void __init arm64_rsi_init(void)
> }
>
> static struct platform_device rsi_dev = {
> - .name = RSI_PDEV_NAME,
> + .name = "arm-cca-dev",
> .id = PLATFORM_DEVID_NONE
> };
>
> diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile
> index 40d19144a860..33c850aaff4d 100644
> --- a/drivers/firmware/smccc/Makefile
> +++ b/drivers/firmware/smccc/Makefile
> @@ -2,3 +2,7 @@
> #
> obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o
> obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o
> +
> +ifeq ($(CONFIG_HAVE_ARM_SMCCC_DISCOVERY),y)
> +obj-$(CONFIG_ARM64) += rmm.o
> +endif
> diff --git a/drivers/firmware/smccc/rmm.c b/drivers/firmware/smccc/rmm.c
> new file mode 100644
> index 000000000000..d572f47e955c
> --- /dev/null
> +++ b/drivers/firmware/smccc/rmm.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Arm Limited
> + */
> +
> +#include <linux/arm-smccc-bus.h>
> +#include <linux/err.h>
> +#include <linux/printk.h>
> +
> +#include "rmm.h"
> +
> +void __init register_rsi_device(void)
> +{
> + unsigned long ret;
> +
> + if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
> + return;
> +
> + ret = rsi_request_version(RSI_ABI_VERSION, NULL, NULL);
> + if (ret != RSI_SUCCESS)
> + return;
> +
> + if (IS_ERR(arm_smccc_device_register(RSI_DEV_NAME)))
> + pr_err("%s: could not register device\n", RSI_DEV_NAME);
> +}
OK, I had something else in my mind when I started looking at 1/4. I didn't
expect each device added on this bus comes up with it's own way to enumerate
it. IMO, it defeats the purpose of building the smccc bus. We may find the
specs for each feature deviated a bit but we can have a generic probe
IMO, let's try that before exploring per feature probe function.
I have a brief sketch of what I think we should aim for(uncompiled/untested)
below. Let me know if that makes sense. I just based it on your bus code.
Regards,
Sudeep
-->8
diff --git c/drivers/firmware/smccc/smccc.c w/drivers/firmware/smccc/smccc.c
index 695c920a8087..450605ddfab6 100644
--- c/drivers/firmware/smccc/smccc.c
+++ w/drivers/firmware/smccc/smccc.c
@@ -9,21 +9,58 @@
#include <linux/init.h>
#include <linux/arm-smccc.h>
#include <linux/kernel.h>
-#include <linux/platform_device.h>
#include <linux/arm-smccc-bus.h>
#include <linux/idr.h>
#include <linux/slab.h>
-#include <asm/archrandom.h>
-
static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
static DEFINE_IDA(arm_smccc_bus_id);
-bool __ro_after_init smccc_trng_available = false;
+struct smccc_device_info {
+ u32 func_id;
+ bool requires_smc;
+ unsigned long min_return;
+ const char *device_name;
+};
+
+bool __ro_after_init smccc_trng_available;
s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED;
s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED;
+static const struct smccc_device_info smccc_devices[] __initconst = {
+ {
+ .func_id = ARM_SMCCC_TRNG_VERSION,
+ .requires_smc = false,
+ .min_return = ARM_SMCCC_TRNG_MIN_VERSION,
+ .device_name = "arm-smccc-trng",
+ },
+};
+
+static bool __init
+smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
+{
+ struct arm_smccc_res res;
+ unsigned long ret;
+
+ if (!IS_ENABLED(CONFIG_ARM64))
+ return false;
+
+ if (smccc_conduit == SMCCC_CONDUIT_NONE)
+ return false;
+
+ if (smccc_dev->requires_smc && smccc_conduit != SMCCC_CONDUIT_SMC)
+ return false;
+
+ arm_smccc_1_1_invoke(smccc_dev->func_id, &res);
+ ret = res.a0;
+
+ if ((s32)ret < 0)
+ return false;
+
+ return ret >= smccc_dev->min_return;
+}
+
void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
{
struct arm_smccc_res res;
@@ -31,7 +68,7 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
smccc_version = version;
smccc_conduit = conduit;
- smccc_trng_available = smccc_probe_trng();
+ smccc_trng_available = smccc_probe_smccc_device(&smccc_devices[0]);
if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
(smccc_conduit != SMCCC_CONDUIT_NONE)) {
@@ -241,14 +278,20 @@ subsys_initcall(arm_smccc_bus_init);
static int __init smccc_devices_init(void)
{
- struct platform_device *pdev;
-
- if (smccc_trng_available) {
- pdev = platform_device_register_simple("smccc_trng", -1,
- NULL, 0);
- if (IS_ERR(pdev))
- pr_err("smccc_trng: could not register device: %ld\n",
- PTR_ERR(pdev));
+ const struct smccc_device_info *smccc_dev;
+ struct arm_smccc_device *sdev;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(smccc_devices); i++) {
+ smccc_dev = &smccc_devices[i];
+
+ if (!smccc_probe_smccc_device(smccc_dev))
+ continue;
+
+ sdev = arm_smccc_device_register(smccc_dev->device_name);
+ if (IS_ERR(sdev))
+ pr_err("%s: could not register device: %ld\n",
+ smccc_dev->device_name, PTR_ERR(sdev));
}
return 0;
^ permalink raw reply related
* [PATCH] dma: at_hdmac: Fix use-after-free by proper tasklet cleanup
From: Hongling Zeng @ 2026-06-04 9:23 UTC (permalink / raw)
To: ludovic.desroches, vkoul, Frank.Li, tudor.ambarus, nicolas.ferre
Cc: linux-arm-kernel, dmaengine, linux-kernel, zhongling0719,
Hongling Zeng, sashiko-bot
Current cleanup paths have a use-after-free vulnerability:
- vchan_init() creates tasklets that access at_dma_chan memory
- free_irq() only waits for IRQ handler, NOT tasklets
- atdma is devm-managed and freed after probe/remove
- Running tasklets accessing freed memory → Use-After-Free!
The fix requires careful ordering:
- Disable interrupts FIRST to stop new tasklets from being scheduled
- Then kill tasklets to wait for already-scheduled ones to complete
- Only then free IRQs and other resources
Fixes: ac803b56860f ("dmaengine: at_hdmac: Convert driver to use virt-dma")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/all/20260604073945.54B311F00898@smtp.kernel.org/
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
---
drivers/dma/at_hdmac.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index e5b30a57c477..ac45e88e16da 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1940,6 +1940,19 @@ static void at_dma_off(struct at_dma *atdma)
cpu_relax();
}
+static void at_dma_cleanup_channels(struct at_dma *atdma)
+{
+ struct dma_chan *chan, *_chan;
+
+ list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
+ device_node) {
+ /* Disable interrupts */
+ atc_disable_chan_irq(atdma, chan->chan_id);
+ tasklet_kill(&to_at_dma_chan(chan)->vc.task);
+ list_del(&chan->device_node);
+ }
+}
+
static int __init at_dma_probe(struct platform_device *pdev)
{
struct at_dma *atdma;
@@ -2109,6 +2122,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
err_memset_pool_create:
dma_pool_destroy(atdma->lli_pool);
err_desc_pool_create:
+ at_dma_cleanup_channels(atdma);
free_irq(platform_get_irq(pdev, 0), atdma);
err_irq:
clk_disable_unprepare(atdma->clk);
@@ -2125,17 +2139,12 @@ static void at_dma_remove(struct platform_device *pdev)
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&atdma->dma_device);
+ at_dma_cleanup_channels(atdma);
+
dma_pool_destroy(atdma->memset_pool);
dma_pool_destroy(atdma->lli_pool);
free_irq(platform_get_irq(pdev, 0), atdma);
- list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
- device_node) {
- /* Disable interrupts */
- atc_disable_chan_irq(atdma, chan->chan_id);
- list_del(&chan->device_node);
- }
-
clk_disable_unprepare(atdma->clk);
}
--
2.25.1
^ permalink raw reply related
* Re: [PATCH 1/2] dt-bindings: spi: Add for Nuvoton MA35D1 SoC QSPI Controller
From: Chi-Wen Weng @ 2026-06-04 9:25 UTC (permalink / raw)
To: Conor Dooley
Cc: broonie, robh, krzk+dt, conor+dt, linux-arm-kernel, linux-spi,
devicetree, linux-kernel, cwweng
In-Reply-To: <20260604-anthem-jokingly-8d8312ff0c3f@spud>
Hi Conor,
Thanks for the clarification.
I will keep using my personal mail account for sending the patches to
avoid the corporate confidentiality footer, but I will set the commit
author and Signed-off-by to my Nuvoton address in v2.
Best regards,
Chi-Wen
Conor Dooley 於 2026/6/4 下午 04:55 寫道:
> On Thu, Jun 04, 2026 at 03:07:31PM +0800, Chi-Wen Weng wrote:
>> Hi Conor,
>>
>> Thanks for the review.
>>
>>> Missing commit message for one, but why can't your Nuvoton mail be used
>>> here?
>> I apologize for the missing commit message; I will add a proper description
>> in v2.
>>
>> Regarding the email address, my Nuvoton mail adds a corporate
>> confidentiality disclaimer to outgoing
>> external mail, so I use my personal address for sending kernel patches.
> This prevents you sending with your work email account, but you can still
> set your commit author to your Nuvoton address FWIW.
>
>> Conor Dooley 於 2026/6/3 下午 11:24 寫道:
>>> On Wed, Jun 03, 2026 at 12:35:50PM +0800, Chi-Wen Weng wrote:
>>>> Signed-off-by: Chi-Wen Weng <cwweng.linux@gmail.com>
^ permalink raw reply
* [PATCH] KVM: arm64: Fix order of arguments to ktime_get_snapshot_id()
From: Uwe Kleine-König @ 2026-06-04 9:27 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Thomas Gleixner
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Jacob Keller, David Woodhouse,
Vincent Donnefort, linux-arm-kernel, kvmarm, linux-kernel
The first argument to ktime_get_snapshot_id() is the clock ID and the
second output parameter. Fix the caller that reversed the order and thus
fix a compiler error.
Fixes: d09439210441 ("KVM: arm64: Use ktime_get_snapshot_id() to retrieve CLOCK_BOOTTIME")
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
---
arch/arm64/kvm/hyp_trace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8574db7491bc..2411b4c32932 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -118,7 +118,7 @@ static void hyp_trace_clock_enable(struct hyp_trace_clock *hyp_clock, bool enabl
hyp_clock->running = false;
}
- ktime_get_snapshot_id(&snap, CLOCK_BOOTTIME);
+ ktime_get_snapshot_id(CLOCK_BOOTTIME, &snap);
hyp_clock->boot = ktime_to_ns(snap.systime);
hyp_clock->cycles = snap.cycles;
base-commit: d09439210441efbadd8b0aa32c1ddb1eab2f3abd
--
2.47.3
^ permalink raw reply related
* [GIT PULL] Rockchip arm32 fix for the current 7.1-rc
From: Heiko Stuebner @ 2026-06-04 9:27 UTC (permalink / raw)
To: arm; +Cc: soc, linux-rockchip, linux-arm-kernel
Hi SoC maintainers,
please find a below a fix for an issue in the ARCH code for 32bit
Rockchip SoCs, that appeared with 7.1-rc .
Please pull
Thanks
Heiko
The following changes since commit 254f49634ee16a731174d2ae34bc50bd5f45e731:
Linux 7.1-rc1 (2026-04-26 14:19:00 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git tags/v7.1-rockchip-arm32fixe
for you to fetch changes up to 6fc5666aa576c6c3bec256fa31d72653210319d5:
ARM: rockchip: keep reset control around (2026-05-26 23:20:39 +0200)
----------------------------------------------------------------
A change in 7.1-rc improved the general handling for reset controllers
using SRCU, but at the same time broke really early users before work-
queues are available.
So adapt the SMP bringup to keep the core-resets around, instead
of aquiring/releasing them on ever SMP action.
----------------------------------------------------------------
Heiko Stuebner (1):
ARM: rockchip: keep reset control around
arch/arm/mach-rockchip/platsmp.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
^ permalink raw reply
* Re: [PATCH 3/4] arm64: mte: Disregard the zero page explicitly for manipulating tags
From: Ard Biesheuvel @ 2026-06-04 9:42 UTC (permalink / raw)
To: Catalin Marinas, Ard Biesheuvel
Cc: linux-arm-kernel, linux-kernel, Will Deacon, maz, Kevin Brodsky,
Mark Brown, David Hildenbrand
In-Reply-To: <aiFDFbeOoxgKigP0@arm.com>
On Thu, 4 Jun 2026, at 11:19, Catalin Marinas wrote:
> On Wed, Jun 03, 2026 at 06:09:53PM +0200, Ard Biesheuvel wrote:
>> From: Ard Biesheuvel <ardb@kernel.org>
>>
>> The zero page is conceptually immutable, and will be moved into .rodata
>> to prevent inadvertent corruption.
>>
>> Prepare the MTE code for this, by ensuring that the zero page is never
>> taken into account for tag manipulation, given that those actions will
>> no longer be permitted on the read-only alias of .rodata in the linear
>> map.
>>
>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>> ---
>> arch/arm64/include/asm/mte.h | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h
>> index 7f7b97e09996..093b34944aee 100644
>> --- a/arch/arm64/include/asm/mte.h
>> +++ b/arch/arm64/include/asm/mte.h
>> @@ -80,6 +80,11 @@ static inline bool page_mte_tagged(struct page *page)
>> */
>> static inline bool try_page_mte_tagging(struct page *page)
>> {
>> + extern struct page *__zero_page;
>> +
>> + if (page == __zero_page)
>> + return false;
>
> Better as is_zero_page()
>
True, but I was concerned about #inclusion hell.
>> +
>> VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));
>>
>> if (!test_and_set_bit(PG_mte_lock, &page->flags.f))
>
> Some form of this fix should have:
>
> Fixes: f620d66af316 ("arm64: mte: Do not flag the zero page as PG_mte_tagged")
> Cc: <stable@vger.kernel.org> # 5.10.x
>
> The current mainline assumption is that mapping the zero page in user
> space is always mapped with pte_special() and we skip the MTE tag
> zeroing (and PG flag setting). However, the above commit missed the KVM
> kvm_s2_fault_map() -> sanitise_mte_tags() path and we don't have a form
> of pte_special() for stage 2 mappings.
>
> I'm more inclined to go with a specific test in the KVM path. It matches
> the stage 1 where we skip the actual tagging. We could add a
> VM_WARN_ONCE in try_page_mte_tagging() to trap future changes.
>
Let's go with that - I'll turn this into a patch for v2
> -------------8<-----------------------
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index d089c107d9b7..445d6cf035c9 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1479,6 +1479,11 @@ static void sanitise_mte_tags(struct kvm *kvm,
> kvm_pfn_t pfn,
> if (!kvm_has_mte(kvm))
> return;
>
> + if (is_zero_pfn(pfn)) {
> + WARN_ON_ONCE(nr_pages != 1);
> + return;
> + }
> +
> if (folio_test_hugetlb(folio)) {
> /* Hugetlb has MTE flags set on head page only */
> if (folio_try_hugetlb_mte_tagging(folio)) {
>
> --
> Catalin
^ permalink raw reply
* Re: [PATCH] KVM: arm64: Fix order of arguments to ktime_get_snapshot_id()
From: Thomas Gleixner @ 2026-06-04 9:49 UTC (permalink / raw)
To: Uwe Kleine-König, Marc Zyngier, Oliver Upton
Cc: Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Jacob Keller, David Woodhouse,
Vincent Donnefort, linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <20260604092714.1537457-2-ukleinek@kernel.org>
On Thu, Jun 04 2026 at 11:27, Uwe Kleine-König wrote:
> The first argument to ktime_get_snapshot_id() is the clock ID and the
> second output parameter. Fix the caller that reversed the order and thus
> fix a compiler error.
I've already squashed a fix earlier today
^ permalink raw reply
* [PATCH 1/2] dt-bindings: phy: nuvoton: Add MA35D1 USB2 OTG PHY binding
From: Joey Lu @ 2026-06-04 10:12 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jacky Huang,
Shan-Chun Hung, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260604101220.1092822-1-a0987203069@gmail.com>
Add device tree binding documentation for the Nuvoton MA35D1 USB 2.0
OTG PHY driver (nuvoton,ma35d1-usb2-phy-otg).
PHY index 0 (USB0) is an OTG port whose signals are routed by a hardware
mux to either the DWC2 device controller or the EHCI0/OHCI0 host
controllers depending on the USB ID pin state. PHY index 1 (USB1) is a
dedicated host-only port.
Optional properties allow board-specific resistor calibration trim
(nuvoton,rcalcode) and over-current detect polarity configuration
(nuvoton,oc-active-high).
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
.../phy/nuvoton,ma35d1-usb2-phy-otg.yaml | 79 +++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy-otg.yaml
diff --git a/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy-otg.yaml b/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy-otg.yaml
new file mode 100644
index 000000000000..19f074565cc6
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy-otg.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/nuvoton,ma35d1-usb2-phy-otg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton MA35D1 USB 2.0 host PHY
+
+maintainers:
+ - Joey Lu <yclu4@nuvoton.com>
+
+description:
+ USB 2.0 PHY driver for the Nuvoton MA35D1 SoC, used by the EHCI and
+ OHCI host controllers.
+
+ USB0 (PHY index 0) is an OTG port whose physical signals are routed to
+ either the DWC2 device controller or the EHCI0/OHCI0 host controller by
+ a hardware mux that follows the USB ID pin.
+
+ USB1 (PHY index 1) is a dedicated host port with no OTG capability.
+
+properties:
+ compatible:
+ const: nuvoton,ma35d1-usb2-phy-otg
+
+ clocks:
+ maxItems: 1
+
+ nuvoton,sys:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: phandle to the system management syscon.
+ - description: PHY instance index.
+ enum:
+ - 0 # USB0, OTG port (shared with DWC2 gadget controller)
+ - 1 # USB1, host-only port
+ description:
+ A phandle to the syscon node covering the SYS register block, with
+ one argument selecting the PHY instance. Index 0 selects the OTG
+ port PHY (USB0) and index 1 selects the host-only PHY (USB1).
+
+ "#phy-cells":
+ const: 0
+
+ nuvoton,rcalcode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 15
+ description:
+ Resistor calibration trim code written to the RCALCODE field in
+ USBPMISCR. The 4-bit value adjusts the PHY's internal termination
+ resistance. When absent the hardware reset default is used.
+
+ nuvoton,oc-active-high:
+ type: boolean
+ description:
+ When present, the over-current detect input from the VBUS power
+ switch is treated as active-high. The default (property absent) is
+ active-low. This setting is shared by both USB host ports.
+
+required:
+ - compatible
+ - clocks
+ - nuvoton,sys
+ - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+
+ usb_hphy0: usb-host-phy {
+ compatible = "nuvoton,ma35d1-usb2-phy-otg";
+ clocks = <&clk HUSBH0_GATE>;
+ nuvoton,sys = <&sys 0>;
+ #phy-cells = <0>;
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH 2/2] phy: nuvoton: Add MA35D1 USB2 OTG PHY driver
From: Joey Lu @ 2026-06-04 10:12 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jacky Huang,
Shan-Chun Hung, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260604101220.1092822-1-a0987203069@gmail.com>
Add a PHY driver for the USB 2.0 PHYs in the Nuvoton MA35D1 SoC,
intended for use with the EHCI and OHCI host controllers.
The MA35D1 SoC has two USB ports:
- USB0: an OTG port shared between a DWC2 gadget controller and
EHCI0/OHCI0 host controllers. A hardware mux automatically routes
the physical USB0 signals to the appropriate controller based on the
USB ID pin state. The DWC2 IP is device-only in hardware,
so host-mode operation on USB0 is handled entirely by EHCI0/OHCI0.
- USB1: a dedicated host-only port served by EHCI1/OHCI1.
The driver implements:
- Power-On Reset sequence with a guard that skips re-initialization if
the PHY is already operational. This protects PHY0 when the DWC2
gadget driver has already run its own init before EHCI0 probes.
- Optional resistor calibration trim via nuvoton,rcalcode.
- Optional over-current detect polarity via nuvoton,oc-active-high.
- For PHY0 only: a USB role switch that exposes the hardware ID pin
state (PWRONOTP[16]).
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/phy/nuvoton/Kconfig | 15 ++
drivers/phy/nuvoton/Makefile | 1 +
drivers/phy/nuvoton/phy-ma35d1-otg.c | 264 +++++++++++++++++++++++++++
3 files changed, 280 insertions(+)
create mode 100644 drivers/phy/nuvoton/phy-ma35d1-otg.c
diff --git a/drivers/phy/nuvoton/Kconfig b/drivers/phy/nuvoton/Kconfig
index d02cae2db315..5fdd13f841e7 100644
--- a/drivers/phy/nuvoton/Kconfig
+++ b/drivers/phy/nuvoton/Kconfig
@@ -10,3 +10,18 @@ config PHY_MA35_USB
help
Enable this to support the USB2.0 PHY on the Nuvoton MA35
series SoCs.
+
+config PHY_MA35_USB_OTG
+ tristate "Nuvoton MA35 USB2.0 OTG PHY driver"
+ depends on ARCH_MA35 || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ select MFD_SYSCON
+ select USB_ROLE_SWITCH
+ help
+ Enable this to support the USB2.0 OTG PHY on the Nuvoton MA35
+ series SoCs. This driver handles PHY initialization for the
+ EHCI/OHCI host controllers, including per-PHY power-on reset,
+ resistor calibration trim, and over-current polarity
+ configuration. For the OTG port (PHY0), it also monitors the
+ USB ID pin and registers a USB role switch.
diff --git a/drivers/phy/nuvoton/Makefile b/drivers/phy/nuvoton/Makefile
index 2937e3921898..3ecd76f35d7c 100644
--- a/drivers/phy/nuvoton/Makefile
+++ b/drivers/phy/nuvoton/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_MA35_USB) += phy-ma35d1-usb2.o
+obj-$(CONFIG_PHY_MA35_USB_OTG) += phy-ma35d1-otg.o
diff --git a/drivers/phy/nuvoton/phy-ma35d1-otg.c b/drivers/phy/nuvoton/phy-ma35d1-otg.c
new file mode 100644
index 000000000000..53bc6ddf755e
--- /dev/null
+++ b/drivers/phy/nuvoton/phy-ma35d1-otg.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Nuvoton MA35D1 USB 2.0 OTG PHY driver
+ *
+ * PHY0 (USB0) is shared between DWC2 gadget and EHCI0/OHCI0 host
+ * controllers. The hardware mux switches automatically via the USB
+ * ID pin. PHY1 (USB1) is host-only.
+ *
+ * Copyright (C) 2026 Nuvoton Technology Corp.
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/usb/role.h>
+
+#define MA35_SYS_PWRONOTP 0x04
+#define PWRONOTP_USBP0ID BIT(16)
+
+#define MA35_SYS_USBPMISCR 0x60
+#define USBPMISCR_PHY_POR(n) BIT(0 + (n) * 16)
+#define USBPMISCR_PHY_SUSPEND(n) BIT(1 + (n) * 16)
+#define USBPMISCR_PHY_COMN(n) BIT(2 + (n) * 16)
+#define USBPMISCR_PHY_HSTCKSTB(n) BIT(8 + (n) * 16)
+#define USBPMISCR_PHY_CK12MSTB(n) BIT(9 + (n) * 16)
+/* Mask for control bits (POR, SUSPEND, COMN) of one PHY */
+#define USBPMISCR_PHY_CTL_MASK(n) (0x7 << ((n) * 16))
+/* Host-mode ready: SUSPEND + HSTCKSTB + CK12MSTB */
+#define USBPMISCR_PHY_HOST_READY(n) (USBPMISCR_PHY_SUSPEND(n) | \
+ USBPMISCR_PHY_HSTCKSTB(n) | \
+ USBPMISCR_PHY_CK12MSTB(n))
+/* RCALCODE: 4-bit resistor trim at bits [15:12] (PHY0) or [31:28] (PHY1) */
+#define USBPMISCR_RCAL_SHIFT(n) (12 + (n) * 16)
+#define USBPMISCR_RCAL_MASK(n) GENMASK(USBPMISCR_RCAL_SHIFT(n) + 3, \
+ USBPMISCR_RCAL_SHIFT(n))
+
+#define MA35_SYS_MISCFCR0 0x70
+/* MISCFCR0[12]: USB host over-current detect polarity (shared, both ports) */
+#define MISCFCR0_UHOVRCURH BIT(12)
+
+struct ma35_otg_phy {
+ struct clk *clk;
+ struct device *dev;
+ struct regmap *sysreg;
+ unsigned int phy_idx;
+ struct usb_role_switch *role_sw;
+ enum usb_role cur_role;
+};
+
+static int ma35_otg_phy_init(struct phy *phy)
+{
+ struct ma35_otg_phy *p = phy_get_drvdata(phy);
+ unsigned int n = p->phy_idx;
+ u32 ready_mask = USBPMISCR_PHY_HOST_READY(n);
+ unsigned int val;
+ int ret;
+
+ regmap_read(p->sysreg, MA35_SYS_USBPMISCR, &val);
+ if ((val & ready_mask) == ready_mask)
+ return 0;
+
+ regmap_update_bits(p->sysreg, MA35_SYS_USBPMISCR,
+ USBPMISCR_PHY_CTL_MASK(n),
+ USBPMISCR_PHY_POR(n) | USBPMISCR_PHY_SUSPEND(n));
+ msleep(20);
+
+ regmap_update_bits(p->sysreg, MA35_SYS_USBPMISCR,
+ USBPMISCR_PHY_CTL_MASK(n),
+ USBPMISCR_PHY_SUSPEND(n));
+
+ ret = regmap_read_poll_timeout(p->sysreg, MA35_SYS_USBPMISCR, val,
+ (val & ready_mask) == ready_mask,
+ 10, 1000);
+ if (ret) {
+ dev_err(p->dev, "USB PHY%u clock not stable (USBPMISCR=0x%08x)\n",
+ n, val);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ma35_otg_phy_power_on(struct phy *phy)
+{
+ struct ma35_otg_phy *p = phy_get_drvdata(phy);
+
+ return clk_prepare_enable(p->clk);
+}
+
+static int ma35_otg_phy_power_off(struct phy *phy)
+{
+ struct ma35_otg_phy *p = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(p->clk);
+ return 0;
+}
+
+static const struct phy_ops ma35_otg_phy_ops = {
+ .init = ma35_otg_phy_init,
+ .power_on = ma35_otg_phy_power_on,
+ .power_off = ma35_otg_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static enum usb_role ma35_otg_read_id(struct ma35_otg_phy *p)
+{
+ unsigned int val;
+
+ regmap_read(p->sysreg, MA35_SYS_PWRONOTP, &val);
+ return (val & PWRONOTP_USBP0ID) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
+}
+
+static int ma35_otg_role_sw_set(struct usb_role_switch *sw,
+ enum usb_role role)
+{
+ struct ma35_otg_phy *p = usb_role_switch_get_drvdata(sw);
+
+ p->cur_role = role;
+
+ return 0;
+}
+
+static enum usb_role ma35_otg_role_sw_get(struct usb_role_switch *sw)
+{
+ struct ma35_otg_phy *p = usb_role_switch_get_drvdata(sw);
+
+ return ma35_otg_read_id(p);
+}
+
+static int ma35_otg_role_switch_init(struct platform_device *pdev,
+ struct ma35_otg_phy *p)
+{
+ struct usb_role_switch_desc sw_desc = { };
+
+ p->cur_role = ma35_otg_read_id(p);
+
+ sw_desc.set = ma35_otg_role_sw_set;
+ sw_desc.get = ma35_otg_role_sw_get;
+ sw_desc.allow_userspace_control = true;
+ sw_desc.driver_data = p;
+ sw_desc.fwnode = dev_fwnode(&pdev->dev);
+
+ p->role_sw = usb_role_switch_register(&pdev->dev, &sw_desc);
+ if (IS_ERR(p->role_sw))
+ return dev_err_probe(&pdev->dev, PTR_ERR(p->role_sw),
+ "failed to register role switch\n");
+
+ return 0;
+}
+
+static void ma35_otg_role_switch_exit(struct ma35_otg_phy *p)
+{
+ if (!p->role_sw)
+ return;
+
+ usb_role_switch_unregister(p->role_sw);
+ p->role_sw = NULL;
+}
+
+static int ma35_otg_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *provider;
+ struct ma35_otg_phy *p;
+ unsigned int sys_args[1];
+ struct phy *phy;
+ u32 rcalcode;
+ int ret;
+
+ p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->dev = &pdev->dev;
+ platform_set_drvdata(pdev, p);
+
+ p->sysreg = syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node,
+ "nuvoton,sys",
+ 1, sys_args);
+ if (IS_ERR(p->sysreg))
+ return dev_err_probe(&pdev->dev, PTR_ERR(p->sysreg),
+ "Failed to get SYS regmap\n");
+
+ p->phy_idx = sys_args[0];
+
+ if (p->phy_idx > 1)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid PHY index %u (must be 0 or 1)\n",
+ p->phy_idx);
+
+ p->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(p->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(p->clk),
+ "failed to get PHY clock\n");
+
+ if (!of_property_read_u32(pdev->dev.of_node, "nuvoton,rcalcode",
+ &rcalcode)) {
+ if (rcalcode > 15)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "rcalcode %u out of range (0-15)\n",
+ rcalcode);
+ regmap_update_bits(p->sysreg, MA35_SYS_USBPMISCR,
+ USBPMISCR_RCAL_MASK(p->phy_idx),
+ rcalcode << USBPMISCR_RCAL_SHIFT(p->phy_idx));
+ }
+
+ if (of_property_read_bool(pdev->dev.of_node, "nuvoton,oc-active-high"))
+ regmap_update_bits(p->sysreg, MA35_SYS_MISCFCR0,
+ MISCFCR0_UHOVRCURH, MISCFCR0_UHOVRCURH);
+
+ phy = devm_phy_create(&pdev->dev, pdev->dev.of_node, &ma35_otg_phy_ops);
+ if (IS_ERR(phy))
+ return dev_err_probe(&pdev->dev, PTR_ERR(phy),
+ "Failed to create PHY\n");
+
+ phy_set_drvdata(phy, p);
+
+ provider = devm_of_phy_provider_register(&pdev->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(provider))
+ return dev_err_probe(&pdev->dev, PTR_ERR(provider),
+ "Failed to register PHY provider\n");
+
+ if (p->phy_idx == 0) {
+ ret = ma35_otg_role_switch_init(pdev, p);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void ma35_otg_phy_remove(struct platform_device *pdev)
+{
+ struct ma35_otg_phy *p = platform_get_drvdata(pdev);
+
+ ma35_otg_role_switch_exit(p);
+}
+
+static const struct of_device_id ma35_otg_phy_of_match[] = {
+ { .compatible = "nuvoton,ma35d1-usb2-phy-otg" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ma35_otg_phy_of_match);
+
+static struct platform_driver ma35_otg_phy_driver = {
+ .probe = ma35_otg_phy_probe,
+ .remove = ma35_otg_phy_remove,
+ .driver = {
+ .name = "ma35d1-usb2-phy-otg",
+ .of_match_table = ma35_otg_phy_of_match,
+ },
+};
+module_platform_driver(ma35_otg_phy_driver);
+
+MODULE_DESCRIPTION("Nuvoton MA35D1 USB 2.0 OTG PHY driver");
+MODULE_AUTHOR("Joey Lu <a0987203069@gmail.com>");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related
* [PATCH 0/2] phy: nuvoton: Add MA35D1 USB2 OTG PHY driver
From: Joey Lu @ 2026-06-04 10:12 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jacky Huang,
Shan-Chun Hung, linux-phy, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
The Nuvoton MA35D1 SoC has two USB 2.0 ports:
USB0 is an OTG-capable port. Its physical signals are routed by a
hardware mux to either a DWC2 gadget controller or the EHCI0/OHCI0
host controllers, depending on the USB ID pin state. The DWC2 IP is
device-only in hardware, so all host-mode operation on USB0 is
handled by EHCI0/OHCI0.
USB1 is a dedicated host-only port served by EHCI1/OHCI1.
About this driver:
- Runs the PHY Power-On Reset sequence, with a guard that skips
re-initialization if the PHY is already operational.
- Supports optional resistor calibration trim (nuvoton,rcalcode) and
over-current detect polarity configuration (nuvoton,oc-active-high).
- For PHY0 (USB0) only: registers a USB role switch that reads the
hardware ID pin state from PWRONOTP[16] on every query.
Joey Lu (2):
dt-bindings: phy: nuvoton: Add MA35D1 USB2 OTG PHY binding
phy: nuvoton: Add MA35D1 USB2 OTG PHY driver
.../phy/nuvoton,ma35d1-usb2-phy-otg.yaml | 79 ++++++
drivers/phy/nuvoton/Kconfig | 15 +
drivers/phy/nuvoton/Makefile | 1 +
drivers/phy/nuvoton/phy-ma35d1-otg.c | 264 ++++++++++++++++++
4 files changed, 359 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/nuvoton,ma35d1-usb2-phy-otg.yaml
create mode 100644 drivers/phy/nuvoton/phy-ma35d1-otg.c
--
2.43.0
^ permalink raw reply
* Re: [PATCH net] net: airoha: Add NULL check for of_reserved_mem_lookup() in airoha_qdma_init_hfwd_queues()
From: Lorenzo Bianconi @ 2026-06-04 10:18 UTC (permalink / raw)
To: ZhaoJinming
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, horms,
linux-arm-kernel, linux-mediatek, netdev, linux-kernel, stable
In-Reply-To: <20260604070352.2603077-1-zhaojinming@uniontech.com>
[-- Attachment #1: Type: text/plain, Size: 1700 bytes --]
> of_reserved_mem_lookup() may return NULL if the reserved memory region
> referenced by the "memory-region" phandle is not found in the reserved
> memory table (e.g. due to a misconfigured DTS or a removed
> memory-region node). The current code dereferences the returned
> pointer without checking for NULL, leading to a kernel NULL pointer
> dereference at the following lines:
>
> dma_addr = rmem->base; // line 1156
> num_desc = div_u64(rmem->size, buf_size); // line 1160
>
> Add a NULL check after of_reserved_mem_lookup() and return -ENODEV if
> the lookup fails, which is consistent with the existing error handling
> for of_parse_phandle() failure in the same code block.
>
> Fixes: 3a1ce9e3d01b ("net: airoha: Add the capability to allocate hwfd buffers via reserved-memory")
> Cc: stable@vger.kernel.org
> Signed-off-by: ZhaoJinming<zhaojinming@uniontech.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index cecd66251dba..2444d3275a81 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1153,6 +1153,9 @@ static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma)
>
> rmem = of_reserved_mem_lookup(np);
> of_node_put(np);
> + if (!rmem)
> + return -ENODEV;
> +
> dma_addr = rmem->base;
> /* Compute the number of hw descriptors according to the
> * reserved memory size and the payload buffer size
> --
> 2.25.1
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH v2] dma: at_hdmac: Fix use-after-free by proper tasklet cleanup
From: Hongling Zeng @ 2026-06-04 10:19 UTC (permalink / raw)
To: ludovic.desroches, vkoul, Frank.Li, tudor.ambarus, nicolas.ferre
Cc: linux-arm-kernel, dmaengine, linux-kernel, zhongling0719,
Hongling Zeng, sashiko-bot
Current cleanup paths have a use-after-free vulnerability:
- vchan_init() creates tasklets that access at_dma_chan memory
- free_irq() only waits for IRQ handler, NOT tasklets
- atdma is devm-managed and freed after probe/remove
- Running tasklets accessing freed memory → Use-After-Free!
The fix requires careful ordering:
- free_irq() FIRST to synchronize with running IRQ handlers and prevent
them from scheduling new tasklets
- Then kill tasklets to wait for already-scheduled ones to complete
- Only then free other resources
Fixes: ac803b56860f ("dmaengine: at_hdmac: Convert driver to use virt-dma")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/all/20260604073945.54B311F00898@smtp.kernel.org/
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
---
Change in v2:
- Fix NULL pointer dereference in probe error path by checking if channels list is initialized before cleanup
- Fix race condition by calling free_irq() before tasklet_kill() to ensure
IRQ handlers cannot reschedule tasklets after cleanup
---
drivers/dma/at_hdmac.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index e5b30a57c477..9048b56b082f 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1940,6 +1940,19 @@ static void at_dma_off(struct at_dma *atdma)
cpu_relax();
}
+static void at_dma_cleanup_channels(struct at_dma *atdma)
+{
+ struct dma_chan *chan, *_chan;
+
+ list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
+ device_node) {
+ /* Disable interrupts */
+ atc_disable_chan_irq(atdma, chan->chan_id);
+ tasklet_kill(&to_at_dma_chan(chan)->vc.task);
+ list_del(&chan->device_node);
+ }
+}
+
static int __init at_dma_probe(struct platform_device *pdev)
{
struct at_dma *atdma;
@@ -2109,6 +2122,8 @@ static int __init at_dma_probe(struct platform_device *pdev)
err_memset_pool_create:
dma_pool_destroy(atdma->lli_pool);
err_desc_pool_create:
+ if (atdma->dma_device.channels.next != NULL)
+ at_dma_cleanup_channels(atdma);
free_irq(platform_get_irq(pdev, 0), atdma);
err_irq:
clk_disable_unprepare(atdma->clk);
@@ -2125,16 +2140,11 @@ static void at_dma_remove(struct platform_device *pdev)
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&atdma->dma_device);
- dma_pool_destroy(atdma->memset_pool);
- dma_pool_destroy(atdma->lli_pool);
free_irq(platform_get_irq(pdev, 0), atdma);
+ at_dma_cleanup_channels(atdma);
- list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
- device_node) {
- /* Disable interrupts */
- atc_disable_chan_irq(atdma, chan->chan_id);
- list_del(&chan->device_node);
- }
+ dma_pool_destroy(atdma->memset_pool);
+ dma_pool_destroy(atdma->lli_pool);
clk_disable_unprepare(atdma->clk);
}
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Suzuki K Poulose @ 2026-06-04 10:24 UTC (permalink / raw)
To: Sudeep Holla, Aneesh Kumar K.V (Arm)
Cc: linux-coco, linux-arm-kernel, linux-kernel, Catalin Marinas,
Greg KH, Jeremy Linton, Jonathan Cameron, Lorenzo Pieralisi,
Mark Rutland, Will Deacon, Steven Price
In-Reply-To: <20260603-determined-bumblebee-of-promise-e633d6@sudeepholla>
On 04/06/2026 10:21, Sudeep Holla wrote:
> On Wed, May 27, 2026 at 03:32:32PM +0530, Aneesh Kumar K.V (Arm) wrote:
>> The Arm CCA guest TSM provider currently binds through the arm-cca-dev
>> platform device. Like arm-smccc-trng, this device is not an independent
>> platform resource; it is a software representation of the RSI firmware
>> service discovered through SMCCC.
>>
>> Move RSI discovery into the SMCCC firmware driver. When the SMCCC conduit
>> is SMC and the RSI ABI version check succeeds, create an arm-rsi-dev SMCCC
>> device. Convert the Arm CCA guest TSM provider to an SMCCC driver so it
>> binds to that discovered RSI service and keeps module autoloading through
>> the SMCCC device id table.
>>
>> Keep the old arm-cca-dev platform-device registration for now. Userspace
>> has used that device as a Realm-guest indicator, so removing it is left to
>> a follow-up patch that adds a replacement sysfs ABI.
>>
>> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
>> ---
>> arch/arm64/include/asm/rsi.h | 2 +-
>> arch/arm64/kernel/rsi.c | 2 +-
>> drivers/firmware/smccc/Makefile | 4 ++
>> drivers/firmware/smccc/rmm.c | 25 ++++++++
>> drivers/firmware/smccc/rmm.h | 17 ++++++
>> drivers/firmware/smccc/smccc.c | 8 +++
>> drivers/virt/coco/arm-cca-guest/Kconfig | 1 +
>> drivers/virt/coco/arm-cca-guest/Makefile | 2 +
>> .../{arm-cca-guest.c => arm-cca.c} | 60 +++++++++----------
>> 9 files changed, 89 insertions(+), 32 deletions(-)
>> create mode 100644 drivers/firmware/smccc/rmm.c
>> create mode 100644 drivers/firmware/smccc/rmm.h
>> rename drivers/virt/coco/arm-cca-guest/{arm-cca-guest.c => arm-cca.c} (85%)
>>
>> diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
>> index 88b50d660e85..2d2d363aaaee 100644
>> --- a/arch/arm64/include/asm/rsi.h
>> +++ b/arch/arm64/include/asm/rsi.h
>> @@ -10,7 +10,7 @@
>> #include <linux/jump_label.h>
>> #include <asm/rsi_cmds.h>
>>
>> -#define RSI_PDEV_NAME "arm-cca-dev"
>> +#define RSI_DEV_NAME "arm-rsi-dev"
>>
>> DECLARE_STATIC_KEY_FALSE(rsi_present);
>>
>> diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
>> index 92160f2e57ff..da440f71bb64 100644
>> --- a/arch/arm64/kernel/rsi.c
>> +++ b/arch/arm64/kernel/rsi.c
>> @@ -161,7 +161,7 @@ void __init arm64_rsi_init(void)
>> }
>>
>> static struct platform_device rsi_dev = {
>> - .name = RSI_PDEV_NAME,
>> + .name = "arm-cca-dev",
>> .id = PLATFORM_DEVID_NONE
>> };
>>
>> diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile
>> index 40d19144a860..33c850aaff4d 100644
>> --- a/drivers/firmware/smccc/Makefile
>> +++ b/drivers/firmware/smccc/Makefile
>> @@ -2,3 +2,7 @@
>> #
>> obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o
>> obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o
>> +
>> +ifeq ($(CONFIG_HAVE_ARM_SMCCC_DISCOVERY),y)
>> +obj-$(CONFIG_ARM64) += rmm.o
>> +endif
>> diff --git a/drivers/firmware/smccc/rmm.c b/drivers/firmware/smccc/rmm.c
>> new file mode 100644
>> index 000000000000..d572f47e955c
>> --- /dev/null
>> +++ b/drivers/firmware/smccc/rmm.c
>> @@ -0,0 +1,25 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2026 Arm Limited
>> + */
>> +
>> +#include <linux/arm-smccc-bus.h>
>> +#include <linux/err.h>
>> +#include <linux/printk.h>
>> +
>> +#include "rmm.h"
>> +
>> +void __init register_rsi_device(void)
>> +{
>> + unsigned long ret;
>> +
>> + if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
>> + return;
>> +
>> + ret = rsi_request_version(RSI_ABI_VERSION, NULL, NULL);
>> + if (ret != RSI_SUCCESS)
>> + return;
>> +
>> + if (IS_ERR(arm_smccc_device_register(RSI_DEV_NAME)))
>> + pr_err("%s: could not register device\n", RSI_DEV_NAME);
>> +}
>
> OK, I had something else in my mind when I started looking at 1/4. I didn't
> expect each device added on this bus comes up with it's own way to enumerate
> it. IMO, it defeats the purpose of building the smccc bus. We may find the
> specs for each feature deviated a bit but we can have a generic probe
> IMO, let's try that before exploring per feature probe function.
I guess this is ideal, but see below.
>
> I have a brief sketch of what I think we should aim for(uncompiled/untested)
> below. Let me know if that makes sense. I just based it on your bus code.
>
> Regards,
> Sudeep
>
> -->8
>
> diff --git c/drivers/firmware/smccc/smccc.c w/drivers/firmware/smccc/smccc.c
> index 695c920a8087..450605ddfab6 100644
> --- c/drivers/firmware/smccc/smccc.c
> +++ w/drivers/firmware/smccc/smccc.c
> @@ -9,21 +9,58 @@
> #include <linux/init.h>
> #include <linux/arm-smccc.h>
> #include <linux/kernel.h>
> -#include <linux/platform_device.h>
> #include <linux/arm-smccc-bus.h>
> #include <linux/idr.h>
> #include <linux/slab.h>
>
> -#include <asm/archrandom.h>
> -
> static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
> static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
> static DEFINE_IDA(arm_smccc_bus_id);
>
> -bool __ro_after_init smccc_trng_available = false;
> +struct smccc_device_info {
> + u32 func_id;
> + bool requires_smc;
> + unsigned long min_return;
Is this viable for all ? There may be additional restrictions around
the return values and further SMC calls ? Which brings us to call backs
and we kind of have a variant of that here.
Suzuki
> + const char *device_name;
> +};
> +
> +bool __ro_after_init smccc_trng_available;
> s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED;
> s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED;
>
> +static const struct smccc_device_info smccc_devices[] __initconst = {
> + {
> + .func_id = ARM_SMCCC_TRNG_VERSION,
> + .requires_smc = false,
> + .min_return = ARM_SMCCC_TRNG_MIN_VERSION,
> + .device_name = "arm-smccc-trng",
> + },
> +};
> +
> +static bool __init
> +smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
> +{
> + struct arm_smccc_res res;
> + unsigned long ret;
> +
> + if (!IS_ENABLED(CONFIG_ARM64))
> + return false;
> +
> + if (smccc_conduit == SMCCC_CONDUIT_NONE)
> + return false;
> +
> + if (smccc_dev->requires_smc && smccc_conduit != SMCCC_CONDUIT_SMC)
> + return false;
> +
> + arm_smccc_1_1_invoke(smccc_dev->func_id, &res);
> + ret = res.a0;
> +
> + if ((s32)ret < 0)
> + return false;
> +
> + return ret >= smccc_dev->min_return;
> +}
> +
> void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
> {
> struct arm_smccc_res res;
> @@ -31,7 +68,7 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
> smccc_version = version;
> smccc_conduit = conduit;
>
> - smccc_trng_available = smccc_probe_trng();
> + smccc_trng_available = smccc_probe_smccc_device(&smccc_devices[0]);
>
> if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
> (smccc_conduit != SMCCC_CONDUIT_NONE)) {
> @@ -241,14 +278,20 @@ subsys_initcall(arm_smccc_bus_init);
>
> static int __init smccc_devices_init(void)
> {
> - struct platform_device *pdev;
> -
> - if (smccc_trng_available) {
> - pdev = platform_device_register_simple("smccc_trng", -1,
> - NULL, 0);
> - if (IS_ERR(pdev))
> - pr_err("smccc_trng: could not register device: %ld\n",
> - PTR_ERR(pdev));
> + const struct smccc_device_info *smccc_dev;
> + struct arm_smccc_device *sdev;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(smccc_devices); i++) {
> + smccc_dev = &smccc_devices[i];
> +
> + if (!smccc_probe_smccc_device(smccc_dev))
> + continue;
> +
> + sdev = arm_smccc_device_register(smccc_dev->device_name);
> + if (IS_ERR(sdev))
> + pr_err("%s: could not register device: %ld\n",
> + smccc_dev->device_name, PTR_ERR(sdev));
> }
>
> return 0;
>
^ permalink raw reply
* Re: [PATCH v19 00/14] crypto/dmaengine: qce: introduce BAM locking and use DMA for register I/O
From: Vinod Koul @ 2026-06-04 10:24 UTC (permalink / raw)
To: Stephan Gerhold
Cc: Bartosz Golaszewski, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Bjorn Andersson, Peter Ujfalusi,
Michal Simek, Frank Li, Andy Gross, Neil Armstrong, dmaengine,
linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Dmitry Baryshkov,
Konrad Dybcio
In-Reply-To: <ah8G_ajPS1KhgPP_@linaro.org>
On 02-06-26, 18:38, Stephan Gerhold wrote:
> On Tue, May 26, 2026 at 03:10:48PM +0200, Bartosz Golaszewski wrote:
> > I feel like I fell into the trap of trying to address pre-existing
> > issues reported by sashiko and in the process provoking more reports so
> > let this be the last iteration where I do this. Vinod can we get this
> > queued for v7.2 now and iron out any previously existing problems in
> > tree?
>
> Thanks a lot for working on fixing all these issues!
>
> I agree there is no point addressing all the "pre-existing issues"
> pointed out by Sashiko, but have you looked through the other comments
> for new issues pointed out for your patches?
I hope Bart and Qualcomm can fix these driver issues as well
>
> Out of curiosity, I was looking a bit at the comments for [PATCH v19
> 06/14] dmaengine: qcom: bam_dma: add support for BAM locking [1]. There
> are 8 open comments there (Critical: 1, High: 6 and Medium: 1). From a
> quick look I would say most of these could be valid. The critical one
> about the usage of dma_cookie_assign() sounds a bit concerning to me, if
> it is true we would be basically breaking parts of the dmaengine API for
> consumers by inserting the lock descriptor in front of everything else.
Yes this seems to be a valid one. Attaching another descriptor for lock
does not sound right to me, as in this case causes descriptor to be
marked 'done' prematurely.
Honestly, I am not quite happy with the way lock is being handled here.
I would hope we can have some better suggestions. Adding a descriptor
for lock does not look right to me. We are adding odd hardware/firmware
behaviour on engine apis.
I had earlier suggested to lock always or lock only for hw/sw versions
supported inside the driver, that might be simplist solution without the
complexity added here
--
~Vinod
^ permalink raw reply
* [GIT PULL] Apple SoC DT changes for v7.2
From: Sven Peter @ 2026-06-04 10:25 UTC (permalink / raw)
To: soc; +Cc: asahi, linux-arm-kernel, linux-kernel, Sven Peter
The following changes since commit 254f49634ee16a731174d2ae34bc50bd5f45e731:
Linux 7.1-rc1 (2026-04-26 14:19:00 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/sven/linux.git tags/apple-soc-dt-7.2
for you to fetch changes up to c65ab4905e5874a1a489c72da4d6e78a6c9b5943:
arm64: dts: apple: Initial t8122 (M3) device trees (2026-06-01 21:25:24 +0200)
----------------------------------------------------------------
Apple SoC DT update for 7.2
Add minimal device trees for all t8122 / base M3 based devices and some
required new compatibles to the dt-bindings. These are enough to boot
Linux on these devices to a simple serial console but future work is
required to make these machines useful for end users.
Signed-off-by: Sven Peter <sven@kernel.org>
----------------------------------------------------------------
Janne Grunau (5):
dt-bindings: arm: apple: apple,pmgr: Add t8122 compatible
dt-bindings: power: apple,pmgr-pwrstate: Add t8122 compatible
dt-bindings: pwm: apple,s5l-fpwm: Add t8122 compatible
dt-bindings: arm: apple: Add M3 based devices
arm64: dts: apple: Initial t8122 (M3) device trees
Documentation/devicetree/bindings/arm/apple.yaml | 18 +
.../devicetree/bindings/arm/apple/apple,pmgr.yaml | 4 +-
.../bindings/power/apple,pmgr-pwrstate.yaml | 4 +-
.../devicetree/bindings/pwm/apple,s5l-fpwm.yaml | 1 +
arch/arm64/boot/dts/apple/Makefile | 5 +
arch/arm64/boot/dts/apple/t8122-j433.dts | 19 +
arch/arm64/boot/dts/apple/t8122-j434.dts | 19 +
arch/arm64/boot/dts/apple/t8122-j504.dts | 37 +
arch/arm64/boot/dts/apple/t8122-j613.dts | 35 +
arch/arm64/boot/dts/apple/t8122-j615.dts | 35 +
arch/arm64/boot/dts/apple/t8122-jxxx.dtsi | 48 +
arch/arm64/boot/dts/apple/t8122-pmgr.dtsi | 1149 ++++++++++++++++++++
arch/arm64/boot/dts/apple/t8122-usbpd-i2c.dtsi | 32 +
arch/arm64/boot/dts/apple/t8122.dtsi | 444 ++++++++
14 files changed, 1848 insertions(+), 2 deletions(-)
create mode 100644 arch/arm64/boot/dts/apple/t8122-j433.dts
create mode 100644 arch/arm64/boot/dts/apple/t8122-j434.dts
create mode 100644 arch/arm64/boot/dts/apple/t8122-j504.dts
create mode 100644 arch/arm64/boot/dts/apple/t8122-j613.dts
create mode 100644 arch/arm64/boot/dts/apple/t8122-j615.dts
create mode 100644 arch/arm64/boot/dts/apple/t8122-jxxx.dtsi
create mode 100644 arch/arm64/boot/dts/apple/t8122-pmgr.dtsi
create mode 100644 arch/arm64/boot/dts/apple/t8122-usbpd-i2c.dtsi
create mode 100644 arch/arm64/boot/dts/apple/t8122.dtsi
^ permalink raw reply
* Re: [PATCH v2 31/39] KVM: arm64: gic-v5: Add GICv5 SPI injection to irqfd
From: Vladimir Murzin @ 2026-06-04 10:51 UTC (permalink / raw)
To: Sascha Bischoff, linux-arm-kernel@lists.infradead.org,
kvmarm@lists.linux.dev, kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oliver.upton@linux.dev, Joey Gouly,
Suzuki Poulose, yuzenghui@huawei.com, peter.maydell@linaro.org,
lpieralisi@kernel.org, Timothy Hayes
In-Reply-To: <20260521144846.1899475-32-sascha.bischoff@arm.com>
Hi Sascha,
On 5/21/26 15:59, Sascha Bischoff wrote:
> Now that there is support for GICv5 SPIs in KVM, update
> vgic_irqfd_set_irq() to translate irqchip pins into GICv5 SPI IntIDs
> before injecting them.
>
> Also adjust IRQCHIP route validation for GICv5: use the configured SPI
> count, fall back to the default SPI count before VGIC init, and cap
> the accepted pin range to the generic irq routing table size.
>
> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> ---
> arch/arm64/kvm/vgic/vgic-irqfd.c | 20 +++++++++++++++++---
> 1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c
> index b9b86e3a6c862..3644516811214 100644
> --- a/arch/arm64/kvm/vgic/vgic-irqfd.c
> +++ b/arch/arm64/kvm/vgic/vgic-irqfd.c
> @@ -19,7 +19,12 @@ static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
> struct kvm *kvm, int irq_source_id,
> int level, bool line_status)
> {
> - unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
> + unsigned int spi_id;
> +
> + if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V5)
> + spi_id = vgic_v5_make_spi(e->irqchip.pin);
> + else
> + spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
>
> if (!vgic_valid_spi(kvm, spi_id))
> return -EINVAL;
> @@ -39,15 +44,24 @@ int kvm_set_routing_entry(struct kvm *kvm,
> struct kvm_kernel_irq_routing_entry *e,
> const struct kvm_irq_routing_entry *ue)
> {
> + unsigned int nr_pins = KVM_IRQCHIP_NUM_PINS;
> int r = -EINVAL;
>
> + if (vgic_is_v5(kvm)) {
> + nr_pins = kvm->arch.vgic.nr_spis;
> + if (!nr_pins)
> + nr_pins = VGIC_V5_DEFAULT_NR_SPIS;
> +
> + nr_pins = min(nr_pins, KVM_IRQCHIP_NUM_PINS);
> + }
> +
I have a few questions about these checks.
IIUC, there are two paths that can lead us here:
vgic_init()
-> kvm_vgic_setup_default_irq_routing()
-> kvm_set_irq_routing()
-> setup_routing_entry()
-> kvm_set_routing_entry()
where vgic_init() sets nr_spis to the default value if it has not
been configured already.
And:
kvm_vm_ioctl(KVM_SET_GSI_ROUTING)
-> kvm_set_irq_routing()
-> setup_routing_entry()
-> kvm_set_routing_entry()
where nr_spis would still be 0 if KVM_SET_GSI_ROUTING is used
before the vGIC is initialized. In that case, how much harm
processing with nr_spis set to 0? Wouldn't the routing be
overwritten once the vGIC is initialized anyway?
Also, IIUC, this is not specific to vGICv5 and appears to be
equally applicable to vGICv2/v3. If so, shouldn't we apply the
same validation logic to the non-vGICv5 cases as well?
Finally, it seems the core already enforces KVM_MAX_IRQ_ROUTES,
and we lower that limit to KVM_IRQCHIP_NUM_PINS. IIUC, nr_spis
limit for vGICv5 is FIELD_MAX(GICV5_IRS_IDR5_SPI_RANGE) which
exceeds both core and our private limit.
Would it be simpler/cleaner to reject nr_spis values provided
through KVM_DEV_ARM_VGIC_GRP_NR_IRQS rather than allowing them
and later capping the accepted pin range?
Thanks
Vladimir
> switch (ue->type) {
> case KVM_IRQ_ROUTING_IRQCHIP:
> e->set = vgic_irqfd_set_irq;
> e->irqchip.irqchip = ue->u.irqchip.irqchip;
> e->irqchip.pin = ue->u.irqchip.pin;
> - if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
> - (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
> + if (e->irqchip.pin >= nr_pins ||
> + e->irqchip.irqchip >= KVM_NR_IRQCHIPS)
> goto out;
> break;
> case KVM_IRQ_ROUTING_MSI:
> -- 2.34.1
>
^ permalink raw reply
* Re: [PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Sudeep Holla @ 2026-06-04 10:55 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: Aneesh Kumar K.V (Arm), linux-coco, linux-arm-kernel,
linux-kernel, Sudeep Holla, Catalin Marinas, Greg KH,
Jeremy Linton, Jonathan Cameron, Lorenzo Pieralisi, Mark Rutland,
Will Deacon, Steven Price
In-Reply-To: <bee6166c-f63e-4692-a874-b80b7a6f6dc4@arm.com>
On Thu, Jun 04, 2026 at 11:24:05AM +0100, Suzuki K Poulose wrote:
> On 04/06/2026 10:21, Sudeep Holla wrote:
> > On Wed, May 27, 2026 at 03:32:32PM +0530, Aneesh Kumar K.V (Arm) wrote:
> > > The Arm CCA guest TSM provider currently binds through the arm-cca-dev
> > > platform device. Like arm-smccc-trng, this device is not an independent
> > > platform resource; it is a software representation of the RSI firmware
> > > service discovered through SMCCC.
> > >
> > > Move RSI discovery into the SMCCC firmware driver. When the SMCCC conduit
> > > is SMC and the RSI ABI version check succeeds, create an arm-rsi-dev SMCCC
> > > device. Convert the Arm CCA guest TSM provider to an SMCCC driver so it
> > > binds to that discovered RSI service and keeps module autoloading through
> > > the SMCCC device id table.
> > >
> > > Keep the old arm-cca-dev platform-device registration for now. Userspace
> > > has used that device as a Realm-guest indicator, so removing it is left to
> > > a follow-up patch that adds a replacement sysfs ABI.
> > >
> > > Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> > > ---
> > > arch/arm64/include/asm/rsi.h | 2 +-
> > > arch/arm64/kernel/rsi.c | 2 +-
> > > drivers/firmware/smccc/Makefile | 4 ++
> > > drivers/firmware/smccc/rmm.c | 25 ++++++++
> > > drivers/firmware/smccc/rmm.h | 17 ++++++
> > > drivers/firmware/smccc/smccc.c | 8 +++
> > > drivers/virt/coco/arm-cca-guest/Kconfig | 1 +
> > > drivers/virt/coco/arm-cca-guest/Makefile | 2 +
> > > .../{arm-cca-guest.c => arm-cca.c} | 60 +++++++++----------
> > > 9 files changed, 89 insertions(+), 32 deletions(-)
> > > create mode 100644 drivers/firmware/smccc/rmm.c
> > > create mode 100644 drivers/firmware/smccc/rmm.h
> > > rename drivers/virt/coco/arm-cca-guest/{arm-cca-guest.c => arm-cca.c} (85%)
> > >
> > > diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
> > > index 88b50d660e85..2d2d363aaaee 100644
> > > --- a/arch/arm64/include/asm/rsi.h
> > > +++ b/arch/arm64/include/asm/rsi.h
> > > @@ -10,7 +10,7 @@
> > > #include <linux/jump_label.h>
> > > #include <asm/rsi_cmds.h>
> > > -#define RSI_PDEV_NAME "arm-cca-dev"
> > > +#define RSI_DEV_NAME "arm-rsi-dev"
> > > DECLARE_STATIC_KEY_FALSE(rsi_present);
> > > diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
> > > index 92160f2e57ff..da440f71bb64 100644
> > > --- a/arch/arm64/kernel/rsi.c
> > > +++ b/arch/arm64/kernel/rsi.c
> > > @@ -161,7 +161,7 @@ void __init arm64_rsi_init(void)
> > > }
> > > static struct platform_device rsi_dev = {
> > > - .name = RSI_PDEV_NAME,
> > > + .name = "arm-cca-dev",
> > > .id = PLATFORM_DEVID_NONE
> > > };
> > > diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile
> > > index 40d19144a860..33c850aaff4d 100644
> > > --- a/drivers/firmware/smccc/Makefile
> > > +++ b/drivers/firmware/smccc/Makefile
> > > @@ -2,3 +2,7 @@
> > > #
> > > obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o
> > > obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o
> > > +
> > > +ifeq ($(CONFIG_HAVE_ARM_SMCCC_DISCOVERY),y)
> > > +obj-$(CONFIG_ARM64) += rmm.o
> > > +endif
> > > diff --git a/drivers/firmware/smccc/rmm.c b/drivers/firmware/smccc/rmm.c
> > > new file mode 100644
> > > index 000000000000..d572f47e955c
> > > --- /dev/null
> > > +++ b/drivers/firmware/smccc/rmm.c
> > > @@ -0,0 +1,25 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * Copyright (C) 2026 Arm Limited
> > > + */
> > > +
> > > +#include <linux/arm-smccc-bus.h>
> > > +#include <linux/err.h>
> > > +#include <linux/printk.h>
> > > +
> > > +#include "rmm.h"
> > > +
> > > +void __init register_rsi_device(void)
> > > +{
> > > + unsigned long ret;
> > > +
> > > + if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
> > > + return;
> > > +
> > > + ret = rsi_request_version(RSI_ABI_VERSION, NULL, NULL);
> > > + if (ret != RSI_SUCCESS)
> > > + return;
> > > +
> > > + if (IS_ERR(arm_smccc_device_register(RSI_DEV_NAME)))
> > > + pr_err("%s: could not register device\n", RSI_DEV_NAME);
> > > +}
> >
> > OK, I had something else in my mind when I started looking at 1/4. I didn't
> > expect each device added on this bus comes up with it's own way to enumerate
> > it. IMO, it defeats the purpose of building the smccc bus. We may find the
> > specs for each feature deviated a bit but we can have a generic probe
> > IMO, let's try that before exploring per feature probe function.
>
> I guess this is ideal, but see below.
>
> >
> > I have a brief sketch of what I think we should aim for(uncompiled/untested)
> > below. Let me know if that makes sense. I just based it on your bus code.
> >
> > Regards,
> > Sudeep
> >
> > -->8
> >
> > diff --git c/drivers/firmware/smccc/smccc.c w/drivers/firmware/smccc/smccc.c
> > index 695c920a8087..450605ddfab6 100644
> > --- c/drivers/firmware/smccc/smccc.c
> > +++ w/drivers/firmware/smccc/smccc.c
> > @@ -9,21 +9,58 @@
> > #include <linux/init.h>
> > #include <linux/arm-smccc.h>
> > #include <linux/kernel.h>
> > -#include <linux/platform_device.h>
> > #include <linux/arm-smccc-bus.h>
> > #include <linux/idr.h>
> > #include <linux/slab.h>
> >
> > -#include <asm/archrandom.h>
> > -
> > static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
> > static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
> > static DEFINE_IDA(arm_smccc_bus_id);
> >
> > -bool __ro_after_init smccc_trng_available = false;
> > +struct smccc_device_info {
> > + u32 func_id;
> > + bool requires_smc;
I wanted to ask this but just forgot.
RSI uses SMC because the Realm is calling the RMM, not the host hypervisor.
Using HVC would make RSI look like a hypervisor ABI and would blur the trust
boundary, is that right assumption ?
I assume the conduit derived from PSCI node for the realms will always be
SMC and it shouldn't be a problem. I mean there won't be a case where you
would need HVC as conduit within the realm VM kernel ?
> > + unsigned long min_return;
>
> Is this viable for all ? There may be additional restrictions around
> the return values and further SMC calls ?
Fair enough, but do you have examples currently ?
> Which brings us to call backs and we kind of have a variant of that here.
>
I am fine with callback but need to keep the scope of it as minimum as
possible IMO. For me it's simple if that main FID for that feature is
implemented we create SMCCC device and probe can deal with all the extra
details, why won't that work ? Just trying to understand why the core
SMCCC bus need to know more or must provide a callback.
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v2 0/3] pinctrl: sunxi: a523: fix GPIO IRQ operation
From: Andre Przywara @ 2026-06-04 10:54 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland
Cc: linux-gpio, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, Linus Walleij
In-Reply-To: <20260327113006.3135663-1-andre.przywara@arm.com>
On Fri, 27 Mar 2026 11:30:03 +0000
Andre Przywara <andre.przywara@arm.com> wrote:
Hi,
> this is the minimal fix version for the GPIO IRQ operation on the
> Allwinner A523/A527/T527 SoCs. SD card detection is broken as a result,
> which is a major annoyance. Those patches here fix that problem, and
> should go into v7.0 still, if possible.
what is the status of this series, please? We missed v7.0 back then, but
please can we take this now, for v7.1? There are review tags for every
patch, and this fixes SD card operation on all A523/A527/T572 boards.
The series still applies cleanly on current master, if I should resend
anyway, please let me know.
Cheers,
Andre
> I dropped the more involved fixes from v1, the risk for regressions is
> now very low:
> - The quirk flag is just dropped from the A523, not the other SoCs. I
> confirmed this again with an experiment, for both the primary and
> secondary pincontroller. This avoids fixing the workaround code for
> now, which is more involved, but for now unneeded.
> - The DT patch just adds the missing interrupt. The IRQ association was
> always wrong and never worked, so this can't make it possibly worse.
> Together those two patches (plus the required binding change) fix the
> problem, I would appreciate if this could be taken ASAP, into v7.0 still.
> The generic pinctrl code is now untouched, which makes this also much
> easier to backport, and drops the dependencies on other v7.0-rc fixes.
>
> Bases on v7.0-rc1, but applies on later revisions as well.
>
> Please have a look and test, especially on A523/A527/T527 boards!
>
> Changelog v1 .. v2:
> - drop generic pinctrl fixes (for now)
> - drop quirk removal from other SoCs (for now)
> - add Chen-Yu's tag
>
> Cheers,
> Andre
>
> Andre Przywara (3):
> pinctrl: sunxi: a523: Remove unneeded IRQ remuxing flag
> dt-bindings: pinctrl: sun55i-a523: increase IRQ banks number
> arm64: dts: allwinner: a523: Add missing GPIO interrupt
>
> .../bindings/pinctrl/allwinner,sun55i-a523-pinctrl.yaml | 8 ++++----
> arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi | 3 ++-
> drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c | 1 -
> drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c | 1 -
> 4 files changed, 6 insertions(+), 7 deletions(-)
>
> base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
^ permalink raw reply
* [PATCH v1] KVM: arm64: Restore POR_EL0 access to host EL0
From: Joey Gouly @ 2026-06-04 10:54 UTC (permalink / raw)
To: kvmarm
Cc: joey.gouly, Marc Zyngier, Oliver Upton, Suzuki K Poulose,
Zenghui Yu, Steffen Eiden, linux-arm-kernel
CPTR_EL2.E0POE was being cleared in __deactivate_cptr_traps_vhe(), which meant
that any accesses to POR_EL0 from host EL0 would trap and be reported to
userspace as an Illegal instruction. This would happen after running any VM,
regardless if it used POE or not.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Link: https://sashiko.dev/#/patchset/20260602155430.2088142-1-maz@kernel.org?part=1
---
Tested by (paraphrased):
$ ./read_por_el0
$ ./lkvm run -f kvm-unit-tests/timer.flat
$ ./read_por_el0 # This gets "Illegal instruction"
Also ran the above flow in a nested VM.
arch/arm64/kvm/hyp/include/hyp/switch.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 320cd45d49c5..e9b36a3b27bb 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -181,6 +181,8 @@ static inline void __deactivate_cptr_traps_vhe(struct kvm_vcpu *vcpu)
val |= CPACR_EL1_ZEN;
if (cpus_have_final_cap(ARM64_SME))
val |= CPACR_EL1_SMEN;
+ if (cpus_have_final_cap(ARM64_HAS_S1POE))
+ val |= CPACR_EL1_E0POE;
write_sysreg(val, cpacr_el1);
}
--
2.25.1
^ permalink raw reply related
* [PATCH] KVM: arm64: Sanitise host vCPU fields in flush_hyp_vcpu()
From: Hyunwoo Kim @ 2026-06-04 11:18 UTC (permalink / raw)
To: maz, oupton, joey.gouly, seiden, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, imv4bel
flush_hyp_vcpu() copies the host vCPU context and vGIC state into the
hyp's private vCPU on every run. ctxt_to_vcpu() expects a guest context
to have a NULL __hyp_running_vcpu, which is only ever set on the host
context, so that it resolves the vCPU via container_of(). The vGIC list
register save and restore expect used_lrs to stay within the number of
implemented list registers. While this is generally the case,
flush_hyp_vcpu() copies both fields verbatim from the host vCPU and
enforces neither expectation.
Fix by clearing __hyp_running_vcpu and clamping used_lrs after the copy.
Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
---
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 06db299c37a89..ef9318ff0c25e 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -7,6 +7,7 @@
#include <hyp/adjust_pc.h>
#include <hyp/switch.h>
+#include <asm/arch_gicv3.h>
#include <asm/pgtable-types.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_emulate.h>
@@ -128,6 +129,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
+ /* A guest context must keep a NULL __hyp_running_vcpu. */
+ hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
+
hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
@@ -139,6 +143,13 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
+ /* Bound the host-provided used_lrs by the implemented list registers. */
+ if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
+ hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
+ min_t(unsigned int,
+ hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
+ (read_gicreg(ICH_VTR_EL2) & 0xf) + 1);
+
hyp_vcpu->vcpu.arch.pid = host_vcpu->arch.pid;
}
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox