* [PATCH v2 1/2] arm64: smccc: add cache clean/invalidate IDs and return codes
2026-06-08 22:07 [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider Srirangan Madhavan
@ 2026-06-08 22:07 ` Srirangan Madhavan
2026-06-08 22:07 ` [PATCH v2 2/2] cache: add SMCCC-backed cache invalidate provider Srirangan Madhavan
2026-06-23 23:37 ` [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider Srirangan Madhavan
2 siblings, 0 replies; 4+ messages in thread
From: Srirangan Madhavan @ 2026-06-08 22:07 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Conor Dooley,
Jonathan Cameron
Cc: Catalin Marinas, Will Deacon, Dan Williams, Thierry Reding,
Jonathan Hunter, Souvik Chakravarty, linux-arm-kernel,
linux-kernel, linux-tegra, Srirangan Madhavan
Define SMCCC Arch function IDs for CLEAN_INV_MEMREGION and its ATTRIBUTES
call, and add RATE_LIMITED/BUSY return codes from DEN0028 for callers that
need transient error handling.
Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
Reviewed-by: Jonathan Cameron <jic23@kernel.org>
---
include/linux/arm-smccc.h | 21 +++++++++++++++++++--
tools/include/linux/arm-smccc.h | 21 +++++++++++++++++++--
2 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 50b47eba7d01..8cba040e0816 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -105,6 +105,22 @@
ARM_SMCCC_SMC_32, \
0, 0x3fff)
+/*
+ * DEN0028 v1.7 defines these cache maintenance functions as SMC64
+ * because they carry 64-bit memory range arguments.
+ */
+#define ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_ARCH, \
+ 0x5)
+
+#define ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION_ATTRIBUTES \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_ARCH, \
+ 0x6)
+
#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
@@ -294,13 +310,14 @@
0x53)
/*
- * Return codes defined in ARM DEN 0070A
- * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
+ * Return codes defined by Arm SMCCC (DEN0028 v1.7).
*/
#define SMCCC_RET_SUCCESS 0
#define SMCCC_RET_NOT_SUPPORTED -1
#define SMCCC_RET_NOT_REQUIRED -2
#define SMCCC_RET_INVALID_PARAMETER -3
+#define SMCCC_RET_RATE_LIMITED -4
+#define SMCCC_RET_BUSY -5
#ifndef __ASSEMBLY__
diff --git a/tools/include/linux/arm-smccc.h b/tools/include/linux/arm-smccc.h
index 63ce9bebccd3..ae5637b3240f 100644
--- a/tools/include/linux/arm-smccc.h
+++ b/tools/include/linux/arm-smccc.h
@@ -96,6 +96,22 @@
ARM_SMCCC_SMC_32, \
0, 0x3fff)
+/*
+ * DEN0028 v1.7 defines these cache maintenance functions as SMC64
+ * because they carry 64-bit memory range arguments.
+ */
+#define ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_ARCH, \
+ 0x5)
+
+#define ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION_ATTRIBUTES \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_ARCH, \
+ 0x6)
+
#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
@@ -182,12 +198,13 @@
0x53)
/*
- * Return codes defined in ARM DEN 0070A
- * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
+ * Return codes defined by Arm SMCCC (DEN0028 v1.7).
*/
#define SMCCC_RET_SUCCESS 0
#define SMCCC_RET_NOT_SUPPORTED -1
#define SMCCC_RET_NOT_REQUIRED -2
#define SMCCC_RET_INVALID_PARAMETER -3
+#define SMCCC_RET_RATE_LIMITED -4
+#define SMCCC_RET_BUSY -5
#endif /*__LINUX_ARM_SMCCC_H*/
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] cache: add SMCCC-backed cache invalidate provider
2026-06-08 22:07 [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider Srirangan Madhavan
2026-06-08 22:07 ` [PATCH v2 1/2] arm64: smccc: add cache clean/invalidate IDs and return codes Srirangan Madhavan
@ 2026-06-08 22:07 ` Srirangan Madhavan
2026-06-23 23:37 ` [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider Srirangan Madhavan
2 siblings, 0 replies; 4+ messages in thread
From: Srirangan Madhavan @ 2026-06-08 22:07 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Conor Dooley,
Jonathan Cameron
Cc: Catalin Marinas, Will Deacon, Dan Williams, Thierry Reding,
Jonathan Hunter, Souvik Chakravarty, linux-arm-kernel,
linux-kernel, linux-tegra, Srirangan Madhavan
Add a cache maintenance provider for the Arm SMCCC cache clean+invalidate
interface.
The provider discovers SMCCC support and attributes at init time,
serializes firmware calls, handles transient BUSY and RATE_LIMITED
responses with bounded retries, and registers with the generic cache
coherency framework used by memregion callers.
Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
Reviewed-by: Jonathan Cameron <jic23@kernel.org>
---
drivers/cache/Kconfig | 11 +++
drivers/cache/Makefile | 2 +
drivers/cache/arm_smccc_cache.c | 157 ++++++++++++++++++++++++++++++++
3 files changed, 170 insertions(+)
create mode 100644 drivers/cache/arm_smccc_cache.c
diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 1518449d47b5..57fd1823dec5 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -42,6 +42,17 @@ menuconfig CACHEMAINT_FOR_HOTPLUG
if CACHEMAINT_FOR_HOTPLUG
+config ARM_SMCCC_CACHE
+ bool "Arm SMCCC cache maintenance provider"
+ depends on ARM64 && HAVE_ARM_SMCCC_DISCOVERY
+ help
+ Enable support for the Arm SMCCC cache clean+invalidate
+ interface as a provider for memory hotplug-like cache
+ maintenance operations.
+ The provider registers only when firmware advertises the
+ SMCCC calls and attributes, so systems without firmware support
+ continue without this registered provider.
+
config HISI_SOC_HHA
tristate "HiSilicon Hydra Home Agent (HHA) device driver"
depends on (ARM64 && ACPI) || COMPILE_TEST
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index b3362b15d6c1..55736a032d6f 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -4,4 +4,6 @@ obj-$(CONFIG_AX45MP_L2_CACHE) += ax45mp_cache.o
obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o
obj-$(CONFIG_STARFIVE_STARLINK_CACHE) += starfive_starlink_cache.o
+# Providers below depend on CACHEMAINT_FOR_HOTPLUG.
+obj-$(CONFIG_ARM_SMCCC_CACHE) += arm_smccc_cache.o
obj-$(CONFIG_HISI_SOC_HHA) += hisi_soc_hha.o
diff --git a/drivers/cache/arm_smccc_cache.c b/drivers/cache/arm_smccc_cache.c
new file mode 100644
index 000000000000..82b9efdb190b
--- /dev/null
+++ b/drivers/cache/arm_smccc_cache.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 NVIDIA Corporation
+ *
+ * Arm SMCCC cache maintenance provider using cache clean+invalidate calls.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/cache_coherency.h>
+#include <linux/cleanup.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/nmi.h>
+
+#define SMCCC_CACHE_MAX_RETRIES 5
+#define SMCCC_CACHE_DEFAULT_DELAY_US 1000UL
+#define SMCCC_CACHE_MAX_DELAY_US 20000UL
+
+struct smccc_cache {
+ /* Must be first member */
+ struct cache_coherency_ops_inst cci;
+ struct mutex lock; /* Serializes SMCCC cache maintenance calls. */
+ u32 latency_us;
+ u32 rate_limit;
+};
+
+static int smccc_cache_status_to_errno(s32 status)
+{
+ switch (status) {
+ case SMCCC_RET_SUCCESS:
+ return 0;
+ case SMCCC_RET_NOT_SUPPORTED:
+ return -EOPNOTSUPP;
+ case SMCCC_RET_INVALID_PARAMETER:
+ return -EINVAL;
+ case SMCCC_RET_RATE_LIMITED:
+ return -EAGAIN;
+ case SMCCC_RET_BUSY:
+ return -EBUSY;
+ default:
+ return -EIO;
+ }
+}
+
+static unsigned long smccc_cache_delay_us(const struct smccc_cache *cache)
+{
+ unsigned long delay_us = 0;
+
+ if (cache->rate_limit)
+ delay_us = DIV_ROUND_UP_ULL(USEC_PER_SEC, cache->rate_limit);
+
+ if (cache->latency_us)
+ delay_us = max(delay_us, (unsigned long)cache->latency_us);
+
+ /*
+ * Firmware may advertise neither a rate limit nor a latency hint; use
+ * a small bounded backoff instead of retrying in a tight loop.
+ */
+ if (!delay_us)
+ delay_us = SMCCC_CACHE_DEFAULT_DELAY_US;
+
+ return min(delay_us, SMCCC_CACHE_MAX_DELAY_US);
+}
+
+static int smccc_cache_wbinv(struct cache_coherency_ops_inst *cci,
+ struct cc_inval_params *invp)
+{
+ struct smccc_cache *cache = container_of(cci, struct smccc_cache, cci);
+ struct arm_smccc_res res = {};
+ unsigned long delay_us = smccc_cache_delay_us(cache);
+ int ret;
+
+ if (!invp->size)
+ return -EINVAL;
+
+ /*
+ * Serialize the full retry sequence. With the default bounds, a caller
+ * may hold the mutex across up to five 20ms backoff sleeps.
+ */
+ guard(mutex)(&cache->lock);
+
+ for (unsigned int i = 0; i < SMCCC_CACHE_MAX_RETRIES; i++) {
+ /* Long firmware operations can trigger watchdog checks. */
+ touch_nmi_watchdog();
+
+ arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION,
+ invp->addr, invp->size, 0UL, &res);
+
+ ret = smccc_cache_status_to_errno((s32)res.a0);
+ if (!ret)
+ return 0;
+
+ if (ret != -EBUSY && ret != -EAGAIN)
+ return ret;
+
+ fsleep(delay_us);
+ }
+
+ return -EBUSY;
+}
+
+static const struct cache_coherency_ops smccc_cache_ops = {
+ .wbinv = smccc_cache_wbinv,
+};
+
+static int __init smccc_cache_init(void)
+{
+ struct smccc_cache *cache;
+ struct arm_smccc_res res = {};
+ int ret;
+
+ if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_1)
+ return -ENODEV;
+
+ if (arm_smccc_1_1_get_conduit() == SMCCC_CONDUIT_NONE)
+ return -ENODEV;
+
+ arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+ ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION, &res);
+ if ((s32)res.a0 < 0)
+ return -ENODEV;
+
+ arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+ ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION_ATTRIBUTES,
+ &res);
+ if ((s32)res.a0 < 0)
+ return -ENODEV;
+
+ arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_CLEAN_INV_MEMREGION_ATTRIBUTES,
+ &res);
+ if ((s32)res.a0)
+ return -ENODEV;
+
+ cache = cache_coherency_ops_instance_alloc(&smccc_cache_ops,
+ struct smccc_cache, cci);
+ if (!cache)
+ return -ENOMEM;
+
+ mutex_init(&cache->lock);
+ cache->latency_us = lower_32_bits(res.a2);
+ cache->rate_limit = lower_32_bits(res.a3);
+
+ ret = cache_coherency_ops_instance_register(&cache->cci);
+ if (ret) {
+ mutex_destroy(&cache->lock);
+ cache_coherency_ops_instance_put(&cache->cci);
+ return ret;
+ }
+
+ pr_info("SMCCC cache clean+invalidate provider registered\n");
+
+ return 0;
+}
+arch_initcall(smccc_cache_init);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider
2026-06-08 22:07 [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider Srirangan Madhavan
2026-06-08 22:07 ` [PATCH v2 1/2] arm64: smccc: add cache clean/invalidate IDs and return codes Srirangan Madhavan
2026-06-08 22:07 ` [PATCH v2 2/2] cache: add SMCCC-backed cache invalidate provider Srirangan Madhavan
@ 2026-06-23 23:37 ` Srirangan Madhavan
2 siblings, 0 replies; 4+ messages in thread
From: Srirangan Madhavan @ 2026-06-23 23:37 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Conor Dooley,
Jonathan Cameron
Cc: Catalin Marinas, Will Deacon, Dan Williams, Thierry Reding,
Jon Hunter, Vikram Sethi, Souvik Chakravarty,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org
Hi all,
Gentle ping on this v2.
This version includes Jonathan's Reviewed-by tags and addresses the v1
comments around the Kconfig wording, Makefile ordering/comment, and retry
loop handling.
The main open question from v1 was whether DEN0028 v1.7 BET0 is sufficient
for merging these SMCCC cache maintenance definitions/provider. Could one
of the Arm/SMCCC maintainers please confirm whether this is acceptable for
merge, or whether the series should wait for a non-beta spec revision?
If the spec status is acceptable, please let me know if there are any
remaining concerns with v2.
Thanks,
Srirangan
________________________________________
From: Srirangan Madhavan
Sent: Monday, June 8, 2026 3:07 PM
To: Mark Rutland; Lorenzo Pieralisi; Sudeep Holla; Conor Dooley; Jonathan Cameron
Cc: Catalin Marinas; Will Deacon; Dan Williams; Thierry Reding; Jon Hunter; Souvik Chakravarty; linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org; linux-tegra@vger.kernel.org; Srirangan Madhavan
Subject: [PATCH v2 0/2] Add SMCCC cache clean/invalidate provider
This series adds an arm64 backend for memregion cache invalidation users
based on the Arm SMCCC cache clean+invalidate interface.
Per DEN0028, this interface targets systems where a Normal Cacheable
memory region can be modified in ways that are not handled by usual PE
coherency mechanisms, and where VA-based CMOs may be too slow or
insufficient for large ranges and/or system-cache implementations.
Representative use cases include device-backed memory state transitions
where stale CPU/system cache lines must be invalidated reliably (for
example secure erase, reset/offline flows, and dynamic memory
reconfiguration).
Patch 1 introduces the Arm SMCCC cache clean/invalidate function IDs and
transient return codes needed by callers [1].
Patch 2 adds a cache maintenance provider that:
- discovers SMCCC support and attributes at init time
- registers with the generic cache coherency framework used by
cpu_cache_invalidate_memregion()
- handles transient BUSY/RATE_LIMITED responses with bounded retries
This patch set does not add a software fallback path; when firmware does
not implement the SMCCC cache maintenance interface, the provider is not
registered and existing behavior is preserved.
Reference:
[1] https://developer.arm.com/documentation/den0028/latest
Note: Jonathan Cameron raised whether DEN0028 v1.7 BET0 is sufficient
for merge. Input from Arm maintainers / SMCCC spec owners on that point
would be appreciated.
Changes since v1:
- Added Jonathan Cameron's Reviewed-by tags.
- Clarified the ARM_SMCCC_CACHE Kconfig help text.
- Added a Makefile comment identifying the providers that depend on
CACHEMAINT_FOR_HOTPLUG.
- Dropped the final-backoff-sleep skip in the retry loop.
Changes since RFC:
- Dropped the RFC tag.
- Moved the provider from arch/arm64/mm to drivers/cache.
- Added a dedicated CONFIG_ARM_SMCCC_CACHE option under the existing
CACHEMAINT_FOR_HOTPLUG menu.
- Dropped the global-operation coalescing optimization.
- Dropped provider handling for SMCCC_RET_NOT_REQUIRED.
- Removed the unnecessary global provider pointer.
- Removed arm64_ prefixes from static provider-local names.
- Documented why these SMCCC Arch cache maintenance calls use SMC64.
- Anchored the SMCCC return-code comment to DEN0028 v1.7.
- Used fsleep() for retry backoff.
- Used unsigned long for retry delay values passed to fsleep().
- Skipped the final backoff sleep when no retry remains.
- Documented the bounded mutex hold time across the serialized retry
sequence.
- Added mutex_destroy() on the registration failure path.
Srirangan Madhavan (2):
arm64: smccc: add cache clean/invalidate IDs and return codes
cache: add SMCCC-backed cache invalidate provider
drivers/cache/Kconfig | 11 +++
drivers/cache/Makefile | 2 +
drivers/cache/arm_smccc_cache.c | 157 ++++++++++++++++++++++++++++++++
include/linux/arm-smccc.h | 21 ++++-
tools/include/linux/arm-smccc.h | 21 ++++-
5 files changed, 208 insertions(+), 4 deletions(-)
create mode 100644 drivers/cache/arm_smccc_cache.c
base-commit: 3b3bea6d4b9c162f9e555905d96b8c1da67ecd5b
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread