* Re: [PATCH v2 1/3] KVM: arm64: Reset page order in pKVM hyp_pool_init
From: Vincent Donnefort @ 2026-05-21 13:21 UTC (permalink / raw)
To: Fuad Tabba
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team,
qperret, Sashiko
In-Reply-To: <CA+EHjTxPoxjvMTZX5w+UyVgC=W3VUSDoOQ-tCDLfnae16SqoMQ@mail.gmail.com>
On Thu, May 21, 2026 at 02:07:36PM +0100, Fuad Tabba wrote:
> On Thu, 21 May 2026 at 11:22, Vincent Donnefort <vdonnefort@google.com> wrote:
> >
> > When a VM fails to initialise after its stage-2 hyp_pool has been
> > initialised, that stage-2 must be torn down entirely. This requires
> > resetting both the refcount and the order of its pages back to 0.
> >
> > Currently, reclaim_pgtable_pages() implicitly resets the page order by
> > allocating the entire pool with order-0 granularity. However, in the VM
> > initialisation error path, the addresses of the donated memory (the PGD)
> > are already known, making it unnecessary to iterate over all pages in
> > the pool.
> >
> > Since the vmemmap page order is a hyp_pool-specific field, leaving a
> > non-zero order on hyp_pool destruction is harmless until another pool
> > attempts to admit the page. Instead of resetting this field during
> > destruction, reset it during pool initialization in hyp_pool_init().
> > Note that pages added to the pool outside of the initial pool range
> > (e.g., via guest_s2_zalloc_page()) must still have their order managed
> > manually.
> >
> > While at it, add a WARN_ON() in the hyp_pool attach path to catch
> > unexpected page orders that exceed the pool's max_order.
> >
> > Fixes: 256b4668cd89 ("KVM: arm64: Introduce separate hypercalls for pKVM VM reservation and initialization")
> > Reported-by: Sashiko <sashiko-bot@kernel.org>
> > Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> >
> > diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> > index 25f04629014e..89eb20d4fee4 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> > @@ -322,7 +322,6 @@ void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
> > while (addr) {
> > page = hyp_virt_to_page(addr);
> > page->refcount = 0;
> > - page->order = 0;
> > push_hyp_memcache(mc, addr, hyp_virt_to_phys);
> > WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(addr), 1));
> > addr = hyp_alloc_pages(&vm->pool, 0);
> > diff --git a/arch/arm64/kvm/hyp/nvhe/page_alloc.c b/arch/arm64/kvm/hyp/nvhe/page_alloc.c
> > index a1eb27a1a747..c3b3dc5a8ea7 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/page_alloc.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/page_alloc.c
> > @@ -97,6 +97,8 @@ static void __hyp_attach_page(struct hyp_pool *pool,
> > u8 order = p->order;
> > struct hyp_page *buddy;
> >
> > + WARN_ON(p->order > pool->max_order);
> > +
>
> Could you add a brief comment? It took me a minute to figure out what this
> catches. IIUC it's not attach's own input, it's a stale p->order from way back
> when an external page was popped from a memcache (today only via
> guest_s2_zalloc_page()). Right?
I think it'd be self explanatory if that was next the page_add_to_list, but that
wouldn't protect the memset (that's really best-effort though).
How about?
/*
* A page with an order bigger than the pool's max is an 'external' page
* whose order hasn't been reset before being added to the pool.
*/
But now I am thinking I can do way better: we can easily identify external
pages, so I could just force the order to 0 in that case.
WDYS?
>
> With that.
>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Tested-by: Fuad Tabba <tabba@google.com>
>
> Cheers,
> /fuad
>
>
>
>
> > memset(hyp_page_to_virt(p), 0, PAGE_SIZE << p->order);
> >
> > /* Skip coalescing for 'external' pages being freed into the pool. */
> > @@ -237,8 +239,10 @@ int hyp_pool_init(struct hyp_pool *pool, u64 pfn, unsigned int nr_pages,
> >
> > /* Init the vmemmap portion */
> > p = hyp_phys_to_page(phys);
> > - for (i = 0; i < nr_pages; i++)
> > + for (i = 0; i < nr_pages; i++) {
> > hyp_set_page_refcounted(&p[i]);
> > + p[i].order = 0;
> > + }
> >
> > /* Attach the unused pages to the buddy tree */
> > for (i = reserved_pages; i < nr_pages; i++)
> > --
> > 2.54.0.746.g67dd491aae-goog
> >
^ permalink raw reply
* [GIT PULL] amlogic ARM64 DT updates for v7.2 take 1
From: Neil Armstrong @ 2026-05-21 13:19 UTC (permalink / raw)
To: soc, arm; +Cc: linux-amlogic, linux-arm-kernel
Hi,
Here's the Amlogic ARM64 DT changes for v7.2, contains improvements for the Khadas VIM4
and VIM1s SBCs, plus some additions for the Phicomm N1 and a couple of low priority fixes.
This PR is largely the same as `amlogic-arm64-dt-for-v7.1`, but I sent the fixes
separately as `amlogic-fixes-v7.1-rc` as discussed with Arnd, so this tag
`amlogic-arm64-dt-for-v7.2-v1` is based on top of `amlogic-fixes-v7.1-rc`.
Thanks,
Neil
The following changes since commit 174a0ef3b33434f475c87e66f37980e39b73805a:
arm64: dts: meson-gxl-p230: fix ethernet PHY interrupt number (2026-04-21 15:46:29 +0200)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git amlogic-arm64-dt-for-v7.2-v1
for you to fetch changes up to 43e6ece01ba673c3bd8dd1638bcd93827d254b3d:
arm64: dts: amlogic: t7: Add i2c pinctrl node (2026-05-18 16:23:29 +0200)
----------------------------------------------------------------
Amlogic ARM64 DT for v7.2 take 1:
- Khadas VIM4 (T7 SoC) features:
- Memory layout fixup
- GIC register range
- Model name fixup
- PWM, eMMC, SD card and SDIO support
- PWM LED
- I2C pinctrl node
- Khadas VIM1s Features
- Bluetooth
- PWM LED
- Power Key
- Function Key via SARADC
- RTC
- Remote control keymap
- Bluetooth node for Phicomm N1
----------------------------------------------------------------
Jian Hu (1):
arm64: dts: amlogic: t7: Add clock controller nodes
Jun Yan (1):
arm64: dts: amlogic: meson-gxl-s905d-phicomm-n1: add bluetooth node
Nick Xie (9):
arm64: dts: amlogic: meson-s4: add UART_A node
arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: enable bluetooth
arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: add PWM LED support
arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: add POWER key support
arm64: dts: amlogic: meson-s4: add internal SARADC controller
arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: add Function key support
arm64: dts: amlogic: meson-s4: add VRTC node
arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: enable HYM8563 RTC
arm64: dts: amlogic: meson-s4-s905y4-khadas-vim1s: use rc-khadas keymap
Ronald Claveau (12):
arm64: dts: amlogic: t7: Add eMMC, SD card and SDIO pinctrl nodes
arm64: dts: amlogic: t7: Add PWM pinctrl nodes
arm64: dts: amlogic: t7: khadas-vim4: Add power regulators
arm64: dts: amlogic: t7: khadas-vim4: Remove invalid property
arm64: dts: amlogic: t7: Add MMC controller nodes
arm64: dts: amlogic: t7: Add PWM controller nodes
arm64: dts: amlogic: t7: khadas-vim4: Add SDIO power sequence and WiFi clock
arm64: dts: amlogic: t7: khadas-vim4: Add MMC nodes
arm64: dts: amlogic: t7: Fix missing required reset property
arm64: dts: amlogic: t7: khadas-vim4: reorder root node
arm64: dts: amlogic: t7: khadas-vim4: add PWM-driven status LED
arm64: dts: amlogic: t7: Add i2c pinctrl node
.../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 215 +++++++++
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 482 +++++++++++++++++++++
.../dts/amlogic/meson-gxl-s905d-phicomm-n1.dts | 15 +
.../dts/amlogic/meson-s4-s905y4-khadas-vim1s.dts | 81 ++++
arch/arm64/boot/dts/amlogic/meson-s4.dtsi | 45 ++
5 files changed, 838 insertions(+)
^ permalink raw reply
* [PATCH v6] stm: class: Add MIPI OST protocol support
From: Yingchao Deng @ 2026-05-21 13:14 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Jonathan Corbet, Shuah Khan, Alexander Shishkin, Alexandre Torgue
Cc: linux-kernel, linux-trace-kernel, linux-doc, linux-arm-kernel,
quic_yingdeng, tingwei.zhang, jinlong.mao, jie.gan,
yuanfang.zhang, Yingchao Deng
Add MIPI OST (Open System Trace) protocol support for stm to format the
traces. The OST Protocol abstracts the underlying layers from the sending
and receiving applications, thus removing dependencies on the connection
media and platform implementation.
OST over STP packet consists of Header/Payload/End. Header is designed to
include the information required by all OST packets. Information that is
not shared by all packets is left to the higher layer protocols. Thus, the
OST Protocol Header can be regarded as the first part of a complete OST
Packet Header, while a higher layer header can be regarded as an extension
designed for a specific purpose.
+--------+--------+--------+--------+
| start |version |entity |protocol|
+--------+--------+--------+--------+
| stm version | magic |
+-----------------------------------+
| cpu |
+-----------------------------------+
| timestamp |
| |
+-----------------------------------+
| tgid |
| |
+-----------------------------------+
| payload |
+-----------------------------------+
| ... | end |
+-----------------------------------+
In header, there will be STARTSIMPLE/VERSION/ENTITY/PROTOCOL.
STARTSIMPLE is used to signal the beginning of a simplified OST protocol.
The Version field is a one byte, unsigned number identifying the version
of the OST Protocol. The Entity ID field is a one byte unsigned number
that identifies the source.
Entity ID values (0~239) are defined and controlled by the TS owner, and
shall be unique for the whole TS. The configfs entity attribute allows the
user to configure which Entity ID is associated with each policy node.
The Protocol ID field is a one byte unsigned number identifying the higher
layer protocol of the OST Packet, i.e. identifying the format of the data
after the OST Protocol Header. OST Control Protocol ID value represents
the common control protocol, the remaining Protocol ID values may be used
by any higher layer protocols capable of being transported by the OST
Protocol.
Co-developed-by: Tingwei Zhang <tingwei.zhang@oss.qualcomm.com>
Signed-off-by: Tingwei Zhang <tingwei.zhang@oss.qualcomm.com>
Co-developed-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
Signed-off-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
Co-developed-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
Changes in v6:
1. Rebase on top of linux-next-20260518.
2. Fix Kconfig: 'default CONFIG_STM' -> 'default STM'.
3. Fix documentation grammar issues.
4. Add p_ost entry to Documentation/trace/index.rst.
5. Add missing priv_sz field to stm_protocol_driver registration.
6. Use kzalloc_obj() instead of kzalloc() in ost_output_open().
7. Add mutex protection in entity configfs store handler.
8. Keep the configfs entity attribute: entity ID values (0~239) are
defined and controlled by the TS owner and are deployment-specific.
stm_source_type only carries a small number of in-kernel source
classifications and cannot represent the full range of OST entity
assignments needed in practice. The configfs attribute allows each
policy node to declare its entity.
OST_ENTITY_TYPE_NONE is an enum sentinel (not entity ID 0) that causes
ost_write() to return -EINVAL when no entity is configured, preventing
emission of packets with an unintended entity field.
OST_ENTITY_DIAG (0xEE) is a TS-owner-defined value used by Qualcomm's
diagnostic framework as the standard entity identifier for diagnostic
trace sources.
Link to v5: https://lore.kernel.org/all/20260129-p_ost-v5-1-2b14fff39428@oss.qualcomm.com/
Changes in v5:
1. Add Co-developed-by tag.
2. Use yearless copyright for new file.
- Link to v4: https://lore.kernel.org/all/20251024-p_ost-v4-1-3652a06fd055@oss.qualcomm.com/
Changes in v4:
1. Delete unused variable 'i'.
2. Fix build error: call to undeclared function 'task_tgid_nr'.
Link to v3 - https://lore.kernel.org/all/20251022071834.1658684-1-yingchao.deng@oss.qualcomm.com/
Changes in v3:
1. Add more details about OST.
2. Delete 'entity_available' node, and 'entity' node will show available
and currently selected (shown in square brackets) entity.
3. Removed the usage of config_item->ci_group->cg_subsys->su_mutex.
Link to v2 - https://lore.kernel.org/all/20230419141328.37472-1-quic_jinlmao@quicinc.com/
---
.../ABI/testing/configfs-stp-policy-p_ost | 9 +
Documentation/trace/index.rst | 1 +
Documentation/trace/p_ost.rst | 39 ++++
drivers/hwtracing/stm/Kconfig | 14 ++
drivers/hwtracing/stm/Makefile | 2 +
drivers/hwtracing/stm/p_ost.c | 241 +++++++++++++++++++++
6 files changed, 306 insertions(+)
diff --git a/Documentation/ABI/testing/configfs-stp-policy-p_ost b/Documentation/ABI/testing/configfs-stp-policy-p_ost
new file mode 100644
index 000000000000..8fb160b50c40
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-stp-policy-p_ost
@@ -0,0 +1,9 @@
+What: /config/stp-policy/<device>:p_ost.<policy>/<node>/entity
+Date: May 2026
+KernelVersion: 7.1
+Description:
+ Set the entity ID which identifies the trace source in the
+ OST packet header. Entity ID values (0~239) are defined by
+ the TS owner. Currently supported values are ftrace, console
+ and diag. RW.
+
diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst
index 5d9bf4694d5d..9cd1e0b5af6d 100644
--- a/Documentation/trace/index.rst
+++ b/Documentation/trace/index.rst
@@ -72,6 +72,7 @@ interactions and system performance.
intel_th
stm
sys-t
+ p_ost
coresight/index
rv/index
hisi-ptt
diff --git a/Documentation/trace/p_ost.rst b/Documentation/trace/p_ost.rst
new file mode 100644
index 000000000000..2b92e2229653
--- /dev/null
+++ b/Documentation/trace/p_ost.rst
@@ -0,0 +1,39 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================
+MIPI OST over STP
+===================
+
+The OST (Open System Trace) driver is used with STM class devices to
+generate standardized trace stream. Trace sources can be identified
+by different entity IDs.
+
+CONFIG_STM_PROTO_OST is for p_ost driver enablement. Once this config
+is enabled, you can select the p_ost protocol by command below:
+
+# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy
+
+The policy name format is extended like this:
+
+ <device_name>:<protocol_name>.<policy_name>
+
+With a coresight-stm device, it will look like "stm0:p_ost.policy".
+
+With the MIPI OST protocol driver, the attributes for each protocol node are:
+
+# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy/default
+# ls /sys/kernel/config/stp-policy/stm0:p_ost.policy/default
+channels entity masters
+
+The entity here is the set of entities that p_ost supports. Currently
+p_ost supports ftrace, console and diag entities.
+
+Set entity:
+# echo 'ftrace' > /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity
+
+Get available and currently selected (shown in square brackets) entity:
+# cat /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity
+[ftrace] console diag
+
+See Documentation/ABI/testing/configfs-stp-policy-p_ost for more details.
+
diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
index cd7f0b0f3fbe..4c83da5d95a0 100644
--- a/drivers/hwtracing/stm/Kconfig
+++ b/drivers/hwtracing/stm/Kconfig
@@ -40,6 +40,20 @@ config STM_PROTO_SYS_T
If you don't know what this is, say N.
+config STM_PROTO_OST
+ tristate "MIPI OST STM framing protocol driver"
+ default STM
+ help
+ This is an implementation of MIPI OST protocol to be used
+ over the STP transport. In addition to the data payload, it
+ also carries additional metadata for entity, better
+ means of trace source identification, etc.
+
+ The receiving side must be able to decode this protocol in
+ addition to the MIPI STP, in order to extract the data.
+
+ If you don't know what this is, say N.
+
config STM_DUMMY
tristate "Dummy STM driver"
help
diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
index 1692fcd29277..d9c8615849b9 100644
--- a/drivers/hwtracing/stm/Makefile
+++ b/drivers/hwtracing/stm/Makefile
@@ -5,9 +5,11 @@ stm_core-y := core.o policy.o
obj-$(CONFIG_STM_PROTO_BASIC) += stm_p_basic.o
obj-$(CONFIG_STM_PROTO_SYS_T) += stm_p_sys-t.o
+obj-$(CONFIG_STM_PROTO_OST) += stm_p_ost.o
stm_p_basic-y := p_basic.o
stm_p_sys-t-y := p_sys-t.o
+stm_p_ost-y := p_ost.o
obj-$(CONFIG_STM_DUMMY) += dummy_stm.o
diff --git a/drivers/hwtracing/stm/p_ost.c b/drivers/hwtracing/stm/p_ost.c
new file mode 100644
index 000000000000..d2174872b761
--- /dev/null
+++ b/drivers/hwtracing/stm/p_ost.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * MIPI OST framing protocol for STM devices.
+ */
+
+#include <linux/pid.h>
+#include <linux/sched/clock.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+#include "stm.h"
+
+/*
+ * OST Base Protocol Header
+ *
+ * Position Bits Field Name
+ * 0 8 STARTSIMPLE
+ * 1 8 Version
+ * 2 8 Entity ID
+ * 3 8 Protocol ID
+ */
+#define OST_FIELD_STARTSIMPLE 0
+#define OST_FIELD_VERSION 8
+#define OST_FIELD_ENTITY 16
+#define OST_FIELD_PROTOCOL 24
+
+#define OST_TOKEN_STARTSIMPLE 0x10
+#define OST_VERSION_MIPI1 0x10
+
+/* entity id to identify the source */
+#define OST_ENTITY_FTRACE 0x01
+#define OST_ENTITY_CONSOLE 0x02
+#define OST_ENTITY_DIAG 0xEE
+
+#define OST_CONTROL_PROTOCOL 0x0
+
+#define DATA_HEADER ((OST_TOKEN_STARTSIMPLE << OST_FIELD_STARTSIMPLE) | \
+ (OST_VERSION_MIPI1 << OST_FIELD_VERSION) | \
+ (OST_CONTROL_PROTOCOL << OST_FIELD_PROTOCOL))
+
+#define STM_MAKE_VERSION(ma, mi) (((ma) << 8) | (mi))
+#define STM_HEADER_MAGIC (0x5953)
+
+enum ost_entity_type {
+ OST_ENTITY_TYPE_NONE,
+ OST_ENTITY_TYPE_FTRACE,
+ OST_ENTITY_TYPE_CONSOLE,
+ OST_ENTITY_TYPE_DIAG,
+};
+
+static const char * const str_ost_entity_type[] = {
+ [OST_ENTITY_TYPE_NONE] = "none",
+ [OST_ENTITY_TYPE_FTRACE] = "ftrace",
+ [OST_ENTITY_TYPE_CONSOLE] = "console",
+ [OST_ENTITY_TYPE_DIAG] = "diag",
+};
+
+static const u32 ost_entity_value[] = {
+ [OST_ENTITY_TYPE_NONE] = 0,
+ [OST_ENTITY_TYPE_FTRACE] = OST_ENTITY_FTRACE,
+ [OST_ENTITY_TYPE_CONSOLE] = OST_ENTITY_CONSOLE,
+ [OST_ENTITY_TYPE_DIAG] = OST_ENTITY_DIAG,
+};
+
+struct ost_policy_node {
+ enum ost_entity_type entity_type;
+};
+
+struct ost_output {
+ struct ost_policy_node node;
+};
+
+/* Set default entity type as none */
+static void ost_policy_node_init(void *priv)
+{
+ struct ost_policy_node *pn = priv;
+
+ pn->entity_type = OST_ENTITY_TYPE_NONE;
+}
+
+static int ost_output_open(void *priv, struct stm_output *output)
+{
+ struct ost_policy_node *pn = priv;
+ struct ost_output *opriv;
+
+ opriv = kzalloc_obj(*opriv, GFP_ATOMIC);
+ if (!opriv)
+ return -ENOMEM;
+
+ memcpy(&opriv->node, pn, sizeof(opriv->node));
+ output->pdrv_private = opriv;
+ return 0;
+}
+
+static void ost_output_close(struct stm_output *output)
+{
+ kfree(output->pdrv_private);
+}
+
+static ssize_t ost_t_policy_entity_show(struct config_item *item,
+ char *page)
+{
+ struct ost_policy_node *pn = to_pdrv_policy_node(item);
+ ssize_t sz = 0;
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) {
+ if (i == pn->entity_type)
+ sz += sysfs_emit_at(page, sz, "[%s] ", str_ost_entity_type[i]);
+ else
+ sz += sysfs_emit_at(page, sz, "%s ", str_ost_entity_type[i]);
+ }
+
+ sz += sysfs_emit_at(page, sz, "\n");
+ return sz;
+}
+
+static int entity_index(const char *str)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) {
+ if (sysfs_streq(str, str_ost_entity_type[i]))
+ return i;
+ }
+
+ return 0;
+}
+
+static ssize_t
+ost_t_policy_entity_store(struct config_item *item, const char *page,
+ size_t count)
+{
+ struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex;
+ struct ost_policy_node *pn = to_pdrv_policy_node(item);
+ int i;
+
+ i = entity_index(page);
+ if (i) {
+ mutex_lock(mutexp);
+ pn->entity_type = i;
+ mutex_unlock(mutexp);
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+CONFIGFS_ATTR(ost_t_policy_, entity);
+
+static struct configfs_attribute *ost_t_policy_attrs[] = {
+ &ost_t_policy_attr_entity,
+ NULL,
+};
+
+static ssize_t
+notrace ost_write(struct stm_data *data, struct stm_output *output,
+ unsigned int chan, const char *buf, size_t count,
+ struct stm_source_data *source)
+{
+ struct ost_output *op = output->pdrv_private;
+ unsigned int c = output->channel + chan;
+ unsigned int m = output->master;
+ const unsigned char nil = 0;
+ u32 header = DATA_HEADER;
+ struct trc_hdr {
+ u16 version;
+ u16 magic;
+ u32 cpu;
+ u64 timestamp;
+ u64 tgid;
+ } hdr;
+ ssize_t sz;
+
+ /*
+ * Identify the source by entity type.
+ * If entity type is not set, return error value.
+ */
+ if (op->node.entity_type)
+ header |= (ost_entity_value[op->node.entity_type] << OST_FIELD_ENTITY);
+ else
+ return -EINVAL;
+
+ /*
+ * STP framing rules for OST frames:
+ * * the first packet of the OST frame is marked;
+ * * the last packet is a FLAG with timestamped tag.
+ */
+ /* Message layout: HEADER / DATA / TAIL */
+ /* HEADER */
+ sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_MARKED,
+ 4, (u8 *)&header);
+ if (sz <= 0)
+ return sz;
+
+ /* DATA */
+ hdr.version = STM_MAKE_VERSION(0, 3);
+ hdr.magic = STM_HEADER_MAGIC;
+ hdr.cpu = raw_smp_processor_id();
+ hdr.timestamp = sched_clock();
+ hdr.tgid = task_tgid_nr(current);
+ sz = stm_data_write(data, m, c, false, &hdr, sizeof(hdr));
+ if (sz <= 0)
+ return sz;
+
+ sz = stm_data_write(data, m, c, false, buf, count);
+
+ /* TAIL */
+ if (sz > 0)
+ data->packet(data, m, c, STP_PACKET_FLAG,
+ STP_PACKET_TIMESTAMPED, 0, &nil);
+
+ return sz;
+}
+
+static const struct stm_protocol_driver ost_pdrv = {
+ .owner = THIS_MODULE,
+ .name = "p_ost",
+ .priv_sz = sizeof(struct ost_policy_node),
+ .write = ost_write,
+ .policy_attr = ost_t_policy_attrs,
+ .output_open = ost_output_open,
+ .output_close = ost_output_close,
+ .policy_node_init = ost_policy_node_init,
+};
+
+static int ost_stm_init(void)
+{
+ return stm_register_protocol(&ost_pdrv);
+}
+module_init(ost_stm_init);
+
+static void ost_stm_exit(void)
+{
+ stm_unregister_protocol(&ost_pdrv);
+}
+module_exit(ost_stm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MIPI Open System Trace STM framing protocol driver");
---
base-commit: 80dd246accce631c328ea43294e53b2b2dd2aa32
change-id: 20260521-stm_p_ost-3489f42a9e8c
Best regards,
--
Yingchao Deng <yingchao.deng@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH v4 11/24] iommu: Add iommu_report_device_broken() to quarantine a broken device
From: Jason Gunthorpe @ 2026-05-21 13:12 UTC (permalink / raw)
To: Nicolin Chen
Cc: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <ag35umFgzIRGZAHA@Asurada-Nvidia>
On Wed, May 20, 2026 at 11:13:14AM -0700, Nicolin Chen wrote:
> > > > We cannot eliminate parallel ATS invalidation. Two threads could be
> > > > concurrently processing the invs list. So it has handle it, the driver
> > > > is going to have to tolerate a number of redundant error events.
> > >
> > > OK. That sounds like we still need a flag or locking so that at
> > > least pci_disable_ats() would not be called again. I will see
> > > what I can do.
> >
> > I think we can call pci_disable_ats() as many times as we want
>
> That triggers WARN_ON(!dev->ats_enabled) in pci_disable_ats :-(
IMHO I'd rather take that out than add a bunch of complication in the
iommu drivers..
> > Still, I'd feel better if it is was definititive and we didn't rely on
> > this. This further points that the driver has to merge multiple error
> > notifications if it gets some AERs and a new "ATC ERROR" all for the
> > same key event.
>
> I feel some race here... Part of the complexity of this v4 is to deal
> with concurrent device reset during the async report() between IOMMU
> core and driver. Now, we add AER that could compete on the device side
> as well...
It is always going to have concurrent events, so long as the resets
sequence in an orderly way it doesn't matter if they overlap.
Most likely the driver will have locking that prevents it from pushing
concurrent resets.
Jason
^ permalink raw reply
* [PATCH v6] stm: class: Add MIPI OST protocol support
From: Yingchao Deng @ 2026-05-21 13:08 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
Jonathan Corbet, Shuah Khan, Alexander Shishkin, Alexandre Torgue
Cc: linux-kernel, linux-trace-kernel, linux-doc, linux-arm-kernel,
Tingwei Zhang, Yuanfang Zhang, Jinlong Mao, Yingchao Deng
Add MIPI OST (Open System Trace) protocol support for stm to format the
traces. The OST Protocol abstracts the underlying layers from the sending
and receiving applications, thus removing dependencies on the connection
media and platform implementation.
OST over STP packet consists of Header/Payload/End. Header is designed to
include the information required by all OST packets. Information that is
not shared by all packets is left to the higher layer protocols. Thus, the
OST Protocol Header can be regarded as the first part of a complete OST
Packet Header, while a higher layer header can be regarded as an extension
designed for a specific purpose.
+--------+--------+--------+--------+
| start |version |entity |protocol|
+--------+--------+--------+--------+
| stm version | magic |
+-----------------------------------+
| cpu |
+-----------------------------------+
| timestamp |
| |
+-----------------------------------+
| tgid |
| |
+-----------------------------------+
| payload |
+-----------------------------------+
| ... | end |
+-----------------------------------+
In header, there will be STARTSIMPLE/VERSION/ENTITY/PROTOCOL.
STARTSIMPLE is used to signal the beginning of a simplified OST protocol.
The Version field is a one byte, unsigned number identifying the version
of the OST Protocol. The Entity ID field is a one byte unsigned number
that identifies the source.
Entity ID values (0~239) are defined and controlled by the TS owner, and
shall be unique for the whole TS. The configfs entity attribute allows the
user to configure which Entity ID is associated with each policy node.
The Protocol ID field is a one byte unsigned number identifying the higher
layer protocol of the OST Packet, i.e. identifying the format of the data
after the OST Protocol Header. OST Control Protocol ID value represents
the common control protocol, the remaining Protocol ID values may be used
by any higher layer protocols capable of being transported by the OST
Protocol.
Co-developed-by: Tingwei Zhang <tingwei.zhang@oss.qualcomm.com>
Signed-off-by: Tingwei Zhang <tingwei.zhang@oss.qualcomm.com>
Co-developed-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
Signed-off-by: Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
Co-developed-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
Changes in v6:
1. Rebase on top of linux-next-20260518.
2. Fix Kconfig: 'default CONFIG_STM' -> 'default STM'.
3. Fix documentation grammar issues.
4. Add p_ost entry to Documentation/trace/index.rst.
5. Add missing priv_sz field to stm_protocol_driver registration.
6. Use kzalloc_obj() instead of kzalloc() in ost_output_open().
7. Add mutex protection in entity configfs store handler.
8. Keep the configfs entity attribute: entity ID values (0~239) are
defined and controlled by the TS owner and are deployment-specific.
stm_source_type only carries a small number of in-kernel source
classifications and cannot represent the full range of OST entity
assignments needed in practice. The configfs attribute allows each
policy node to declare its entity.
OST_ENTITY_TYPE_NONE is an enum sentinel (not entity ID 0) that causes
ost_write() to return -EINVAL when no entity is configured, preventing
emission of packets with an unintended entity field.
OST_ENTITY_DIAG (0xEE) is a TS-owner-defined value used by Qualcomm's
diagnostic framework as the standard entity identifier for diagnostic
trace sources.
Link to v5: https://lore.kernel.org/all/20260129-p_ost-v5-1-2b14fff39428@oss.qualcomm.com/
Changes in v5:
1. Add Co-developed-by tag.
2. Use yearless copyright for new file.
- Link to v4: https://lore.kernel.org/all/20251024-p_ost-v4-1-3652a06fd055@oss.qualcomm.com/
Changes in v4:
1. Delete unused variable 'i'.
2. Fix build error: call to undeclared function 'task_tgid_nr'.
Link to v3 - https://lore.kernel.org/all/20251022071834.1658684-1-yingchao.deng@oss.qualcomm.com/
Changes in v3:
1. Add more details about OST.
2. Delete 'entity_available' node, and 'entity' node will show available
and currently selected (shown in square brackets) entity.
3. Removed the usage of config_item->ci_group->cg_subsys->su_mutex.
Link to v2 - https://lore.kernel.org/all/20230419141328.37472-1-quic_jinlmao@quicinc.com/
---
.../ABI/testing/configfs-stp-policy-p_ost | 9 +
Documentation/trace/index.rst | 1 +
Documentation/trace/p_ost.rst | 39 ++++
drivers/hwtracing/stm/Kconfig | 14 ++
drivers/hwtracing/stm/Makefile | 2 +
drivers/hwtracing/stm/p_ost.c | 241 +++++++++++++++++++++
6 files changed, 306 insertions(+)
diff --git a/Documentation/ABI/testing/configfs-stp-policy-p_ost b/Documentation/ABI/testing/configfs-stp-policy-p_ost
new file mode 100644
index 000000000000..8fb160b50c40
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-stp-policy-p_ost
@@ -0,0 +1,9 @@
+What: /config/stp-policy/<device>:p_ost.<policy>/<node>/entity
+Date: May 2026
+KernelVersion: 7.1
+Description:
+ Set the entity ID which identifies the trace source in the
+ OST packet header. Entity ID values (0~239) are defined by
+ the TS owner. Currently supported values are ftrace, console
+ and diag. RW.
+
diff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst
index 5d9bf4694d5d..9cd1e0b5af6d 100644
--- a/Documentation/trace/index.rst
+++ b/Documentation/trace/index.rst
@@ -72,6 +72,7 @@ interactions and system performance.
intel_th
stm
sys-t
+ p_ost
coresight/index
rv/index
hisi-ptt
diff --git a/Documentation/trace/p_ost.rst b/Documentation/trace/p_ost.rst
new file mode 100644
index 000000000000..2b92e2229653
--- /dev/null
+++ b/Documentation/trace/p_ost.rst
@@ -0,0 +1,39 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================
+MIPI OST over STP
+===================
+
+The OST (Open System Trace) driver is used with STM class devices to
+generate standardized trace stream. Trace sources can be identified
+by different entity IDs.
+
+CONFIG_STM_PROTO_OST is for p_ost driver enablement. Once this config
+is enabled, you can select the p_ost protocol by command below:
+
+# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy
+
+The policy name format is extended like this:
+
+ <device_name>:<protocol_name>.<policy_name>
+
+With a coresight-stm device, it will look like "stm0:p_ost.policy".
+
+With the MIPI OST protocol driver, the attributes for each protocol node are:
+
+# mkdir /sys/kernel/config/stp-policy/stm0:p_ost.policy/default
+# ls /sys/kernel/config/stp-policy/stm0:p_ost.policy/default
+channels entity masters
+
+The entity here is the set of entities that p_ost supports. Currently
+p_ost supports ftrace, console and diag entities.
+
+Set entity:
+# echo 'ftrace' > /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity
+
+Get available and currently selected (shown in square brackets) entity:
+# cat /sys/kernel/config/stp-policy/stm0:p_ost.policy/default/entity
+[ftrace] console diag
+
+See Documentation/ABI/testing/configfs-stp-policy-p_ost for more details.
+
diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
index cd7f0b0f3fbe..4c83da5d95a0 100644
--- a/drivers/hwtracing/stm/Kconfig
+++ b/drivers/hwtracing/stm/Kconfig
@@ -40,6 +40,20 @@ config STM_PROTO_SYS_T
If you don't know what this is, say N.
+config STM_PROTO_OST
+ tristate "MIPI OST STM framing protocol driver"
+ default STM
+ help
+ This is an implementation of MIPI OST protocol to be used
+ over the STP transport. In addition to the data payload, it
+ also carries additional metadata for entity, better
+ means of trace source identification, etc.
+
+ The receiving side must be able to decode this protocol in
+ addition to the MIPI STP, in order to extract the data.
+
+ If you don't know what this is, say N.
+
config STM_DUMMY
tristate "Dummy STM driver"
help
diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
index 1692fcd29277..d9c8615849b9 100644
--- a/drivers/hwtracing/stm/Makefile
+++ b/drivers/hwtracing/stm/Makefile
@@ -5,9 +5,11 @@ stm_core-y := core.o policy.o
obj-$(CONFIG_STM_PROTO_BASIC) += stm_p_basic.o
obj-$(CONFIG_STM_PROTO_SYS_T) += stm_p_sys-t.o
+obj-$(CONFIG_STM_PROTO_OST) += stm_p_ost.o
stm_p_basic-y := p_basic.o
stm_p_sys-t-y := p_sys-t.o
+stm_p_ost-y := p_ost.o
obj-$(CONFIG_STM_DUMMY) += dummy_stm.o
diff --git a/drivers/hwtracing/stm/p_ost.c b/drivers/hwtracing/stm/p_ost.c
new file mode 100644
index 000000000000..d2174872b761
--- /dev/null
+++ b/drivers/hwtracing/stm/p_ost.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * MIPI OST framing protocol for STM devices.
+ */
+
+#include <linux/pid.h>
+#include <linux/sched/clock.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+#include "stm.h"
+
+/*
+ * OST Base Protocol Header
+ *
+ * Position Bits Field Name
+ * 0 8 STARTSIMPLE
+ * 1 8 Version
+ * 2 8 Entity ID
+ * 3 8 Protocol ID
+ */
+#define OST_FIELD_STARTSIMPLE 0
+#define OST_FIELD_VERSION 8
+#define OST_FIELD_ENTITY 16
+#define OST_FIELD_PROTOCOL 24
+
+#define OST_TOKEN_STARTSIMPLE 0x10
+#define OST_VERSION_MIPI1 0x10
+
+/* entity id to identify the source */
+#define OST_ENTITY_FTRACE 0x01
+#define OST_ENTITY_CONSOLE 0x02
+#define OST_ENTITY_DIAG 0xEE
+
+#define OST_CONTROL_PROTOCOL 0x0
+
+#define DATA_HEADER ((OST_TOKEN_STARTSIMPLE << OST_FIELD_STARTSIMPLE) | \
+ (OST_VERSION_MIPI1 << OST_FIELD_VERSION) | \
+ (OST_CONTROL_PROTOCOL << OST_FIELD_PROTOCOL))
+
+#define STM_MAKE_VERSION(ma, mi) (((ma) << 8) | (mi))
+#define STM_HEADER_MAGIC (0x5953)
+
+enum ost_entity_type {
+ OST_ENTITY_TYPE_NONE,
+ OST_ENTITY_TYPE_FTRACE,
+ OST_ENTITY_TYPE_CONSOLE,
+ OST_ENTITY_TYPE_DIAG,
+};
+
+static const char * const str_ost_entity_type[] = {
+ [OST_ENTITY_TYPE_NONE] = "none",
+ [OST_ENTITY_TYPE_FTRACE] = "ftrace",
+ [OST_ENTITY_TYPE_CONSOLE] = "console",
+ [OST_ENTITY_TYPE_DIAG] = "diag",
+};
+
+static const u32 ost_entity_value[] = {
+ [OST_ENTITY_TYPE_NONE] = 0,
+ [OST_ENTITY_TYPE_FTRACE] = OST_ENTITY_FTRACE,
+ [OST_ENTITY_TYPE_CONSOLE] = OST_ENTITY_CONSOLE,
+ [OST_ENTITY_TYPE_DIAG] = OST_ENTITY_DIAG,
+};
+
+struct ost_policy_node {
+ enum ost_entity_type entity_type;
+};
+
+struct ost_output {
+ struct ost_policy_node node;
+};
+
+/* Set default entity type as none */
+static void ost_policy_node_init(void *priv)
+{
+ struct ost_policy_node *pn = priv;
+
+ pn->entity_type = OST_ENTITY_TYPE_NONE;
+}
+
+static int ost_output_open(void *priv, struct stm_output *output)
+{
+ struct ost_policy_node *pn = priv;
+ struct ost_output *opriv;
+
+ opriv = kzalloc_obj(*opriv, GFP_ATOMIC);
+ if (!opriv)
+ return -ENOMEM;
+
+ memcpy(&opriv->node, pn, sizeof(opriv->node));
+ output->pdrv_private = opriv;
+ return 0;
+}
+
+static void ost_output_close(struct stm_output *output)
+{
+ kfree(output->pdrv_private);
+}
+
+static ssize_t ost_t_policy_entity_show(struct config_item *item,
+ char *page)
+{
+ struct ost_policy_node *pn = to_pdrv_policy_node(item);
+ ssize_t sz = 0;
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) {
+ if (i == pn->entity_type)
+ sz += sysfs_emit_at(page, sz, "[%s] ", str_ost_entity_type[i]);
+ else
+ sz += sysfs_emit_at(page, sz, "%s ", str_ost_entity_type[i]);
+ }
+
+ sz += sysfs_emit_at(page, sz, "\n");
+ return sz;
+}
+
+static int entity_index(const char *str)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(str_ost_entity_type); i++) {
+ if (sysfs_streq(str, str_ost_entity_type[i]))
+ return i;
+ }
+
+ return 0;
+}
+
+static ssize_t
+ost_t_policy_entity_store(struct config_item *item, const char *page,
+ size_t count)
+{
+ struct mutex *mutexp = &item->ci_group->cg_subsys->su_mutex;
+ struct ost_policy_node *pn = to_pdrv_policy_node(item);
+ int i;
+
+ i = entity_index(page);
+ if (i) {
+ mutex_lock(mutexp);
+ pn->entity_type = i;
+ mutex_unlock(mutexp);
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+CONFIGFS_ATTR(ost_t_policy_, entity);
+
+static struct configfs_attribute *ost_t_policy_attrs[] = {
+ &ost_t_policy_attr_entity,
+ NULL,
+};
+
+static ssize_t
+notrace ost_write(struct stm_data *data, struct stm_output *output,
+ unsigned int chan, const char *buf, size_t count,
+ struct stm_source_data *source)
+{
+ struct ost_output *op = output->pdrv_private;
+ unsigned int c = output->channel + chan;
+ unsigned int m = output->master;
+ const unsigned char nil = 0;
+ u32 header = DATA_HEADER;
+ struct trc_hdr {
+ u16 version;
+ u16 magic;
+ u32 cpu;
+ u64 timestamp;
+ u64 tgid;
+ } hdr;
+ ssize_t sz;
+
+ /*
+ * Identify the source by entity type.
+ * If entity type is not set, return error value.
+ */
+ if (op->node.entity_type)
+ header |= (ost_entity_value[op->node.entity_type] << OST_FIELD_ENTITY);
+ else
+ return -EINVAL;
+
+ /*
+ * STP framing rules for OST frames:
+ * * the first packet of the OST frame is marked;
+ * * the last packet is a FLAG with timestamped tag.
+ */
+ /* Message layout: HEADER / DATA / TAIL */
+ /* HEADER */
+ sz = data->packet(data, m, c, STP_PACKET_DATA, STP_PACKET_MARKED,
+ 4, (u8 *)&header);
+ if (sz <= 0)
+ return sz;
+
+ /* DATA */
+ hdr.version = STM_MAKE_VERSION(0, 3);
+ hdr.magic = STM_HEADER_MAGIC;
+ hdr.cpu = raw_smp_processor_id();
+ hdr.timestamp = sched_clock();
+ hdr.tgid = task_tgid_nr(current);
+ sz = stm_data_write(data, m, c, false, &hdr, sizeof(hdr));
+ if (sz <= 0)
+ return sz;
+
+ sz = stm_data_write(data, m, c, false, buf, count);
+
+ /* TAIL */
+ if (sz > 0)
+ data->packet(data, m, c, STP_PACKET_FLAG,
+ STP_PACKET_TIMESTAMPED, 0, &nil);
+
+ return sz;
+}
+
+static const struct stm_protocol_driver ost_pdrv = {
+ .owner = THIS_MODULE,
+ .name = "p_ost",
+ .priv_sz = sizeof(struct ost_policy_node),
+ .write = ost_write,
+ .policy_attr = ost_t_policy_attrs,
+ .output_open = ost_output_open,
+ .output_close = ost_output_close,
+ .policy_node_init = ost_policy_node_init,
+};
+
+static int ost_stm_init(void)
+{
+ return stm_register_protocol(&ost_pdrv);
+}
+module_init(ost_stm_init);
+
+static void ost_stm_exit(void)
+{
+ stm_unregister_protocol(&ost_pdrv);
+}
+module_exit(ost_stm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MIPI Open System Trace STM framing protocol driver");
---
base-commit: 80dd246accce631c328ea43294e53b2b2dd2aa32
change-id: 20260521-stm_p_ost-3489f42a9e8c
Best regards,
--
Yingchao Deng <yingchao.deng@oss.qualcomm.com>
^ permalink raw reply related
* Re: [PATCH v2 3/3] KVM: arm64: Add fail-safe for refcounted pages in __pkvm_hyp_donate_host
From: Fuad Tabba @ 2026-05-21 13:07 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team,
qperret
In-Reply-To: <20260521102149.804874-4-vdonnefort@google.com>
On Thu, 21 May 2026 at 11:22, Vincent Donnefort <vdonnefort@google.com> wrote:
>
> A previous bug in __pkvm_init_vm error path showed that the hypervisor
> could leak refcounted pages, (i.e. losing access to a page while its
> refcount is still elevated). This poses a threat to the pKVM state
> machine.
>
> Address this by introducing a fail-safe in n __pkvm_hyp_donate_host.
Stray n.
> Transitions are not a hot path so added security is worth the extra
> check.
>
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Cheers,
/fuad
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 42b0b648f32f..bb97d05b9b25 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -855,6 +855,16 @@ static int __hyp_check_page_state_range(phys_addr_t phys, u64 size, enum pkvm_pa
> return 0;
> }
>
> +static int __hyp_check_page_count_range(phys_addr_t phys, u64 size)
> +{
> + for_each_hyp_page(page, phys, size) {
> + if (page->refcount)
> + return -EBUSY;
> + }
> +
> + return 0;
> +}
> +
> static bool guest_pte_is_poisoned(kvm_pte_t pte)
> {
> if (kvm_pte_valid(pte))
> @@ -1053,7 +1063,6 @@ int __pkvm_guest_unshare_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn)
> int __pkvm_host_unshare_hyp(u64 pfn)
> {
> u64 phys = hyp_pfn_to_phys(pfn);
> - u64 virt = (u64)__hyp_va(phys);
> u64 size = PAGE_SIZE;
> int ret;
>
> @@ -1066,10 +1075,9 @@ int __pkvm_host_unshare_hyp(u64 pfn)
> ret = __hyp_check_page_state_range(phys, size, PKVM_PAGE_SHARED_BORROWED);
> if (ret)
> goto unlock;
> - if (hyp_page_count((void *)virt)) {
> - ret = -EBUSY;
> + ret = __hyp_check_page_count_range(phys, size);
> + if (ret)
> goto unlock;
> - }
>
> __hyp_set_page_state_range(phys, size, PKVM_NOPAGE);
> WARN_ON(__host_set_page_state_range(phys, size, PKVM_PAGE_OWNED));
> @@ -1132,6 +1140,10 @@ int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages)
> if (ret)
> goto unlock;
>
> + ret = __hyp_check_page_count_range(phys, size);
> + if (ret)
> + goto unlock;
> +
> __hyp_set_page_state_range(phys, size, PKVM_NOPAGE);
> WARN_ON(kvm_pgtable_hyp_unmap(&pkvm_pgtable, virt, size) != size);
> WARN_ON(host_stage2_set_owner_locked(phys, size, PKVM_ID_HOST));
> --
> 2.54.0.746.g67dd491aae-goog
>
^ permalink raw reply
* Re: [PATCH v2 2/3] KVM: arm64: Fix __pkvm_init_vm error path
From: Fuad Tabba @ 2026-05-21 13:07 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team,
qperret, Sashiko
In-Reply-To: <20260521102149.804874-3-vdonnefort@google.com>
On Thu, 21 May 2026 at 11:22, Vincent Donnefort <vdonnefort@google.com> wrote:
>
> In the unlikely case where insert_vm_table_entry fails, __pkvm_init_vm
> release the memory donated by the host for the PGD, but as the stage-2
> is still set-up the hypervisor keeps a refcount on those pages,
> effectively leaking the references.
>
> Fix the rollback with the newly added kvm_guest_destroy_stage2().
>
> Fixes: 256b4668cd89 ("KVM: arm64: Introduce separate hypercalls for pKVM VM reservation and initialization")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Cheers,
/fuad
>
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> index 3cbfae0e3dda..4f2b871199cb 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
> @@ -56,6 +56,7 @@ int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot p
> int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id);
> int kvm_host_prepare_stage2(void *pgt_pool_base);
> int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd);
> +void kvm_guest_destroy_stage2(struct pkvm_hyp_vm *vm);
> void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt);
>
> int hyp_pin_shared_mem(void *from, void *to);
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 89eb20d4fee4..42b0b648f32f 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -306,16 +306,21 @@ int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
> return 0;
> }
>
> +void kvm_guest_destroy_stage2(struct pkvm_hyp_vm *vm)
> +{
> + guest_lock_component(vm);
> + kvm_pgtable_stage2_destroy(&vm->pgt);
> + vm->kvm.arch.mmu.pgd_phys = 0ULL;
> + guest_unlock_component(vm);
> +}
> +
> void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
> {
> struct hyp_page *page;
> void *addr;
>
> /* Dump all pgtable pages in the hyp_pool */
> - guest_lock_component(vm);
> - kvm_pgtable_stage2_destroy(&vm->pgt);
> - vm->kvm.arch.mmu.pgd_phys = 0ULL;
> - guest_unlock_component(vm);
> + kvm_guest_destroy_stage2(vm);
>
> /* Drain the hyp_pool into the memcache */
> addr = hyp_alloc_pages(&vm->pool, 0);
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> index eb1c10120f9f..3b2c4fbc34d8 100644
> --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
> +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
> @@ -853,10 +853,12 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
> /* Must be called last since this publishes the VM. */
> ret = insert_vm_table_entry(handle, hyp_vm);
> if (ret)
> - goto err_remove_mappings;
> + goto err_destroy_stage2;
>
> return 0;
>
> +err_destroy_stage2:
> + kvm_guest_destroy_stage2(hyp_vm);
> err_remove_mappings:
> unmap_donated_memory(hyp_vm, vm_size);
> unmap_donated_memory(pgd, pgd_size);
> --
> 2.54.0.746.g67dd491aae-goog
>
^ permalink raw reply
* Re: [PATCH v2 1/3] KVM: arm64: Reset page order in pKVM hyp_pool_init
From: Fuad Tabba @ 2026-05-21 13:07 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team,
qperret, Sashiko
In-Reply-To: <20260521102149.804874-2-vdonnefort@google.com>
On Thu, 21 May 2026 at 11:22, Vincent Donnefort <vdonnefort@google.com> wrote:
>
> When a VM fails to initialise after its stage-2 hyp_pool has been
> initialised, that stage-2 must be torn down entirely. This requires
> resetting both the refcount and the order of its pages back to 0.
>
> Currently, reclaim_pgtable_pages() implicitly resets the page order by
> allocating the entire pool with order-0 granularity. However, in the VM
> initialisation error path, the addresses of the donated memory (the PGD)
> are already known, making it unnecessary to iterate over all pages in
> the pool.
>
> Since the vmemmap page order is a hyp_pool-specific field, leaving a
> non-zero order on hyp_pool destruction is harmless until another pool
> attempts to admit the page. Instead of resetting this field during
> destruction, reset it during pool initialization in hyp_pool_init().
> Note that pages added to the pool outside of the initial pool range
> (e.g., via guest_s2_zalloc_page()) must still have their order managed
> manually.
>
> While at it, add a WARN_ON() in the hyp_pool attach path to catch
> unexpected page orders that exceed the pool's max_order.
>
> Fixes: 256b4668cd89 ("KVM: arm64: Introduce separate hypercalls for pKVM VM reservation and initialization")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> index 25f04629014e..89eb20d4fee4 100644
> --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
> @@ -322,7 +322,6 @@ void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
> while (addr) {
> page = hyp_virt_to_page(addr);
> page->refcount = 0;
> - page->order = 0;
> push_hyp_memcache(mc, addr, hyp_virt_to_phys);
> WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(addr), 1));
> addr = hyp_alloc_pages(&vm->pool, 0);
> diff --git a/arch/arm64/kvm/hyp/nvhe/page_alloc.c b/arch/arm64/kvm/hyp/nvhe/page_alloc.c
> index a1eb27a1a747..c3b3dc5a8ea7 100644
> --- a/arch/arm64/kvm/hyp/nvhe/page_alloc.c
> +++ b/arch/arm64/kvm/hyp/nvhe/page_alloc.c
> @@ -97,6 +97,8 @@ static void __hyp_attach_page(struct hyp_pool *pool,
> u8 order = p->order;
> struct hyp_page *buddy;
>
> + WARN_ON(p->order > pool->max_order);
> +
Could you add a brief comment? It took me a minute to figure out what this
catches. IIUC it's not attach's own input, it's a stale p->order from way back
when an external page was popped from a memcache (today only via
guest_s2_zalloc_page()). Right?
With that.
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Cheers,
/fuad
> memset(hyp_page_to_virt(p), 0, PAGE_SIZE << p->order);
>
> /* Skip coalescing for 'external' pages being freed into the pool. */
> @@ -237,8 +239,10 @@ int hyp_pool_init(struct hyp_pool *pool, u64 pfn, unsigned int nr_pages,
>
> /* Init the vmemmap portion */
> p = hyp_phys_to_page(phys);
> - for (i = 0; i < nr_pages; i++)
> + for (i = 0; i < nr_pages; i++) {
> hyp_set_page_refcounted(&p[i]);
> + p[i].order = 0;
> + }
>
> /* Attach the unused pages to the buddy tree */
> for (i = reserved_pages; i < nr_pages; i++)
> --
> 2.54.0.746.g67dd491aae-goog
>
^ permalink raw reply
* Re: [PATCH v2 0/3] Fix __pkvm_init_vm error path
From: Fuad Tabba @ 2026-05-21 13:07 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team,
qperret
In-Reply-To: <20260521102149.804874-1-vdonnefort@google.com>
On Thu, 21 May 2026 at 11:22, Vincent Donnefort <vdonnefort@google.com> wrote:
>
> Sashiko reported a potential refcount leak in the unlikely case where
> insert_vm_table_entry fails.
>
> While at it, I have added a fail-safe to __pkvm_hyp_donate_host to ensure this
> function doesn't allow leaking refcounted pages.
>
> Changes since v2:
>
> * Proactively init hyp_page order field in hyp_pool_init
>
> v1 (https://lore.kernel.org/all/20260521081250.655226-1-vdonnefort@google.com/)
>
> *** BLURB HERE ***
nit: missing BLURB :)
/fuad
/fuad
>
> Vincent Donnefort (3):
> KVM: arm64: Reset page order in pKVM hyp_pool_init
> KVM: arm64: Fix __pkvm_init_vm error path
> KVM: arm64: Add fail-safe for refcounted pages in
> __pkvm_hyp_donate_host
>
> arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 +
> arch/arm64/kvm/hyp/nvhe/mem_protect.c | 34 ++++++++++++++-----
> arch/arm64/kvm/hyp/nvhe/page_alloc.c | 6 +++-
> arch/arm64/kvm/hyp/nvhe/pkvm.c | 4 ++-
> 4 files changed, 34 insertions(+), 11 deletions(-)
>
>
> base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
> --
> 2.54.0.746.g67dd491aae-goog
>
^ permalink raw reply
* Re: [PATCH v4 1/3] PCI: Allow ATS to be always on for CXL.cache capable devices
From: Jason Gunthorpe @ 2026-05-21 13:05 UTC (permalink / raw)
To: Yi Liu
Cc: Nicolin Chen, will, robin.murphy, bhelgaas, joro, praan, baolu.lu,
kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
linux-kernel, linux-pci, dan.j.williams, jonathan.cameron, vsethi,
linux-cxl, nirmoyd
In-Reply-To: <80e7e1be-c384-470f-9949-8c0dbad165ac@intel.com>
On Thu, May 21, 2026 at 03:31:46PM +0800, Yi Liu wrote:
> Does this hardware behavior satisfy the security expectation you have in
> mind? Or do you still require that both the DTE bit and the PCI ATS
> capability be explicitly disabled when a blocking domain is in effect?
If the HW rejects translated TLPs then you should be clearing the ATS
enable bit in the device config space prior to rejecting them
But it does seem secure enough as-is.
Jason
^ permalink raw reply
* [PATCH] irqchip/gic-v4: Harden against bogus command line
From: Mostafa Saleh @ 2026-05-21 13:05 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel; +Cc: maz, tglx, Mostafa Saleh
When accidentally setting “kvm-arm.vgic_v4_enable=1” on the wrong
setup that has no MSI controller device tree node (it exists but
not used) and GICv4, it caused a panic as “gic_domain” is NULL and
the kernel attempted to access its ops.
Originally, I hit this on an older kernel, but was able to reproduce
it on upstream with Qemu by hacking this unreasonable setup.
[ 33.145536] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000028
[ 33.145658] Mem abort info:
[ 33.145751] ESR = 0x0000000096000006
...
[ 33.154057] CPU: 1 UID: 0 PID: 295 Comm: lkvm-static Not tainted 7.1.0-rc4-ge3f15ad3970e #5 PREEMPT
[ 33.156922] Hardware name: linux,dummy-virt (DT)
[ 33.158780] pstate: 81402005 (Nzcv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[ 33.160340] pc : __irq_domain_instantiate+0x1d4/0x578
[ 33.162602] lr : __irq_domain_instantiate+0x1cc/0x578
Add a hardening check to avoid the NULL access, and fail the VM
creation in that case.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
drivers/irqchip/irq-gic-v4.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index 8455b4a5fbb0..7e39f7eae85f 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -159,6 +159,9 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
{
int vpe_base_irq, i;
+ if (!gic_domain)
+ return -EINVAL;
+
vm->fwnode = irq_domain_alloc_named_id_fwnode("GICv4-vpe",
task_pid_nr(current));
if (!vm->fwnode)
--
2.54.0.669.g59709faab0-goog
^ permalink raw reply related
* Re: [PATCH v7 09/28] media: rockchip: rga: remove redundant rga_frame variables
From: Michael Tretter @ 2026-05-21 13:03 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-9-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:14 +0200, Sven Püschel wrote:
> Remove the redundant rga_frame variables width, height and color space.
> The value of these variables is already contained in the pix member
> of rga_frame. The code also keeps these values in sync. Therefore drop
> them in favor of the existing pix member.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-buf.c | 6 ++---
> drivers/media/platform/rockchip/rga/rga-hw.c | 6 ++---
> drivers/media/platform/rockchip/rga/rga.c | 32 ++++++++++-----------------
> drivers/media/platform/rockchip/rga/rga.h | 5 -----
> 4 files changed, 18 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
> index 65fc0d5b4aa10..ffc6162b2e681 100644
> --- a/drivers/media/platform/rockchip/rga/rga-buf.c
> +++ b/drivers/media/platform/rockchip/rga/rga-buf.c
> @@ -103,10 +103,10 @@ static int get_plane_offset(struct rga_frame *f,
> if (plane == 0)
> return 0;
> if (plane == 1)
> - return stride * f->height;
> + return stride * f->pix.height;
> if (plane == 2)
> - return stride * f->height +
> - (stride * f->height / info->hdiv / info->vdiv);
> + return stride * f->pix.height +
> + (stride * f->pix.height / info->hdiv / info->vdiv);
>
> return -EINVAL;
> }
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index d1618bb247501..ec6c17504ca15 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -53,7 +53,7 @@ rga_get_addr_offset(struct rga_frame *frm, struct rga_addr_offset *offset,
> x_div = frm->fmt->x_div;
> y_div = frm->fmt->y_div;
> uv_stride = frm->stride / x_div;
> - pixel_width = frm->stride / frm->width;
> + pixel_width = frm->stride / frm->pix.width;
>
> lt->y_off = offset->y_off + y * frm->stride + x * pixel_width;
> lt->u_off = offset->u_off + (y / y_div) * uv_stride + x / x_div;
> @@ -191,7 +191,7 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
>
> if (RGA_COLOR_FMT_IS_YUV(ctx->in.fmt->hw_format) &&
> RGA_COLOR_FMT_IS_RGB(ctx->out.fmt->hw_format)) {
> - switch (ctx->in.colorspace) {
> + switch (ctx->in.pix.colorspace) {
> case V4L2_COLORSPACE_REC709:
> src_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
> break;
> @@ -203,7 +203,7 @@ static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
>
> if (RGA_COLOR_FMT_IS_RGB(ctx->in.fmt->hw_format) &&
> RGA_COLOR_FMT_IS_YUV(ctx->out.fmt->hw_format)) {
> - switch (ctx->out.colorspace) {
> + switch (ctx->out.pix.colorspace) {
> case V4L2_COLORSPACE_REC709:
> dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
> break;
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index c07207edffdb6..ca8d8a53dc251 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -329,9 +329,6 @@ static struct rga_fmt *rga_fmt_find(u32 pixelformat)
> }
>
> static struct rga_frame def_frame = {
> - .width = DEFAULT_WIDTH,
> - .height = DEFAULT_HEIGHT,
> - .colorspace = V4L2_COLORSPACE_DEFAULT,
> .crop.left = 0,
> .crop.top = 0,
> .crop.width = DEFAULT_WIDTH,
> @@ -363,9 +360,9 @@ static int rga_open(struct file *file)
> ctx->out = def_frame;
>
> v4l2_fill_pixfmt_mp(&ctx->in.pix,
> - ctx->in.fmt->fourcc, ctx->out.width, ctx->out.height);
> + ctx->in.fmt->fourcc, DEFAULT_WIDTH, DEFAULT_HEIGHT);
> v4l2_fill_pixfmt_mp(&ctx->out.pix,
> - ctx->out.fmt->fourcc, ctx->out.width, ctx->out.height);
> + ctx->out.fmt->fourcc, DEFAULT_WIDTH, DEFAULT_HEIGHT);
>
> if (mutex_lock_interruptible(&rga->mutex)) {
> kfree(ctx);
> @@ -453,10 +450,8 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
> if (IS_ERR(frm))
> return PTR_ERR(frm);
>
> - v4l2_fill_pixfmt_mp(pix_fmt, frm->fmt->fourcc, frm->width, frm->height);
> -
> + *pix_fmt = frm->pix;
> pix_fmt->field = V4L2_FIELD_NONE;
> - pix_fmt->colorspace = frm->colorspace;
>
> return 0;
> }
> @@ -505,27 +500,24 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> frm = rga_get_frame(ctx, f->type);
> if (IS_ERR(frm))
> return PTR_ERR(frm);
> - frm->width = pix_fmt->width;
> - frm->height = pix_fmt->height;
> frm->size = 0;
> for (i = 0; i < pix_fmt->num_planes; i++)
> frm->size += pix_fmt->plane_fmt[i].sizeimage;
> frm->fmt = rga_fmt_find(pix_fmt->pixelformat);
> frm->stride = pix_fmt->plane_fmt[0].bytesperline;
> - frm->colorspace = pix_fmt->colorspace;
>
> /* Reset crop settings */
> frm->crop.left = 0;
> frm->crop.top = 0;
> - frm->crop.width = frm->width;
> - frm->crop.height = frm->height;
> + frm->crop.width = pix_fmt->width;
> + frm->crop.height = pix_fmt->height;
>
> frm->pix = *pix_fmt;
>
> v4l2_dbg(debug, 1, &rga->v4l2_dev,
> "[%s] fmt - %p4cc %dx%d (stride %d, sizeimage %d)\n",
> V4L2_TYPE_IS_OUTPUT(f->type) ? "OUTPUT" : "CAPTURE",
> - &frm->fmt->fourcc, frm->width, frm->height,
> + &frm->fmt->fourcc, pix_fmt->width, pix_fmt->height,
> frm->stride, frm->size);
>
> for (i = 0; i < pix_fmt->num_planes; i++) {
> @@ -579,8 +571,8 @@ static int vidioc_g_selection(struct file *file, void *priv,
> } else {
> s->r.left = 0;
> s->r.top = 0;
> - s->r.width = f->width;
> - s->r.height = f->height;
> + s->r.width = f->pix.width;
> + s->r.height = f->pix.height;
> }
>
> return 0;
> @@ -629,8 +621,8 @@ static int vidioc_s_selection(struct file *file, void *priv,
> return -EINVAL;
> }
>
> - if (s->r.left + s->r.width > f->width ||
> - s->r.top + s->r.height > f->height ||
> + if (s->r.left + s->r.width > f->pix.width ||
> + s->r.top + s->r.height > f->pix.height ||
> s->r.width < MIN_WIDTH || s->r.height < MIN_HEIGHT) {
> v4l2_dbg(debug, 1, &rga->v4l2_dev, "unsupported crop value.\n");
> return -EINVAL;
> @@ -821,8 +813,8 @@ static int rga_probe(struct platform_device *pdev)
> goto rel_m2m;
> }
>
> - def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
> - def_frame.size = def_frame.stride * def_frame.height;
> + def_frame.stride = (DEFAULT_WIDTH * def_frame.fmt->depth) >> 3;
> + def_frame.size = def_frame.stride * DEFAULT_HEIGHT;
>
> ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
> if (ret) {
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 477cf5b62bbb2..c4a3905a48f0d 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -24,11 +24,6 @@ struct rga_fmt {
> };
>
> struct rga_frame {
> - /* Original dimensions */
> - u32 width;
> - u32 height;
> - u32 colorspace;
> -
> /* Crop */
> struct v4l2_rect crop;
>
>
> --
> 2.54.0
>
>
--
Pengutronix e.K. | Michael Tretter |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH v14 06/44] arm64: RMI: Check for RMI support at init
From: Marc Zyngier @ 2026-05-21 13:02 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-7-steven.price@arm.com>
On Wed, 13 May 2026 14:17:14 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> Query the RMI version number and check if it is a compatible version.
> The first two feature registers are read and exposed for future code to
> use.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> v14:
> * This moves the basic RMI setup into the 'kernel' directory. This is
> because RMI will be used for some features outside of KVM so should
> be available even if KVM isn't compiled in.
> ---
> arch/arm64/include/asm/rmi_cmds.h | 3 ++
> arch/arm64/kernel/Makefile | 2 +-
> arch/arm64/kernel/cpufeature.c | 1 +
> arch/arm64/kernel/rmi.c | 65 +++++++++++++++++++++++++++++++
> 4 files changed, 70 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm64/kernel/rmi.c
>
> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
> index 04f7066894e9..9179934925c5 100644
> --- a/arch/arm64/include/asm/rmi_cmds.h
> +++ b/arch/arm64/include/asm/rmi_cmds.h
> @@ -10,6 +10,9 @@
>
> #include <asm/rmi_smc.h>
>
> +extern unsigned long rmm_feat_reg0;
> +extern unsigned long rmm_feat_reg1;
> +
> struct rtt_entry {
> unsigned long walk_level;
> unsigned long desc;
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 74b76bb70452..d68f351aae75 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -34,7 +34,7 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
> cpufeature.o alternative.o cacheinfo.o \
> smp.o smp_spin_table.o topology.o smccc-call.o \
> syscall.o proton-pack.o idle.o patching.o pi/ \
> - rsi.o jump_label.o
> + rsi.o jump_label.o rmi.o
>
> obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
> sys_compat.o
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 6d53bb15cf7b..8bdd95a8c2de 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -292,6 +292,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar3[] = {
> static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
> ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_CSV3_SHIFT, 4, 0),
> ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_CSV2_SHIFT, 4, 0),
> + ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_RME_SHIFT, 4, 0),
> ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_DIT_SHIFT, 4, 0),
> ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_AMU_SHIFT, 4, 0),
> ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_MPAM_SHIFT, 4, 0),
> diff --git a/arch/arm64/kernel/rmi.c b/arch/arm64/kernel/rmi.c
> new file mode 100644
> index 000000000000..99c1ccc35c11
> --- /dev/null
> +++ b/arch/arm64/kernel/rmi.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2023-2025 ARM Ltd.
> + */
> +
> +#include <linux/memblock.h>
> +
> +#include <asm/rmi_cmds.h>
> +
> +unsigned long rmm_feat_reg0;
> +unsigned long rmm_feat_reg1;
What is the requirement for making those globally accessible? Can't
they be made static and use an accessor that returns them? Can the
variables be made __ro_after_init?
> +
> +static int rmi_check_version(void)
> +{
> + struct arm_smccc_res res;
> + unsigned short version_major, version_minor;
> + unsigned long host_version = RMI_ABI_VERSION(RMI_ABI_MAJOR_VERSION,
> + RMI_ABI_MINOR_VERSION);
> + unsigned long aa64pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
> +
> + /* If RME isn't supported, then RMI can't be */
> + if (cpuid_feature_extract_unsigned_field(aa64pfr0, ID_AA64PFR0_EL1_RME_SHIFT) == 0)
> + return -ENXIO;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_VERSION, host_version, &res);
> +
> + if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
> + return -ENXIO;
> +
> + version_major = RMI_ABI_VERSION_GET_MAJOR(res.a1);
> + version_minor = RMI_ABI_VERSION_GET_MINOR(res.a1);
> +
> + if (res.a0 != RMI_SUCCESS) {
> + unsigned short high_version_major, high_version_minor;
> +
> + high_version_major = RMI_ABI_VERSION_GET_MAJOR(res.a2);
> + high_version_minor = RMI_ABI_VERSION_GET_MINOR(res.a2);
> +
> + pr_err("Unsupported RMI ABI (v%d.%d - v%d.%d) we want v%d.%d\n",
> + version_major, version_minor,
> + high_version_major, high_version_minor,
> + RMI_ABI_MAJOR_VERSION,
> + RMI_ABI_MINOR_VERSION);
> + return -ENXIO;
> + }
> +
> + pr_info("RMI ABI version %d.%d\n", version_major, version_minor);
> +
> + return 0;
> +}
> +
> +static int __init arm64_init_rmi(void)
> +{
> + /* Continue without realm support if we can't agree on a version */
> + if (rmi_check_version())
> + return 0;
> +
> + if (WARN_ON(rmi_features(0, &rmm_feat_reg0)))
> + return 0;
> + if (WARN_ON(rmi_features(1, &rmm_feat_reg1)))
> + return 0;
> +
> + return 0;
> +}
> +subsys_initcall(arm64_init_rmi);
Is there any reliance on this being executed before or after KVM's own
initialisation? If so, this should be captured.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v4 3/5] firmware: arm_ffa: Fix Endpoint Memory Access Descriptor offset calculation
From: Sudeep Holla @ 2026-05-21 12:55 UTC (permalink / raw)
To: Mostafa Saleh
Cc: op-tee, linux-kernel, Sudeep Holla, kvmarm, linux-arm-kernel, maz,
oupton, joey.gouly, suzuki.poulose, catalin.marinas,
jens.wiklander, sumit.garg, sebastianene, vdonnefort
In-Reply-To: <20260520204948.2440882-4-smostafa@google.com>
On Wed, May 20, 2026 at 08:49:46PM +0000, Mostafa Saleh wrote:
> From: Sebastian Ene <sebastianene@google.com>
>
> Use the descriptor's `ep_mem_offset` to calculate the start of the endpoint
> memory access array and to comply with the FF-A spec instead of defaulting
> to `sizeof(struct ffa_mem_region)`.
> This requires moving `ffa_mem_region_additional_setup()` earlier in the setup
> flow.
> Also, add sanity checks to ensure the calculated descriptor offsets do not
> exceed `max_fragsize`.
>
Core change remains same as v3 except improved error checking, so my
review still applies.
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v7 08/28] media: rockchip: rga: use stride for offset calculation
From: Michael Tretter @ 2026-05-21 12:52 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-8-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:13 +0200, Sven Püschel wrote:
> Use the stride instead of the width for the offset calculation. This
> ensures that the bytesperline value doesn't need to match the width
> value of the image.
>
> Furthermore this patch removes the dependency on the uv_factor property
> and instead reuses the v4l2_format_info to determine the correct
> division factor.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-buf.c | 14 +++++++++-----
> drivers/media/platform/rockchip/rga/rga.c | 16 ----------------
> drivers/media/platform/rockchip/rga/rga.h | 1 -
> 3 files changed, 9 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
> index bb575873f2b24..65fc0d5b4aa10 100644
> --- a/drivers/media/platform/rockchip/rga/rga-buf.c
> +++ b/drivers/media/platform/rockchip/rga/rga-buf.c
> @@ -14,7 +14,6 @@
> #include <media/videobuf2-dma-sg.h>
> #include <media/videobuf2-v4l2.h>
>
> -#include "rga-hw.h"
> #include "rga.h"
>
> static ssize_t fill_descriptors(struct rga_dma_desc *desc, size_t max_desc,
> @@ -95,14 +94,19 @@ static int rga_buf_init(struct vb2_buffer *vb)
> return 0;
> }
>
> -static int get_plane_offset(struct rga_frame *f, int plane)
> +static int get_plane_offset(struct rga_frame *f,
> + const struct v4l2_format_info *info,
> + int plane)
> {
> + u32 stride = f->pix.plane_fmt[0].bytesperline;
> +
> if (plane == 0)
> return 0;
> if (plane == 1)
> - return f->width * f->height;
> + return stride * f->height;
> if (plane == 2)
> - return f->width * f->height + (f->width * f->height / f->fmt->uv_factor);
> + return stride * f->height +
> + (stride * f->height / info->hdiv / info->vdiv);
>
> return -EINVAL;
> }
> @@ -148,7 +152,7 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
> /* Fill the remaining planes */
> info = v4l2_format_info(f->fmt->fourcc);
> for (i = info->mem_planes; i < info->comp_planes; i++)
> - offsets[i] = get_plane_offset(f, i);
> + offsets[i] = get_plane_offset(f, info, i);
>
> rbuf->offset.y_off = offsets[0];
> rbuf->offset.u_off = offsets[1];
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index 4e710a050cb7c..c07207edffdb6 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -190,7 +190,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_ALPHA_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR8888,
> .depth = 32,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -199,7 +198,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR8888,
> .depth = 32,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -208,7 +206,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_XBGR8888,
> .depth = 32,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -217,7 +214,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_RGB888,
> .depth = 24,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -226,7 +222,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_RGB888,
> .depth = 24,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -235,7 +230,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR4444,
> .depth = 16,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -244,7 +238,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR1555,
> .depth = 16,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -253,7 +246,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_BGR565,
> .depth = 16,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -262,7 +254,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 1,
> },
> @@ -271,7 +262,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422SP,
> .depth = 16,
> - .uv_factor = 2,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -280,7 +270,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 1,
> },
> @@ -289,7 +278,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 1,
> },
> @@ -298,7 +286,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422SP,
> .depth = 16,
> - .uv_factor = 2,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -307,7 +294,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420P,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 2,
> },
> @@ -316,7 +302,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422P,
> .depth = 16,
> - .uv_factor = 2,
> .y_div = 1,
> .x_div = 2,
> },
> @@ -325,7 +310,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420P,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 2,
> },
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 2db10acecb405..477cf5b62bbb2 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -17,7 +17,6 @@
> struct rga_fmt {
> u32 fourcc;
> int depth;
> - u8 uv_factor;
> u8 y_div;
> u8 x_div;
> u8 color_swap;
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH v4 2/5] firmware: arm_ffa: Fix out-of-bound writes in ffa_setup_and_transmit()
From: Sudeep Holla @ 2026-05-21 12:51 UTC (permalink / raw)
To: Mostafa Saleh
Cc: op-tee, linux-kernel, Sudeep Holla, kvmarm, linux-arm-kernel, maz,
oupton, joey.gouly, suzuki.poulose, catalin.marinas,
jens.wiklander, sumit.garg, sebastianene, vdonnefort
In-Reply-To: <20260520204948.2440882-3-smostafa@google.com>
On Wed, May 20, 2026 at 08:49:45PM +0000, Mostafa Saleh wrote:
> Sashiko (locally) reports multiple out-of-bound issues in
> ffa_setup_and_transmit:
> 1) Writing ep_mem_access->reserved can write out of bounds for FFA
> versions < 1.2 as ffa_emad_size_get() returns 16 bytes in that case
> while reserved has an offset of 24.
> Instead of zeroing fields, memset the struct to zero first based on
> the FFA version.
>
Neat, I clearly missed taking this approach when I added zero-ing of
member initially.
> 2) Make sure there is enough size to write constituents.
>
> While at it, convert the only sizeof() in the driver that uses a
> type instead of variable.
>
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v14 05/44] arm64: RMI: Add wrappers for RMI calls
From: Marc Zyngier @ 2026-05-21 12:49 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-6-steven.price@arm.com>
On Wed, 13 May 2026 14:17:13 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> The wrappers make the call sites easier to read and deal with the
> boiler plate of handling the error codes from the RMM.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> Changes from v13:
> * Update to RMM v2.0-bet1 spec including some SRO support (there still
> some FIXMEs where SRO support is incomplete).
> Changes from v12:
> * Update to RMM v2.0 specification
> Changes from v8:
> * Switch from arm_smccc_1_2_smc() to arm_smccc_1_2_invoke() in
> rmi_rtt_read_entry() for consistency.
> Changes from v7:
> * Minor renaming of parameters and updated comments
> Changes from v5:
> * Further improve comments
> Changes from v4:
> * Improve comments
> Changes from v2:
> * Make output arguments optional.
> * Mask RIPAS value rmi_rtt_read_entry()
> * Drop unused rmi_rtt_get_phys()
> ---
> arch/arm64/include/asm/rmi_cmds.h | 661 ++++++++++++++++++++++++++++++
> 1 file changed, 661 insertions(+)
> create mode 100644 arch/arm64/include/asm/rmi_cmds.h
>
> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
> new file mode 100644
> index 000000000000..04f7066894e9
> --- /dev/null
> +++ b/arch/arm64/include/asm/rmi_cmds.h
> @@ -0,0 +1,661 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023 ARM Ltd.
> + */
> +
> +#ifndef __ASM_RMI_CMDS_H
> +#define __ASM_RMI_CMDS_H
> +
> +#include <linux/arm-smccc.h>
> +
> +#include <asm/rmi_smc.h>
> +
> +struct rtt_entry {
> + unsigned long walk_level;
> + unsigned long desc;
> + int state;
> + int ripas;
> +};
> +
> +#define RMI_MAX_ADDR_LIST 256
> +
> +struct rmi_sro_state {
> + struct arm_smccc_1_2_regs regs;
> + unsigned long addr_count;
> + unsigned long addr_list[RMI_MAX_ADDR_LIST];
> +};
> +
> +#define rmi_smccc(...) do { \
> + arm_smccc_1_1_invoke(__VA_ARGS__); \
> +} while (RMI_RETURN_STATUS(res.a0) == RMI_BUSY || \
> + RMI_RETURN_STATUS(res.a0) == RMI_BLOCKED)
> +
> +unsigned long rmi_sro_execute(struct rmi_sro_state *sro, gfp_t gfp);
> +void rmi_sro_free(struct rmi_sro_state *sro);
> +
> +/**
> + * rmi_rmm_config_set() - Configure the RMM
> + * @cfg_ptr: PA of a struct rmm_config
> + *
> + * Sets configuration options on the RMM.
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_rmm_config_set(unsigned long cfg_ptr)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_RMM_CONFIG_SET, cfg_ptr, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_rmm_activate() - Activate the RMM
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_rmm_activate(void)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_RMM_ACTIVATE, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_granule_tracking_get() - Get configuration of a Granule tracking region
> + * @start: Base PA of the tracking region
> + * @end: End of the PA region
> + * @out_category: Memory category
> + * @out_state: Tracking region state
> + * @out_top: Top of the memory region
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_granule_tracking_get(unsigned long start,
> + unsigned long end,
> + unsigned long *out_category,
> + unsigned long *out_state,
> + unsigned long *out_top)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_GRANULE_TRACKING_GET, start, end, &res);
> +
> + if (out_category)
> + *out_category = res.a1;
> + if (out_state)
> + *out_state = res.a2;
> + if (out_top)
> + *out_top = res.a3;
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_gpt_l1_create() - Create a Level 1 GPT
> + * @addr: Base of physical address region described by the L1GPT
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_gpt_l1_create(unsigned long addr)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_GPT_L1_CREATE, addr, &res);
> +
> + if (RMI_RETURN_STATUS(res.a0) == RMI_INCOMPLETE) {
> + /* FIXME */
Is that part of the SRO stuff you're talking about in the notes?
What is the ETA for fixing all these FIXMEs?
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v7 07/28] media: rockchip: rga: use clk_bulk api
From: Michael Tretter @ 2026-05-21 12:48 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-7-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:12 +0200, Sven Püschel wrote:
> Use the clk_bulk API to avoid code duplication for each of the three
> clocks.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga.c | 65 ++++---------------------------
> drivers/media/platform/rockchip/rga/rga.h | 6 +--
> 2 files changed, 11 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index fea63b94c5f3d..4e710a050cb7c 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -698,48 +698,10 @@ static const struct video_device rga_videodev = {
> .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
> };
>
> -static int rga_enable_clocks(struct rockchip_rga *rga)
> -{
> - int ret;
> -
> - ret = clk_prepare_enable(rga->sclk);
> - if (ret) {
> - dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
> - return ret;
> - }
> -
> - ret = clk_prepare_enable(rga->aclk);
> - if (ret) {
> - dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
> - goto err_disable_sclk;
> - }
> -
> - ret = clk_prepare_enable(rga->hclk);
> - if (ret) {
> - dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
> - goto err_disable_aclk;
> - }
> -
> - return 0;
> -
> -err_disable_aclk:
> - clk_disable_unprepare(rga->aclk);
> -err_disable_sclk:
> - clk_disable_unprepare(rga->sclk);
> -
> - return ret;
> -}
> -
> -static void rga_disable_clocks(struct rockchip_rga *rga)
> -{
> - clk_disable_unprepare(rga->sclk);
> - clk_disable_unprepare(rga->hclk);
> - clk_disable_unprepare(rga->aclk);
> -}
> -
> static int rga_parse_dt(struct rockchip_rga *rga)
> {
> struct reset_control *core_rst, *axi_rst, *ahb_rst;
> + int ret;
>
> core_rst = devm_reset_control_get(rga->dev, "core");
> if (IS_ERR(core_rst)) {
> @@ -771,23 +733,12 @@ static int rga_parse_dt(struct rockchip_rga *rga)
> udelay(1);
> reset_control_deassert(ahb_rst);
>
> - rga->sclk = devm_clk_get(rga->dev, "sclk");
> - if (IS_ERR(rga->sclk)) {
> - dev_err(rga->dev, "failed to get sclk clock\n");
> - return PTR_ERR(rga->sclk);
> - }
> -
> - rga->aclk = devm_clk_get(rga->dev, "aclk");
> - if (IS_ERR(rga->aclk)) {
> - dev_err(rga->dev, "failed to get aclk clock\n");
> - return PTR_ERR(rga->aclk);
> - }
> -
> - rga->hclk = devm_clk_get(rga->dev, "hclk");
> - if (IS_ERR(rga->hclk)) {
> - dev_err(rga->dev, "failed to get hclk clock\n");
> - return PTR_ERR(rga->hclk);
> + ret = devm_clk_bulk_get_all(rga->dev, &rga->clks);
> + if (ret < 0) {
This changes the behavior since the call is now successful if there are
no clocks specified in the device tree. Is this an intended change?
Michael
> + dev_err(rga->dev, "failed to get clocks\n");
> + return ret;
> }
> + rga->num_clks = ret;
>
> return 0;
> }
> @@ -935,7 +886,7 @@ static int __maybe_unused rga_runtime_suspend(struct device *dev)
> {
> struct rockchip_rga *rga = dev_get_drvdata(dev);
>
> - rga_disable_clocks(rga);
> + clk_bulk_disable_unprepare(rga->num_clks, rga->clks);
>
> return 0;
> }
> @@ -944,7 +895,7 @@ static int __maybe_unused rga_runtime_resume(struct device *dev)
> {
> struct rockchip_rga *rga = dev_get_drvdata(dev);
>
> - return rga_enable_clocks(rga);
> + return clk_bulk_prepare_enable(rga->num_clks, rga->clks);
> }
>
> static const struct dev_pm_ops rga_pm = {
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 72a28b120fabf..2db10acecb405 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -6,6 +6,7 @@
> #ifndef __RGA_H__
> #define __RGA_H__
>
> +#include <linux/clk.h>
> #include <linux/platform_device.h>
> #include <media/videobuf2-v4l2.h>
> #include <media/v4l2-ctrls.h>
> @@ -81,9 +82,8 @@ struct rockchip_rga {
> struct device *dev;
> struct regmap *grf;
> void __iomem *regs;
> - struct clk *sclk;
> - struct clk *aclk;
> - struct clk *hclk;
> + struct clk_bulk_data *clks;
> + int num_clks;
> struct rockchip_rga_version version;
>
> /* vfd lock */
>
> --
> 2.54.0
>
>
^ permalink raw reply
* [PATCH v2 3/3] KVM: arm64: Fix memory leak in hyp_trace_unload()
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort, Sashiko
In-Reply-To: <20260521124613.911067-1-vdonnefort@google.com>
During trace remote loading, hyp_trace_load() allocates the descriptor
pages but fails to store the allocated size in trace_buffer->desc_size.
As a result, when unloading the trace buffer, hyp_trace_unload() calls
free_pages_exact() with a size of 0 which fails to free the memory.
Fix this by updating the descriptor size in trace_buffer->desc_size.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8595f9bdb3dc..c4b3ee552131 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -249,6 +249,7 @@ static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
goto err_free_desc;
trace_buffer->desc = desc;
+ trace_buffer->desc_size = desc_size;
ret = hyp_trace_buffer_alloc_bpages_backing(trace_buffer, size);
if (ret)
@@ -298,6 +299,7 @@ static void hyp_trace_unload(struct trace_buffer_desc *desc, void *priv)
hyp_trace_buffer_free_bpages_backing(trace_buffer);
free_pages_exact(trace_buffer->desc, trace_buffer->desc_size);
trace_buffer->desc = NULL;
+ trace_buffer->desc_size = 0;
}
static int hyp_trace_enable_tracing(bool enable, void *priv)
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* [PATCH v2 2/3] KVM: arm64: Fix rollback in hyp_trace_buffer_share_hyp()
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort, Sashiko
In-Reply-To: <20260521124613.911067-1-vdonnefort@google.com>
When sharing the trace buffer with the hypervisor, if sharing a page
fails, the rollback path in hyp_trace_buffer_share_hyp() misses
unsharing the metadata page (meta_va) which was successfully shared
before entering the page sharing loop.
Additionally, if a failure occurs, the cleanup calls
hyp_trace_buffer_unshare_hyp() with an incorrect CPU index. Since that
CPU's pages were already rolled back locally in the loop, this leads to
duplicate unsharing attempts.
Fix both issues affecting the rollback.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 06805b426101..8595f9bdb3dc 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -212,14 +212,15 @@ static int hyp_trace_buffer_share_hyp(struct hyp_trace_buffer *trace_buffer)
}
if (ret) {
- for (p--; p >= 0; p--)
+ while (--p >= 0)
__unshare_page(rb_desc->page_va[p]);
+ __unshare_page(rb_desc->meta_va);
break;
}
}
if (ret)
- hyp_trace_buffer_unshare_hyp(trace_buffer, cpu--);
+ hyp_trace_buffer_unshare_hyp(trace_buffer, --cpu);
return ret;
}
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* [PATCH v2 1/3] KVM: arm64: Fix meta-page unsharing in pKVM hyp tracing
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort
In-Reply-To: <20260521124613.911067-1-vdonnefort@google.com>
As the hyp_trace_buffer_unshare_hyp() function name suggests we should
unshare all the previously shared pages, otherwise we leak hyp-shared
pages which won't be reusable for hyp memory.
Fix the typo by calling __unshare_page() on the meta-page, ensuring all
previously shared pages are correctly unshared.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8b7f2bf2fba8..06805b426101 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -189,7 +189,7 @@ static void hyp_trace_buffer_unshare_hyp(struct hyp_trace_buffer *trace_buffer,
if (cpu > last_cpu)
break;
- __share_page(rb_desc->meta_va);
+ __unshare_page(rb_desc->meta_va);
for (p = 0; p < rb_desc->nr_page_va; p++)
__unshare_page(rb_desc->page_va[p]);
}
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* [PATCH v2 0/3] Fixes for hyp_trace.c
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort
While reviewing my v1, Sashiko found a couple of issues with the error path and
more annoyingly a memory leak which I originally missed as the allocated
decriptor isn't tracked by kmemleak.
Changes since v2:
- Fix rollback in hyp_trace_buffer_share_hyp()
- Fix memory leak in hyp_trace_unload()
v1 (https://lore.kernel.org/all/20260521090939.735108-1-vdonnefort@google.com/)
Vincent Donnefort (3):
KVM: arm64: Fix meta-page unsharing in pKVM hyp tracing
KVM: arm64: Fix rollback in hyp_trace_buffer_share_hyp()
KVM: arm64: Fix memory leak in hyp_trace_unload()
arch/arm64/kvm/hyp_trace.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply
* Re: [PATCH v7 06/28] media: rockchip: rga: fix too small buffer size
From: Michael Tretter @ 2026-05-21 12:44 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-6-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:11 +0200, Sven Püschel wrote:
> Fix the command buffer size being only a quarter of the actual size.
> The RGA_CMDBUF_SIZE macro was potentially intended to specify the length
> of the cmdbuf u32 array pointer. But as it's used to specify the size of
> the allocation, which is counted in bytes. Therefore adjust the macro
> size to bytes as it better matches the variable name and adjust it's
> users accordingly.
>
> As the command buffer is relatively small, it probably didn't caused
> an issue due to being smaller than a single page.
>
> Fixes: f7e7b48e6d79 ("[media] rockchip/rga: v4l2 m2m support")
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>
> ---
>
> Flagged by Sashiko:
> https://sashiko.dev/#/patchset/20260325-spu-rga3-v4-0-e90ec1c61354%40pengutronix.de?part=10
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 2 +-
> drivers/media/platform/rockchip/rga/rga-hw.h | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index 43ed742a16492..d1618bb247501 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -414,7 +414,7 @@ static void rga_cmd_set(struct rga_ctx *ctx,
> {
> struct rockchip_rga *rga = ctx->rga;
>
> - memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE * 4);
> + memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE);
Maybe use rga->hw->cmdbuf_size instead of RGA_CMDBUF_SIZE to really be
in sync with the allocation.
Anyway:
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
>
> rga_cmd_set_src_addr(ctx, src->dma_desc_pa);
> /*
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h
> index cc6bd7f5b0300..2b8537a5fd0d7 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.h
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.h
> @@ -6,7 +6,7 @@
> #ifndef __RGA_HW_H__
> #define __RGA_HW_H__
>
> -#define RGA_CMDBUF_SIZE 0x20
> +#define RGA_CMDBUF_SIZE 0x80
>
> /* Hardware limits */
> #define MAX_WIDTH 8192
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH v14 04/44] arm64: RMI: Add SMC definitions for calling the RMM
From: Marc Zyngier @ 2026-05-21 12:40 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-5-steven.price@arm.com>
On Wed, 13 May 2026 14:17:12 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> The RMM (Realm Management Monitor) provides functionality that can be
> accessed by SMC calls from the host.
>
> The SMC definitions are based on DEN0137[1] version 2.0-bet1
>
> [1] https://developer.arm.com/documentation/den0137/2-0bet1/
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> Changes since v13:
> * Updated to RMM spec v2.0-bet1
> Changes since v12:
> * Updated to RMM spec v2.0-bet0
> Changes since v9:
> * Corrected size of 'ripas_value' in struct rec_exit. The spec states
> this is an 8-bit type with padding afterwards (rather than a u64).
> Changes since v8:
> * Added RMI_PERMITTED_GICV3_HCR_BITS to define which bits the RMM
> permits to be modified.
> Changes since v6:
> * Renamed REC_ENTER_xxx defines to include 'FLAG' to make it obvious
> these are flag values.
> Changes since v5:
> * Sorted the SMC #defines by value.
> * Renamed SMI_RxI_CALL to SMI_RMI_CALL since the macro is only used for
> RMI calls.
> * Renamed REC_GIC_NUM_LRS to REC_MAX_GIC_NUM_LRS since the actual
> number of available list registers could be lower.
> * Provided a define for the reserved fields of FeatureRegister0.
> * Fix inconsistent names for padding fields.
> Changes since v4:
> * Update to point to final released RMM spec.
> * Minor rearrangements.
> Changes since v3:
> * Update to match RMM spec v1.0-rel0-rc1.
> Changes since v2:
> * Fix specification link.
> * Rename rec_entry->rec_enter to match spec.
> * Fix size of pmu_ovf_status to match spec.
> ---
> arch/arm64/include/asm/rmi_smc.h | 448 +++++++++++++++++++++++++++++++
> 1 file changed, 448 insertions(+)
> create mode 100644 arch/arm64/include/asm/rmi_smc.h
>
> diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_smc.h
> new file mode 100644
> index 000000000000..a09b7a631fef
> --- /dev/null
> +++ b/arch/arm64/include/asm/rmi_smc.h
> @@ -0,0 +1,448 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023-2026 ARM Ltd.
> + *
> + * The values and structures in this file are from the Realm Management Monitor
> + * specification (DEN0137) version 2.0-bet1:
> + * https://developer.arm.com/documentation/den0137/2-0bet1/
How long is this spec going to be available on the ARM web site, which
has a tendency of being reorganised every other week? And there is
already a beta2.
> + */
> +
> +#ifndef __ASM_RMI_SMC_H
> +#define __ASM_RMI_SMC_H
> +
> +#include <linux/arm-smccc.h>
> +
> +#define SMC_RMI_CALL(func) \
> + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
> + ARM_SMCCC_SMC_64, \
> + ARM_SMCCC_OWNER_STANDARD, \
> + (func))
> +
> +#define SMC_RMI_VERSION SMC_RMI_CALL(0x0150)
> +
> +#define SMC_RMI_RTT_DATA_MAP_INIT SMC_RMI_CALL(0x0153)
> +
> +#define SMC_RMI_REALM_ACTIVATE SMC_RMI_CALL(0x0157)
> +#define SMC_RMI_REALM_CREATE SMC_RMI_CALL(0x0158)
> +#define SMC_RMI_REALM_DESTROY SMC_RMI_CALL(0x0159)
> +#define SMC_RMI_REC_CREATE SMC_RMI_CALL(0x015a)
> +#define SMC_RMI_REC_DESTROY SMC_RMI_CALL(0x015b)
> +#define SMC_RMI_REC_ENTER SMC_RMI_CALL(0x015c)
> +#define SMC_RMI_RTT_CREATE SMC_RMI_CALL(0x015d)
> +#define SMC_RMI_RTT_DESTROY SMC_RMI_CALL(0x015e)
> +
> +#define SMC_RMI_RTT_READ_ENTRY SMC_RMI_CALL(0x0161)
> +
> +#define SMC_RMI_RTT_DEV_VALIDATE SMC_RMI_CALL(0x0163)
> +#define SMC_RMI_PSCI_COMPLETE SMC_RMI_CALL(0x0164)
> +#define SMC_RMI_FEATURES SMC_RMI_CALL(0x0165)
> +#define SMC_RMI_RTT_FOLD SMC_RMI_CALL(0x0166)
> +
> +#define SMC_RMI_RTT_INIT_RIPAS SMC_RMI_CALL(0x0168)
> +#define SMC_RMI_RTT_SET_RIPAS SMC_RMI_CALL(0x0169)
> +#define SMC_RMI_VSMMU_CREATE SMC_RMI_CALL(0x016a)
> +#define SMC_RMI_VSMMU_DESTROY SMC_RMI_CALL(0x016b)
> +#define SMC_RMI_RMM_CONFIG_SET SMC_RMI_CALL(0x016e)
> +#define SMC_RMI_PSMMU_IRQ_NOTIFY SMC_RMI_CALL(0x016f)
> +
> +#define SMC_RMI_PDEV_ABORT SMC_RMI_CALL(0x0174)
> +#define SMC_RMI_PDEV_COMMUNICATE SMC_RMI_CALL(0x0175)
> +#define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176)
> +#define SMC_RMI_PDEV_DESTROY SMC_RMI_CALL(0x0177)
> +#define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178)
> +
> +#define SMC_RMI_PDEV_STREAM_KEY_REFRESH SMC_RMI_CALL(0x017a)
> +#define SMC_RMI_PDEV_SET_PUBKEY SMC_RMI_CALL(0x017b)
> +#define SMC_RMI_PDEV_STOP SMC_RMI_CALL(0x017c)
> +#define SMC_RMI_RTT_AUX_CREATE SMC_RMI_CALL(0x017d)
> +#define SMC_RMI_RTT_AUX_DESTROY SMC_RMI_CALL(0x017e)
> +#define SMC_RMI_RTT_AUX_FOLD SMC_RMI_CALL(0x017f)
> +
> +#define SMC_RMI_VDEV_ABORT SMC_RMI_CALL(0x0185)
> +#define SMC_RMI_VDEV_COMMUNICATE SMC_RMI_CALL(0x0186)
> +#define SMC_RMI_VDEV_CREATE SMC_RMI_CALL(0x0187)
> +#define SMC_RMI_VDEV_DESTROY SMC_RMI_CALL(0x0188)
> +#define SMC_RMI_VDEV_GET_STATE SMC_RMI_CALL(0x0189)
> +#define SMC_RMI_VDEV_UNLOCK SMC_RMI_CALL(0x018a)
> +#define SMC_RMI_RTT_SET_S2AP SMC_RMI_CALL(0x018b)
> +#define SMC_RMI_VDEV_COMPLETE SMC_RMI_CALL(0x018e)
> +
> +#define SMC_RMI_VDEV_GET_INTERFACE_REPORT SMC_RMI_CALL(0x01d0)
> +#define SMC_RMI_VDEV_GET_MEASUREMENTS SMC_RMI_CALL(0x01d1)
> +#define SMC_RMI_VDEV_LOCK SMC_RMI_CALL(0x01d2)
> +#define SMC_RMI_VDEV_START SMC_RMI_CALL(0x01d3)
> +
> +#define SMC_RMI_VSMMU_EVENT_NOTIFY SMC_RMI_CALL(0x01d6)
> +#define SMC_RMI_PSMMU_ACTIVATE SMC_RMI_CALL(0x01d7)
> +#define SMC_RMI_PSMMU_DEACTIVATE SMC_RMI_CALL(0x01d8)
> +
> +#define SMC_RMI_PSMMU_ST_L2_CREATE SMC_RMI_CALL(0x01db)
> +#define SMC_RMI_PSMMU_ST_L2_DESTROY SMC_RMI_CALL(0x01dc)
> +#define SMC_RMI_DPT_L0_CREATE SMC_RMI_CALL(0x01dd)
> +#define SMC_RMI_DPT_L0_DESTROY SMC_RMI_CALL(0x01de)
> +#define SMC_RMI_DPT_L1_CREATE SMC_RMI_CALL(0x01df)
> +#define SMC_RMI_DPT_L1_DESTROY SMC_RMI_CALL(0x01e0)
> +#define SMC_RMI_GRANULE_TRACKING_GET SMC_RMI_CALL(0x01e1)
> +
> +#define SMC_RMI_GRANULE_TRACKING_SET SMC_RMI_CALL(0x01e3)
> +
> +#define SMC_RMI_RMM_CONFIG_GET SMC_RMI_CALL(0x01ec)
> +
> +#define SMC_RMI_RMM_STATE_GET SMC_RMI_CALL(0x01ee)
> +
> +#define SMC_RMI_PSMMU_EVENT_CONSUME SMC_RMI_CALL(0x01f0)
> +#define SMC_RMI_GRANULE_RANGE_DELEGATE SMC_RMI_CALL(0x01f1)
> +#define SMC_RMI_GRANULE_RANGE_UNDELEGATE SMC_RMI_CALL(0x01f2)
> +#define SMC_RMI_GPT_L1_CREATE SMC_RMI_CALL(0x01f3)
> +#define SMC_RMI_GPT_L1_DESTROY SMC_RMI_CALL(0x01f4)
> +#define SMC_RMI_RTT_DATA_MAP SMC_RMI_CALL(0x01f5)
> +#define SMC_RMI_RTT_DATA_UNMAP SMC_RMI_CALL(0x01f6)
> +#define SMC_RMI_RTT_DEV_MAP SMC_RMI_CALL(0x01f7)
> +#define SMC_RMI_RTT_DEV_UNMAP SMC_RMI_CALL(0x01f8)
> +#define SMC_RMI_RTT_ARCH_DEV_MAP SMC_RMI_CALL(0x01f9)
> +#define SMC_RMI_RTT_ARCH_DEV_UNMAP SMC_RMI_CALL(0x01fa)
> +#define SMC_RMI_RTT_UNPROT_MAP SMC_RMI_CALL(0x01fb)
> +#define SMC_RMI_RTT_UNPROT_UNMAP SMC_RMI_CALL(0x01fc)
> +#define SMC_RMI_RTT_AUX_PROT_MAP SMC_RMI_CALL(0x01fd)
> +#define SMC_RMI_RTT_AUX_PROT_UNMAP SMC_RMI_CALL(0x01fe)
> +#define SMC_RMI_RTT_AUX_UNPROT_MAP SMC_RMI_CALL(0x01ff)
> +#define SMC_RMI_RTT_AUX_UNPROT_UNMAP SMC_RMI_CALL(0x0200)
> +#define SMC_RMI_REALM_TERMINATE SMC_RMI_CALL(0x0201)
> +#define SMC_RMI_RMM_ACTIVATE SMC_RMI_CALL(0x0202)
> +#define SMC_RMI_OP_CONTINUE SMC_RMI_CALL(0x0203)
> +#define SMC_RMI_PDEV_STREAM_CONNECT SMC_RMI_CALL(0x0204)
> +#define SMC_RMI_PDEV_STREAM_DISCONNECT SMC_RMI_CALL(0x0205)
> +#define SMC_RMI_PDEV_STREAM_COMPLETE SMC_RMI_CALL(0x0206)
> +#define SMC_RMI_PDEV_STREAM_KEY_PURGE SMC_RMI_CALL(0x0207)
> +#define SMC_RMI_OP_MEM_DONATE SMC_RMI_CALL(0x0208)
> +#define SMC_RMI_OP_MEM_RECLAIM SMC_RMI_CALL(0x0209)
> +#define SMC_RMI_OP_CANCEL SMC_RMI_CALL(0x020a)
> +#define SMC_RMI_VSMMU_FEATURES SMC_RMI_CALL(0x020b)
> +#define SMC_RMI_VSMMU_CMD_GET SMC_RMI_CALL(0x020c)
> +#define SMC_RMI_VSMMU_CMD_COMPLETE SMC_RMI_CALL(0x020d)
> +#define SMC_RMI_PSMMU_INFO SMC_RMI_CALL(0x020e)
> +
> +#define RMI_ABI_MAJOR_VERSION 2
> +#define RMI_ABI_MINOR_VERSION 0
> +
> +#define RMI_ABI_VERSION_GET_MAJOR(version) ((version) >> 16)
> +#define RMI_ABI_VERSION_GET_MINOR(version) ((version) & 0xFFFF)
> +#define RMI_ABI_VERSION(major, minor) (((major) << 16) | (minor))
> +
> +#define RMI_UNASSIGNED 0
> +#define RMI_ASSIGNED 1
> +#define RMI_TABLE 2
> +
> +#define RMI_RETURN_STATUS(ret) ((ret) & 0xFF)
> +#define RMI_RETURN_INDEX(ret) (((ret) >> 8) & 0xFF)
> +#define RMI_RETURN_MEMREQ(ret) (((ret) >> 8) & 0x3)
> +#define RMI_RETURN_CAN_CANCEL(ret) (((ret) >> 10) & 0x1)
Use FIELD_GET() and specify masks that define the actual fields.
> +
> +#define RMI_SUCCESS 0
> +#define RMI_ERROR_INPUT 1
> +#define RMI_ERROR_REALM 2
> +#define RMI_ERROR_REC 3
> +#define RMI_ERROR_RTT 4
> +#define RMI_ERROR_NOT_SUPPORTED 5
> +#define RMI_ERROR_DEVICE 6
> +#define RMI_ERROR_RTT_AUX 7
> +#define RMI_ERROR_PSMMU_ST 8
> +#define RMI_ERROR_DPT 9
> +#define RMI_BUSY 10
> +#define RMI_ERROR_GLOBAL 11
> +#define RMI_ERROR_TRACKING 12
> +#define RMI_INCOMPLETE 13
> +#define RMI_BLOCKED 14
> +#define RMI_ERROR_GPT 15
> +#define RMI_ERROR_GRANULE 16
> +
> +#define RMI_OP_MEM_REQ_NONE 0
> +#define RMI_OP_MEM_REQ_DONATE 1
> +#define RMI_OP_MEM_REQ_RECLAIM 2
> +
> +#define RMI_DONATE_SIZE(req) ((req) & 0x3)
> +#define RMI_DONATE_COUNT_MASK GENMASK(15, 2)
> +#define RMI_DONATE_COUNT(req) (((req) & RMI_DONATE_COUNT_MASK) >> 2)
> +#define RMI_DONATE_CONTIG(req) (!!((req) & BIT(16)))
> +#define RMI_DONATE_STATE(req) (!!((req) & BIT(17)))
FIELD_GET().
> +
> +#define RMI_OP_MEM_DELEGATED 0
> +#define RMI_OP_MEM_UNDELEGATED 1
> +
> +#define RMI_ADDR_TYPE_NONE 0
> +#define RMI_ADDR_TYPE_SINGLE 1
> +#define RMI_ADDR_TYPE_LIST 2
> +
> +#define RMI_ADDR_RANGE_SIZE_MASK GENMASK(1, 0)
> +#define RMI_ADDR_RANGE_COUNT_MASK GENMASK(PAGE_SHIFT - 1, 2)
> +#define RMI_ADDR_RANGE_ADDR_MASK (PAGE_MASK & GENMASK(51, 0))
> +#define RMI_ADDR_RANGE_STATE_MASK BIT(63)
> +
> +#define RMI_ADDR_RANGE_SIZE(ar) (FIELD_GET(RMI_ADDR_RANGE_SIZE_MASK, \
> + (ar)))
> +#define RMI_ADDR_RANGE_COUNT(ar) (FIELD_GET(RMI_ADDR_RANGE_COUNT_MASK, \
> + (ar)))
> +#define RMI_ADDR_RANGE_ADDR(ar) ((ar) & RMI_ADDR_RANGE_ADDR_MASK)
> +#define RMI_ADDR_RANGE_STATE(ar) (FIELD_GET(RMI_ADDR_RANGE_STATE_MASK, \
> + (ar)))
> +
> +enum rmi_ripas {
> + RMI_EMPTY = 0,
> + RMI_RAM = 1,
> + RMI_DESTROYED = 2,
> + RMI_DEV = 3,
> +};
> +
> +#define RMI_NO_MEASURE_CONTENT 0
> +#define RMI_MEASURE_CONTENT 1
> +
> +#define RMI_FEATURE_REGISTER_0_S2SZ GENMASK(7, 0)
> +#define RMI_FEATURE_REGISTER_0_LPA2 BIT(8)
> +#define RMI_FEATURE_REGISTER_0_SVE BIT(9)
> +#define RMI_FEATURE_REGISTER_0_SVE_VL GENMASK(13, 10)
> +#define RMI_FEATURE_REGISTER_0_NUM_BPS GENMASK(19, 14)
> +#define RMI_FEATURE_REGISTER_0_NUM_WPS GENMASK(25, 20)
> +#define RMI_FEATURE_REGISTER_0_PMU BIT(26)
> +#define RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS GENMASK(31, 27)
> +
> +#define RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_4KB BIT(0)
> +#define RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_16KB BIT(1)
> +#define RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_64KB BIT(2)
> +#define RMI_FEATURE_REGISTER_1_HASH_SHA_256 BIT(3)
> +#define RMI_FEATURE_REGISTER_1_HASH_SHA_384 BIT(4)
> +#define RMI_FEATURE_REGISTER_1_HASH_SHA_512 BIT(5)
> +#define RMI_FEATURE_REGISTER_1_MAX_RECS_ORDER GENMASK(9, 6)
> +#define RMI_FEATURE_REGISTER_1_L0GPTSZ GENMASK(13, 10)
> +#define RMI_FEATURE_REGISTER_1_PPS GENMASK(16, 14)
> +
> +#define RMI_FEATURE_REGISTER_2_DA BIT(0)
> +#define RMI_FEATURE_REGISTER_2_DA_COH BIT(1)
> +#define RMI_FEATURE_REGISTER_2_VSMMU BIT(2)
> +#define RMI_FEATURE_REGISTER_2_ATS BIT(3)
> +#define RMI_FEATURE_REGISTER_2_MAX_VDEVS_ORDER GENMASK(7, 4)
> +#define RMI_FEATURE_REGISTER_2_VDEV_KROU BIT(8)
> +#define RMI_FEATURE_REGISTER_2_NON_TEE_STREAM BIT(9)
> +
> +#define RMI_FEATURE_REGISTER_3_MAX_NUM_AUX_PLANES GENMASK(3, 0)
> +#define RMI_FEATURE_REGISTER_3_RTT_PLAN GENMASK(5, 4)
> +#define RMI_FEATURE_REGISTER_3_RTT_S2AP_INDIRECT BIT(6)
> +
> +#define RMI_FEATURE_REGISTER_4_MEC_COUNT GENMASK(63, 0)
> +
> +#define RMI_MEM_CATEGORY_CONVENTIONAL 0
> +#define RMI_MEM_CATEGORY_DEV_NCOH 1
> +#define RMI_MEM_CATEGORY_DEV_COH 2
> +
> +#define RMI_TRACKING_RESERVED 0
> +#define RMI_TRACKING_NONE 1
> +#define RMI_TRACKING_FINE 2
> +#define RMI_TRACKING_COARSE 3
> +
> +#define RMI_GRANULE_SIZE_4KB 0
> +#define RMI_GRANULE_SIZE_16KB 1
> +#define RMI_GRANULE_SIZE_64KB 2
> +
> +/*
> + * Note many of these fields are smaller than u64 but all fields have u64
> + * alignment, so use u64 to ensure correct alignment.
> + */
> +struct rmm_config {
> + union { /* 0x0 */
> + struct {
> + u64 tracking_region_size;
> + u64 rmi_granule_size;
> + };
> + u8 sizer[0x1000];
SZ_4K?
> + };
> +};
> +
> +#define RMI_REALM_PARAM_FLAG_LPA2 BIT(0)
> +#define RMI_REALM_PARAM_FLAG_SVE BIT(1)
> +#define RMI_REALM_PARAM_FLAG_PMU BIT(2)
> +
> +struct realm_params {
> + union { /* 0x0 */
> + struct {
> + u64 flags;
> + u64 s2sz;
> + u64 sve_vl;
> + u64 num_bps;
> + u64 num_wps;
> + u64 pmu_num_ctrs;
> + u64 hash_algo;
> + u64 num_aux_planes;
> + };
> + u8 padding0[0x400];
SZ_1K? And similarly all over the shop?
I haven't checked the details of the encodings (life is too short),
but I wonder how much of this exists as an MRS and could be
automatically generated?
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v3] i2c: imx: mark I2C adapter when hardware is powered down
From: Mukesh Savaliya @ 2026-05-21 12:39 UTC (permalink / raw)
To: Carlos Song (OSS), Mukesh Savaliya, o.rempel@pengutronix.de,
kernel@pengutronix.de, andi.shyti@kernel.org, Frank Li,
s.hauer@pengutronix.de, festevam@gmail.com, Carlos Song,
Bough Chen
Cc: linux-i2c@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
In-Reply-To: <AM0PR04MB68024A0FAF0637726C08B87BE80E2@AM0PR04MB6802.eurprd04.prod.outlook.com>
On 5/21/2026 5:32 PM, Carlos Song (OSS) wrote:
>
>
>> -----Original Message-----
>> From: Mukesh Savaliya <mukesh.savaliya@oss.qualcomm.com>
>> Sent: Thursday, May 21, 2026 7:14 PM
>> To: Carlos Song (OSS) <carlos.song@oss.nxp.com>; Mukesh Savaliya
>> <mukesh.savaliya@oss.qualcomm.com>; o.rempel@pengutronix.de;
>> kernel@pengutronix.de; andi.shyti@kernel.org; Frank Li <frank.li@nxp.com>;
>> s.hauer@pengutronix.de; festevam@gmail.com; Carlos Song
>> <carlos.song@nxp.com>; Bough Chen <haibo.chen@nxp.com>
>> Cc: linux-i2c@vger.kernel.org; imx@lists.linux.dev;
>> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
>> stable@vger.kernel.org
>> Subject: Re: [PATCH v3] i2c: imx: mark I2C adapter when hardware is powered
>> down
>>
>>
>> On 5/21/2026 4:21 PM, Carlos Song (OSS) wrote:
>>
>> [...]
>>
>>>>>> -----Original Message-----
>>>>>> From: Mukesh Savaliya <mukesh.savaliya@oss.qualcomm.com>
>>>>>> Sent: Thursday, May 21, 2026 3:40 PM
>>>>>> To: Carlos Song (OSS) <carlos.song@oss.nxp.com>;
>>>>>> o.rempel@pengutronix.de; kernel@pengutronix.de;
>>>>>> andi.shyti@kernel.org; Frank Li <frank.li@nxp.com>;
>>>>>> s.hauer@pengutronix.de; festevam@gmail.com; Carlos Song
>>>>>> <carlos.song@nxp.com>; Bough Chen <haibo.chen@nxp.com>
>>>>>> Cc: linux-i2c@vger.kernel.org; imx@lists.linux.dev;
>>>>>> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
>>>>>> stable@vger.kernel.org
>>>>>> Subject: Re: [PATCH v3] i2c: imx: mark I2C adapter when hardware is
>>>>>> powered down
>>>>>>
>>>>>> Hi Carlos,
>>>>>>
>>>>>> On 5/20/2026 3:45 PM, Carlos Song (OSS) wrote:
>>>>>>> From: Carlos Song <carlos.song@nxp.com>
>>>>>>>
>>>>>>> Mark the I2C adapter as suspended during system suspend to block
>>>>>>> further transfers, and resume it on system resume. This prevents
>>>>>>> potential hangs when the hardware is powered down but clients
>>>>>>> still attempt
>>>>>> I2C transfers.
>>>>>>>
>>>> what was the reason of this hang ? I was thinking you don't have
>>>> interrupts working when client requested transfer but adapter was
>>>> suspended. Please correct me if wrong.
>>>>
>>>> And it would be good to mention the actual problem and why/how it
>> occurred.
>>>>>> Code changes looks fine to me but have comment on commit log.
>>>>>>
>>>>>> It seems, you are adding support of _noirq() callbacks to allow
>>>>>> transfers during suspend/resume noirq phase of PM.
>>>>>>
>>>>>> Would it make sense if you can write "Replace system PM callbacks
>>>>>> with noirq PM callbacks" OR "Allow transfers during _noirq phase of
>>>>>> the PM ops" instead of "mark I2C adapter when hardware is powered
>>>> down" ?
>>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> Thank you for your comments!
>>>>>
>>>>> But this patch is added is not for support noirq PM callback or
>>>>> transfer in noirq
>>>> phase.
>>>>>
>>>> Okay, may be actual problem description can help me.
>>>>> In fact, this fix is to mark the I2C adapter as suspended during
>>>>> system noirq suspend to block further transfers, and resume it on
>>>>> system noirq resume. This is to prohibit I2C device calling the I2C
>>>>> controller after the system noirq suspend and before noirq resume,
>>>>> because at
>>>> this time the I2C instance is powered off or the clock is disabled
>>>> ... So I want to keep current commit. How do you think?
>>>> completely Makes sense. Please help add how this problem occurred and
>> why ?
>>>> So the change/fix will be good to understand against it.
>>>
>>> Hi,
>>>
>>> In some I.MX platform, some I2C devices will keep a work queue all
>>> time, the work queue will trigger I2C xfer every once in a while, but the work
>> queue shouldn't be free in system suspend.
>>>
>>
>> work queue has transfers queued even if system is suspended ? IMO, the client
>> i2c devices should not let system go to suspend.
>>
>
> Hi Mukesh,
>
> Thank you for the detailed discussion.
>
> Yes, I totally agree that I2C client drivers should ideally stop
> issuing transfers when the system is suspending.
>
> However, in practice there are many different I2C clients, and not all
> of them strictly adhere to this requirement. Some clients may still
> trigger transfers through workqueues or deferred contexts during the
> suspend/resume window.
>
> Therefore, adding this protection at the I2C controller side helps to
> avoid unexpected accesses when the hardware resources are unavailable,
> making the system more robust.
>
Agreed !
>>> Within a very short time window, possibly from noirq_suspend to the
>>> system actually being suspended, or possibly from the system starting
>>> to resume to before noirq_resume, this work queue will trigger an I2C
>>> transfer, and at this time the I2C controller's clk and pinctrl have
>>> not yet been restored, reading and
>>
>> Right, this kind of explains the problem to me. I think you are trying to serve
>> i2c transfers when your resources(clk, pinctrl) are not turned ON and also
>> interrupt remains disabled. And that's why you need to add
>> _noir() PM callbacks supports along with IRQF_NO_SUSPEND |
>> IRQF_EARLY_RESUME flags.
>>
>>> writing I2C registers causes the system to hang. This patch make all
>>> I2C operations are performed in a safe hardware state.
>>>
>>> Is it better if I add these comment to patch commit log?
>>>>>
>> if my latest comments makes sense against the issue, you may write
>> accordingly. if i am wrong, then your explanation makes sense. Cause of the
>> hang needs to be clearly mention int the commit log in your next patch.
>>
>
> Based on our discussion, I have updated the commit log as below:
>
> On some i.MX platforms, certain I2C client drivers keep a periodic
> workqueue which continues to trigger I2C transfers.
>
> During system suspend/resume, there exists a time window between:
> - noirq_suspend and full suspend
> - resume start and noirq_resume
- noirq_resume and resume start [Just opposite ?]
>
> In this window, the I2C controller resources such as clock and pinctrl
> may already be disabled or not yet restored.
>
> If a workqueue triggers an I2C transfer in this period, the driver
> attempts to access I2C registers while the hardware resources are
> unavailable, which may lead to system hang.
>
> Mark the I2C adapter as suspended during noirq suspend and block new
> transfers until resume, ensuring that I2C transfers are only issued
> when hardware resources are available.
>
> Does this look good to you?
>
Looks good, Thanks !
>>>>
>>>
>
^ permalink raw reply
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