* [PATCH v2 07/11] firmware: arm_ffa: Keep framework RX release under lock
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel; +Cc: Jens Wiklander, Sudeep Holla
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
The framework notification handler drops rx_lock before issuing
FFA_RX_RELEASE, leaving a window where another RX-buffer user can
start a new FF-A transaction before ownership has actually been
returned to firmware.
Move the FFA_RX_RELEASE calls so they execute while rx_lock is still
held on both the kmemdup() failure path and the normal success path.
While doing that, switch the handler to scoped_guard() to keep the
critical section explicit.
Fixes: 285a5ea0f542 ("firmware: arm_ffa: Add support for handling framework notifications")
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 29 +++++++++++++----------------
1 file changed, 13 insertions(+), 16 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index ed502486eb35..18bcbd161805 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1494,25 +1494,22 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
if (!(bitmap & FRAMEWORK_NOTIFY_RX_BUFFER_FULL))
return;
- mutex_lock(&drv_info->rx_lock);
+ scoped_guard(mutex, &drv_info->rx_lock) {
+ msg = drv_info->rx_buffer;
+ buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
+ if (!buf) {
+ ffa_rx_release();
+ return;
+ }
- msg = drv_info->rx_buffer;
- buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
- if (!buf) {
- mutex_unlock(&drv_info->rx_lock);
- return;
+ target = SENDER_ID(msg->send_recv_id);
+ if (msg->offset >= sizeof(*msg))
+ uuid_copy(&uuid, &msg->uuid);
+ else
+ uuid_copy(&uuid, &uuid_null);
+ ffa_rx_release();
}
- target = SENDER_ID(msg->send_recv_id);
- if (msg->offset >= sizeof(*msg))
- uuid_copy(&uuid, &msg->uuid);
- else
- uuid_copy(&uuid, &uuid_null);
-
- mutex_unlock(&drv_info->rx_lock);
-
- ffa_rx_release();
-
read_lock(&drv_info->notify_lock);
cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target, &uuid);
read_unlock(&drv_info->notify_lock);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 03/11] firmware: arm_ffa: Avoid collapsing NPI work from different CPUs
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel; +Cc: Jens Wiklander, Sudeep Holla
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
Notification pending interrupts are registered as per-CPU IRQs, but the
driver queues all NPI handling through a single shared work_struct.
That allows queue_work_on() calls from different CPUs to collapse onto a
single pending work item even though the work function uses the CPU it
runs on to fetch and handle per-CPU notifications.
Move notif_pcpu_work into the per-CPU ffa_pcpu_irq state and initialize
one work item per CPU. This keeps NPI handling independent per CPU and
avoids losing notifications when multiple CPUs queue work concurrently.
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index e6a051b20cb7..4e66c7325a4e 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -87,6 +87,7 @@ static inline int ffa_to_linux_errno(int errno)
struct ffa_pcpu_irq {
struct ffa_drv_info *info;
+ struct work_struct notif_pcpu_work;
};
struct ffa_drv_info {
@@ -106,7 +107,6 @@ struct ffa_drv_info {
unsigned int cpuhp_state;
struct ffa_pcpu_irq __percpu *irq_pcpu;
struct workqueue_struct *notif_pcpu_wq;
- struct work_struct notif_pcpu_work;
struct work_struct sched_recv_irq_work;
struct xarray partition_info;
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
@@ -1539,8 +1539,9 @@ ffa_self_notif_handle(u16 vcpu, bool is_per_vcpu, void *cb_data)
static void notif_pcpu_irq_work_fn(struct work_struct *work)
{
- struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
+ struct ffa_pcpu_irq *pcpu = container_of(work, struct ffa_pcpu_irq,
notif_pcpu_work);
+ struct ffa_drv_info *info = pcpu->info;
ffa_self_notif_handle(smp_processor_id(), true, info);
}
@@ -1811,7 +1812,7 @@ static irqreturn_t notif_pend_irq_handler(int irq, void *irq_data)
struct ffa_drv_info *info = pcpu->info;
queue_work_on(smp_processor_id(), info->notif_pcpu_wq,
- &info->notif_pcpu_work);
+ &pcpu->notif_pcpu_work);
return IRQ_HANDLED;
}
@@ -1928,8 +1929,11 @@ static int ffa_init_pcpu_irq(void)
if (!irq_pcpu)
return -ENOMEM;
- for_each_present_cpu(cpu)
+ for_each_present_cpu(cpu) {
per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
+ INIT_WORK(&per_cpu_ptr(irq_pcpu, cpu)->notif_pcpu_work,
+ notif_pcpu_irq_work_fn);
+ }
drv_info->irq_pcpu = irq_pcpu;
@@ -1958,7 +1962,6 @@ static int ffa_init_pcpu_irq(void)
}
INIT_WORK(&drv_info->sched_recv_irq_work, ffa_sched_recv_irq_work_fn);
- INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
if (!drv_info->notif_pcpu_wq)
return -EINVAL;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 05/11] firmware: arm_ffa: Unregister bus notifier on teardown for FF-A v1.0
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel; +Cc: Jens Wiklander, Sudeep Holla
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
For FF-A v1.0 the driver registers a bus notifier to backfill UUID
matching, but the notifier was never unregistered on cleanup paths.
Track the registration state and unregister it during teardown and early
partition-setup failure.
Fixes: 9dd15934f60d ("firmware: arm_ffa: Move the FF-A v1.0 NULL UUID workaround to bus notifier")
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 2241e851f7ae..a122814eb6d7 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -101,6 +101,7 @@ struct ffa_drv_info {
bool mem_ops_native;
bool msg_direct_req2_supp;
bool bitmap_created;
+ bool bus_notifier_registered;
bool notif_enabled;
unsigned int sched_recv_irq;
unsigned int notif_pend_irq;
@@ -1630,6 +1631,15 @@ static struct notifier_block ffa_bus_nb = {
.notifier_call = ffa_bus_notifier,
};
+static void ffa_bus_notifier_unregister(void)
+{
+ if (!drv_info->bus_notifier_registered)
+ return;
+
+ bus_unregister_notifier(&ffa_bus_type, &ffa_bus_nb);
+ drv_info->bus_notifier_registered = false;
+}
+
static int ffa_xa_add_partition_info(struct ffa_device *dev)
{
struct ffa_dev_part_info *info;
@@ -1713,6 +1723,8 @@ static void ffa_partitions_cleanup(void)
struct list_head *phead;
unsigned long idx;
+ ffa_bus_notifier_unregister();
+
/* Clean up/free all registered devices */
ffa_devices_unregister();
@@ -1740,11 +1752,14 @@ static int ffa_setup_partitions(void)
ret = bus_register_notifier(&ffa_bus_type, &ffa_bus_nb);
if (ret)
pr_err("Failed to register FF-A bus notifiers\n");
+ else
+ drv_info->bus_notifier_registered = true;
}
count = ffa_partition_probe(&uuid_null, &pbuf);
if (count <= 0) {
pr_info("%s: No partitions found, error %d\n", __func__, count);
+ ffa_bus_notifier_unregister();
return -EINVAL;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2 09/11] firmware: arm_ffa: Align RxTx buffer size before mapping
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel
Cc: Jens Wiklander, Sudeep Holla, Sebastian Ene
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
Commit 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during
RXTX_MAP") advertises PAGE_ALIGN(rxtx_bufsz) to firmware when mapping the
buffers but the driver continues to stores the minimum FF-A buffer size
in drv_info->rxtx_bufsz which is used elsewhere in the driver.
Align the size before storing it so that the allocation, validation and
FFA_RXTX_MAP all use the same buffer size.
Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP")
Cc: Sebastian Ene <sebastianene@google.com>
Link: https://sashiko.dev/#/patchset/20260402113939.930221-1-sebastianene@google.com
Reviewed-by: Sebastian Ene <sebastianene@google.com>
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 4944aa6b815f..9181cc752ce1 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -2111,6 +2111,7 @@ static int __init ffa_init(void)
rxtx_bufsz = SZ_4K;
}
+ rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
drv_info->rxtx_bufsz = rxtx_bufsz;
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->rx_buffer) {
@@ -2126,7 +2127,7 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
- PAGE_ALIGN(rxtx_bufsz) / FFA_PAGE_SIZE);
+ rxtx_bufsz / FFA_PAGE_SIZE);
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 08/11] firmware: arm_ffa: Validate framework notification message layout
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel; +Cc: Jens Wiklander, Sudeep Holla
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
Framework notifications carry an indirect message in the shared RX
buffer. Validate the reported offset and size before using them, reject
zero-length payloads, and ensure that any non-header payload starts at
the UUID field rather than in the middle of the message header.
Use the validated offset and size values for both kmemdup() and the UUID
parsing path so malformed firmware data cannot drive an out-of-bounds
read or an oversized allocation.
Fixes: 285a5ea0f542 ("firmware: arm_ffa: Add support for handling framework notifications")
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 18bcbd161805..4944aa6b815f 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1489,21 +1489,35 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
int notify_id = 0, target;
struct ffa_indirect_msg_hdr *msg;
struct notifier_cb_info *cb_info = NULL;
+ size_t min_offset = offsetof(struct ffa_indirect_msg_hdr, uuid);
/* Only one framework notification defined and supported for now */
if (!(bitmap & FRAMEWORK_NOTIFY_RX_BUFFER_FULL))
return;
scoped_guard(mutex, &drv_info->rx_lock) {
+ u32 offset, size;
+
msg = drv_info->rx_buffer;
- buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
+ offset = msg->offset;
+ size = msg->size;
+
+ if (!size || (offset != min_offset && offset < sizeof(*msg)) ||
+ offset > drv_info->rxtx_bufsz ||
+ size > drv_info->rxtx_bufsz - offset) {
+ pr_err("invalid framework notification message\n");
+ ffa_rx_release();
+ return;
+ }
+
+ buf = kmemdup((void *)msg + offset, size, GFP_KERNEL);
if (!buf) {
ffa_rx_release();
return;
}
target = SENDER_ID(msg->send_recv_id);
- if (msg->offset >= sizeof(*msg))
+ if (offset >= sizeof(*msg))
uuid_copy(&uuid, &msg->uuid);
else
uuid_copy(&uuid, &uuid_null);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 11/11] firmware: arm_ffa: Fix sched-recv callback partition lookup
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel; +Cc: Jens Wiklander, Sudeep Holla
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
ffa_sched_recv_cb_update() used list_for_each_entry_safe() to search for
a matching partition and then tested the iterator against NULL. That is
not a valid end-of-list check for circular lists and can fall through
with an invalid pointer. Use a normal iterator and detect the not-found
case correctly before touching the partition state.
Fixes: be61da938576 ("firmware: arm_ffa: Allow multiple UUIDs per partition to register SRI callback")
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 2e9820395162..7bf8555c09da 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1209,7 +1209,7 @@ static int
ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
void *cb_data, bool is_registration)
{
- struct ffa_dev_part_info *partition = NULL, *tmp;
+ struct ffa_dev_part_info *partition = NULL;
struct list_head *phead;
bool cb_valid;
@@ -1222,11 +1222,11 @@ ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
return -EINVAL;
}
- list_for_each_entry_safe(partition, tmp, phead, node)
+ list_for_each_entry(partition, phead, node)
if (partition->dev == dev)
break;
- if (!partition) {
+ if (&partition->node == phead) {
pr_err("%s: No such partition ID 0x%x\n", __func__, dev->vm_id);
return -EINVAL;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2 10/11] firmware: arm_ffa: Snapshot notifier callbacks under lock
From: Sudeep Holla @ 2026-04-28 18:33 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel; +Cc: Jens Wiklander, Sudeep Holla
In-Reply-To: <20260428-ffa_fixes-v2-0-8595ae450034@kernel.org>
Both notification handlers currently look up a notifier callback under
notify_lock, drop the lock, and then dereference the returned
notifier entry. A concurrent unregister can delete and free that
entry in the gap, leaving the handler to dereference stale memory.
Copy the callback pointer and callback data while notify_lock is
still held and invoke the callback only after the lock is dropped.
This keeps the existing callback execution model while removing the
use-after-free window in both the framework and non-framework
notification paths.
Fixes: 285a5ea0f542 ("firmware: arm_ffa: Add support for handling framework notifications")
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 35 +++++++++++++++++++++++------------
1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 9181cc752ce1..2e9820395162 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1465,20 +1465,25 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
{
+ ffa_notifier_cb cb;
+ void *cb_data;
int notify_id;
- struct notifier_cb_info *cb_info = NULL;
for (notify_id = 0; notify_id <= FFA_MAX_NOTIFICATIONS && bitmap;
notify_id++, bitmap >>= 1) {
if (!(bitmap & 1))
continue;
- read_lock(&drv_info->notify_lock);
- cb_info = notifier_hnode_get_by_type(notify_id, type);
- read_unlock(&drv_info->notify_lock);
+ scoped_guard(read_lock, &drv_info->notify_lock) {
+ struct notifier_cb_info *cb_info;
+
+ cb_info = notifier_hnode_get_by_type(notify_id, type);
+ cb = cb_info ? cb_info->cb : NULL;
+ cb_data = cb_info ? cb_info->cb_data : NULL;
+ }
- if (cb_info && cb_info->cb)
- cb_info->cb(notify_id, cb_info->cb_data);
+ if (cb)
+ cb(notify_id, cb_data);
}
}
@@ -1486,9 +1491,10 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
{
void *buf;
uuid_t uuid;
+ void *fwk_cb_data;
int notify_id = 0, target;
+ ffa_fwk_notifier_cb fwk_cb;
struct ffa_indirect_msg_hdr *msg;
- struct notifier_cb_info *cb_info = NULL;
size_t min_offset = offsetof(struct ffa_indirect_msg_hdr, uuid);
/* Only one framework notification defined and supported for now */
@@ -1524,12 +1530,17 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
ffa_rx_release();
}
- read_lock(&drv_info->notify_lock);
- cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target, &uuid);
- read_unlock(&drv_info->notify_lock);
+ scoped_guard(read_lock, &drv_info->notify_lock) {
+ struct notifier_cb_info *cb_info;
+
+ cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target,
+ &uuid);
+ fwk_cb = cb_info ? cb_info->fwk_cb : NULL;
+ fwk_cb_data = cb_info ? cb_info->cb_data : NULL;
+ }
- if (cb_info && cb_info->fwk_cb)
- cb_info->fwk_cb(notify_id, cb_info->cb_data, buf);
+ if (fwk_cb)
+ fwk_cb(notify_id, fwk_cb_data, buf);
kfree(buf);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v5 0/8] unwind, arm64: add sframe unwinder for kernel
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
Implement a generic kernel sframe-based [1] unwinder. The main goal is
to improve reliable stacktrace on arm64 by unwinding across exception
boundaries.
On x86, the ORC unwinder provides reliable stacktrace through similar
methodology, but arm64 lacks the necessary support from objtool to
create ORC unwind tables.
Currently, there's already a sframe unwinder proposed for userspace: [2].
To maintain common definitions and algorithms for sframe lookup, a
substantial portion of this patch series aims to refactor the sframe
lookup code to support both kernel and userspace sframe sections.
Currently, only GNU Binutils support sframe. This series relies on the
Sframe V3 format, which is supported in binutils 2.46.
These patches are based on Steven Rostedt's sframe/core branch [3],
which is and aggregation of existing work done for x86 sframe userspace
unwind, and contains [2]. This branch is, in turn, based on Linux
v7.0-rc3. This full series (applied to the sframe/core branch) is
available on github: [4].
Ref:
[1]: https://sourceware.org/binutils/docs/sframe-spec.html
[2]: https://lore.kernel.org/lkml/20260127150554.2760964-1-jremus@linux.ibm.com/
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git/log/?h=sframe/core
[4]: https://github.com/dylanbhatch/linux/tree/sframe-v5
Changes since v4:
- (Jens) Fix some minor nits.
- Handle .init.text and .exit.text in function address validation.
Changes since v3:
- (Jens) Clean up patch summaries.
- (Jens) Rename SFRAME_LOOKUP -> UNWIND_SFRAME_LOOKUP to fit existing
naming convention.
- (Randy) Correct typo errors in new config options.
- (Jens) Move unwind types to a new unwind_types.h to match their
usage.
- (Jens) Update KERNEL_[COPY|GET] to use label-based error handling
like their userspace counterparts.
- (Jens) Rename SFRAME_UNWINDER -> HAVE_UNWIND_KERNEL_SFRAME and
ARCH_SUPPORTS_SFRAME_UNWINDER -> ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
to match existing naming convention.
- (Jens) Move HAVE_UNWIND_KERNEL_SFRAME config option to arch/Kconfig.
- (Jens) Rename/move extern definitions of __[start|end]_sframe into
include/asm-generic/sections.h.
- (Jens) Fix up CFI annotations at kernel entry.
- (Jens) Fix error path for unsorted FDE lookup.
- (Jens) Zero-out module sframe_section before init.
- (Jens) For SFRAME_VALIDATION, use an arch-specific function-address
validation helper so that .rodata.text can be correctly handled on
arm64 vmlinux.
- (Jens) Fixup and better comment kernel stacktrace code.
Changes since v2:
The biggest change from v2 is the switch from adding a dedicated,
in-kernel sframe-lookup library, to refactoring/using the existing
library developed by Josh, Jens, and Steve. Consequently, this series
now depends on Sframe V3, though this upgrade would likely have been
necessary anyway. Below is a full accounting of the changes since v2.
- (Josh) Add stricter reliability checks during unwind.
- (Puranjay, Indu, Jens) Update to use a common sframe library with
userpace unwind, thus resolving the need to support
SFRAME_F_FDE_FUNC_START_PCREL, added in binutils 2.45.
- (Jens) Add check for sframe V3, thus resolving the prior need for V2
and SFRAME_F_FDE_FUNC_START_PCREL support.
- (Will) Add ARCH_SUPPORTS_SFRAME_UNWINDER, remove SFRAME_UNWIND_TABLE
- (Indu) add support for unsorted FDE tables, allowing for module
sframe lookups.
- (Mark) Prefer frame-pointer unwind when possible, for better
performance.
- Simplify compile-time logic, adding stubbs when necessary.
- Add support for in-kernel SFRAME_VALIDATION.
- Rebase onto core/sframe (with v7.0-rc3 base)
Dylan Hatch (7):
sframe: Allow kernelspace sframe sections
arm64, unwind: build kernel with sframe V3 info
sframe: Provide PC lookup for vmlinux .sframe section
sframe: Allow unsorted FDEs
arm64/module, sframe: Add sframe support for modules
sframe: Introduce in-kernel SFRAME_VALIDATION
unwind: arm64: Use sframe to unwind interrupt frames
Weinan Liu (1):
arm64: entry: add unwind info for various kernel entries
MAINTAINERS | 3 +-
Makefile | 8 +
arch/Kconfig | 27 +-
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/module.h | 6 +
arch/arm64/include/asm/sections.h | 1 +
arch/arm64/include/asm/stacktrace/common.h | 6 +
arch/arm64/include/asm/unwind_sframe.h | 55 +++
arch/arm64/kernel/entry.S | 23 +
arch/arm64/kernel/module.c | 8 +
arch/arm64/kernel/setup.c | 2 +
arch/arm64/kernel/stacktrace.c | 246 ++++++++++-
arch/arm64/kernel/vdso/Makefile | 2 +-
arch/arm64/kernel/vmlinux.lds.S | 2 +
.../{unwind_user_sframe.h => unwind_sframe.h} | 6 +-
arch/x86/include/asm/unwind_user.h | 12 +-
include/asm-generic/sections.h | 4 +
include/asm-generic/vmlinux.lds.h | 15 +
include/linux/sframe.h | 67 ++-
include/linux/unwind_types.h | 46 ++
include/linux/unwind_user_types.h | 41 --
kernel/unwind/Makefile | 2 +-
kernel/unwind/sframe.c | 410 ++++++++++++++----
kernel/unwind/user.c | 41 +-
24 files changed, 827 insertions(+), 207 deletions(-)
create mode 100644 arch/arm64/include/asm/unwind_sframe.h
rename arch/x86/include/asm/{unwind_user_sframe.h => unwind_sframe.h} (50%)
create mode 100644 include/linux/unwind_types.h
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply
* [PATCH v5 2/8] arm64, unwind: build kernel with sframe V3 info
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
Build with -Wa,--gsframe-3 flags to generate a .sframe section. This
will be used for in-kernel reliable stacktrace in cases where the frame
pointer alone is insufficient.
Currently, the sframe format only supports arm64, x86_64 and s390x
architectures.
Signed-off-by: Weinan Liu <wnliu@google.com>
Reviewed-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
MAINTAINERS | 1 +
Makefile | 8 ++++++++
arch/Kconfig | 21 +++++++++++++++++++++
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/unwind_sframe.h | 8 ++++++++
arch/arm64/kernel/vdso/Makefile | 2 +-
include/asm-generic/sections.h | 4 ++++
include/asm-generic/vmlinux.lds.h | 15 +++++++++++++++
8 files changed, 59 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/unwind_sframe.h
diff --git a/MAINTAINERS b/MAINTAINERS
index cfc7dec88da4..a7d75f9cb5f4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27561,6 +27561,7 @@ STACK UNWINDING
M: Josh Poimboeuf <jpoimboe@kernel.org>
M: Steven Rostedt <rostedt@goodmis.org>
S: Maintained
+F: arch/*/include/asm/unwind_sframe.h
F: include/linux/sframe.h
F: include/linux/unwind*.h
F: kernel/unwind/
diff --git a/Makefile b/Makefile
index 2b15f0b4a0cb..6c94a5257679 100644
--- a/Makefile
+++ b/Makefile
@@ -1110,6 +1110,14 @@ endif
# Ensure compilers do not transform certain loops into calls to wcslen()
KBUILD_CFLAGS += -fno-builtin-wcslen
+# build with sframe table
+ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+CC_FLAGS_SFRAME := -Wa,--gsframe-3
+KBUILD_CFLAGS += $(CC_FLAGS_SFRAME)
+KBUILD_AFLAGS += $(CC_FLAGS_SFRAME)
+export CC_FLAGS_SFRAME
+endif
+
# change __FILE__ to the relative path to the source directory
ifdef building_out_of_srctree
KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=
diff --git a/arch/Kconfig b/arch/Kconfig
index d7caf2e245ce..8d27b3249e7a 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -520,6 +520,27 @@ config SFRAME_VALIDATION
If unsure, say N.
+config ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
+ bool
+ help
+ An architecture can select this if it enables the SFrame (Simple
+ Frame) unwinder for unwinding kernel stack traces. It uses an unwind
+ table that is directly generated by the toolchain based on DWARF CFI
+ information.
+
+config HAVE_UNWIND_KERNEL_SFRAME
+ bool "Sframe unwinder"
+ depends on AS_SFRAME3
+ depends on 64BIT
+ depends on ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
+ select UNWIND_SFRAME_LOOKUP
+ help
+ This option enables the SFrame (Simple Frame) unwinder for unwinding
+ kernel stack traces. It uses unwind an table that is directly
+ generated by the toolchain based on DWARF CFI information. In
+ practice, this can provide more reliable stacktrace results than
+ unwinding with frame pointers alone.
+
config HAVE_PERF_REGS
bool
help
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 38dba5f7e4d2..f7ae8eaaadc4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -112,6 +112,7 @@ config ARM64
select ARCH_SUPPORTS_SCHED_SMT
select ARCH_SUPPORTS_SCHED_CLUSTER
select ARCH_SUPPORTS_SCHED_MC
+ select ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
select ARCH_WANT_DEFAULT_BPF_JIT
diff --git a/arch/arm64/include/asm/unwind_sframe.h b/arch/arm64/include/asm/unwind_sframe.h
new file mode 100644
index 000000000000..876412881196
--- /dev/null
+++ b/arch/arm64/include/asm/unwind_sframe.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_UNWIND_SFRAME_H
+#define _ASM_ARM64_UNWIND_SFRAME_H
+
+#define SFRAME_REG_SP 31
+#define SFRAME_REG_FP 29
+
+#endif /* _ASM_ARM64_UNWIND_SFRAME_H */
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..c60ef921956f 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -38,7 +38,7 @@ ccflags-y += -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
$(RANDSTRUCT_CFLAGS) $(KSTACK_ERASE_CFLAGS) \
$(GCC_PLUGINS_CFLAGS) \
- $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
+ $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) $(CC_FLAGS_SFRAME) \
-Wmissing-prototypes -Wmissing-declarations
CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 0755bc39b0d8..336d27011a58 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -31,6 +31,7 @@
* __irqentry_text_start, __irqentry_text_end
* __softirqentry_text_start, __softirqentry_text_end
* __start_opd, __end_opd
+ * __start_sframe, __end_sframe
*/
extern char _text[], _stext[], _etext[];
extern char _data[], _sdata[], _edata[];
@@ -53,6 +54,9 @@ extern char __ctors_start[], __ctors_end[];
/* Start and end of .opd section - used for function descriptors. */
extern char __start_opd[], __end_opd[];
+/* Start and end of .sframe section - used for stack unwinding. */
+extern char __start_sframe[], __end_sframe[];
+
/* Start and end of instrumentation protected text section */
extern char __noinstr_text_start[], __noinstr_text_end[];
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1e1580febe4b..090da633db92 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -491,6 +491,8 @@
*(.rodata1) \
} \
\
+ SFRAME \
+ \
/* PCI quirks */ \
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
BOUNDED_SECTION_PRE_LABEL(.pci_fixup_early, _pci_fixups_early, __start, __end) \
@@ -911,6 +913,19 @@
#define TRACEDATA
#endif
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+#define SFRAME \
+ /* sframe */ \
+ .sframe : AT(ADDR(.sframe) - LOAD_OFFSET) { \
+ __start_sframe = .; \
+ KEEP(*(.sframe)) \
+ KEEP(*(.init.sframe)) \
+ __end_sframe = .; \
+ }
+#else
+#define SFRAME
+#endif
+
#ifdef CONFIG_PRINTK_INDEX
#define PRINTK_INDEX \
.printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) { \
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 1/8] sframe: Allow kernelspace sframe sections
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
Generalize the sframe lookup code to support kernelspace sections. This
is done by defining a SFRAME_LOOKUP option that can be activated
separate from HAVE_UNWIND_USER_SFRAME, as there will be other client to
this library than just userspace unwind.
Sframe section location is now tracked in a separate sec_type field to
determine whether user-access functions are necessary to read the sframe
data. Relevant type delarations are moved and renamed to reflect the
non-user sframe support.
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
MAINTAINERS | 2 +-
arch/Kconfig | 4 +
.../{unwind_user_sframe.h => unwind_sframe.h} | 6 +-
arch/x86/include/asm/unwind_user.h | 12 +-
include/linux/sframe.h | 48 ++--
include/linux/unwind_types.h | 46 +++
include/linux/unwind_user_types.h | 41 ---
kernel/unwind/Makefile | 2 +-
kernel/unwind/sframe.c | 270 ++++++++++++------
kernel/unwind/user.c | 41 +--
10 files changed, 293 insertions(+), 179 deletions(-)
rename arch/x86/include/asm/{unwind_user_sframe.h => unwind_sframe.h} (50%)
create mode 100644 include/linux/unwind_types.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 8c46465ee7a9..cfc7dec88da4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27557,7 +27557,7 @@ F: Documentation/driver-api/uio-howto.rst
F: drivers/uio/
F: include/linux/uio_driver.h
-USERSPACE STACK UNWINDING
+STACK UNWINDING
M: Josh Poimboeuf <jpoimboe@kernel.org>
M: Steven Rostedt <rostedt@goodmis.org>
S: Maintained
diff --git a/arch/Kconfig b/arch/Kconfig
index f1ed8bc0806d..d7caf2e245ce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -486,6 +486,9 @@ config AS_SFRAME3
def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,-Wa$(comma)--gsframe-3)
select AS_SFRAME
+config UNWIND_SFRAME_LOOKUP
+ bool
+
config UNWIND_USER
bool
@@ -496,6 +499,7 @@ config HAVE_UNWIND_USER_FP
config HAVE_UNWIND_USER_SFRAME
bool
select UNWIND_USER
+ select UNWIND_SFRAME_LOOKUP
config SFRAME_VALIDATION
bool "Enable .sframe section debugging"
diff --git a/arch/x86/include/asm/unwind_user_sframe.h b/arch/x86/include/asm/unwind_sframe.h
similarity index 50%
rename from arch/x86/include/asm/unwind_user_sframe.h
rename to arch/x86/include/asm/unwind_sframe.h
index d828ae1a4aac..44d42e6ffde4 100644
--- a/arch/x86/include/asm/unwind_user_sframe.h
+++ b/arch/x86/include/asm/unwind_sframe.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_X86_UNWIND_USER_SFRAME_H
-#define _ASM_X86_UNWIND_USER_SFRAME_H
+#ifndef _ASM_X86_UNWIND_SFRAME_H
+#define _ASM_X86_UNWIND_SFRAME_H
#ifdef CONFIG_X86_64
@@ -9,4 +9,4 @@
#endif
-#endif /* _ASM_X86_UNWIND_USER_SFRAME_H */
+#endif /* _ASM_X86_UNWIND_SFRAME_H */
diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h
index ae46906c3b39..8fdab3581b86 100644
--- a/arch/x86/include/asm/unwind_user.h
+++ b/arch/x86/include/asm/unwind_user.h
@@ -55,30 +55,30 @@ static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum)
#define ARCH_INIT_USER_FP_FRAME(ws) \
.cfa = { \
- .rule = UNWIND_USER_CFA_RULE_FP_OFFSET,\
+ .rule = UNWIND_CFA_RULE_FP_OFFSET,\
.offset = 2*(ws), \
}, \
.ra = { \
- .rule = UNWIND_USER_RULE_CFA_OFFSET_DEREF,\
+ .rule = UNWIND_RULE_CFA_OFFSET_DEREF,\
.offset = -1*(ws), \
}, \
.fp = { \
- .rule = UNWIND_USER_RULE_CFA_OFFSET_DEREF,\
+ .rule = UNWIND_RULE_CFA_OFFSET_DEREF,\
.offset = -2*(ws), \
}, \
.outermost = false,
#define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \
.cfa = { \
- .rule = UNWIND_USER_CFA_RULE_SP_OFFSET,\
+ .rule = UNWIND_CFA_RULE_SP_OFFSET,\
.offset = 1*(ws), \
}, \
.ra = { \
- .rule = UNWIND_USER_RULE_CFA_OFFSET_DEREF,\
+ .rule = UNWIND_RULE_CFA_OFFSET_DEREF,\
.offset = -1*(ws), \
}, \
.fp = { \
- .rule = UNWIND_USER_RULE_RETAIN,\
+ .rule = UNWIND_RULE_RETAIN,\
}, \
.outermost = false,
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index b79c5ec09229..0cb2924367bc 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -3,37 +3,46 @@
#define _LINUX_SFRAME_H
#include <linux/mm_types.h>
+#include <linux/unwind_types.h>
#include <linux/srcu.h>
-#include <linux/unwind_user_types.h>
-#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+#ifdef CONFIG_UNWIND_SFRAME_LOOKUP
+
+enum sframe_sec_type {
+ SFRAME_KERNEL,
+ SFRAME_USER,
+};
struct sframe_section {
- struct rcu_head rcu;
+ struct rcu_head rcu;
#ifdef CONFIG_DYNAMIC_DEBUG
- const char *filename;
+ const char *filename;
#endif
- unsigned long sframe_start;
- unsigned long sframe_end;
- unsigned long text_start;
- unsigned long text_end;
-
- unsigned long fdes_start;
- unsigned long fres_start;
- unsigned long fres_end;
- unsigned int num_fdes;
-
- signed char ra_off;
- signed char fp_off;
+ enum sframe_sec_type sec_type;
+ unsigned long sframe_start;
+ unsigned long sframe_end;
+ unsigned long text_start;
+ unsigned long text_end;
+
+ unsigned long fdes_start;
+ unsigned long fres_start;
+ unsigned long fres_end;
+ unsigned int num_fdes;
+
+ signed char ra_off;
+ signed char fp_off;
};
+#endif /* CONFIG_UNWIND_SFRAME_LOOKUP */
+
+#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+
#define INIT_MM_SFRAME .sframe_mt = MTREE_INIT(sframe_mt, 0),
extern void sframe_free_mm(struct mm_struct *mm);
extern int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
unsigned long text_start, unsigned long text_end);
extern int sframe_remove_section(unsigned long sframe_addr);
-extern int sframe_find(unsigned long ip, struct unwind_user_frame *frame);
static inline bool current_has_sframe(void)
{
@@ -42,6 +51,8 @@ static inline bool current_has_sframe(void)
return mm && !mtree_empty(&mm->sframe_mt);
}
+extern int sframe_find_user(unsigned long ip, struct unwind_frame *frame);
+
#else /* !CONFIG_HAVE_UNWIND_USER_SFRAME */
#define INIT_MM_SFRAME
@@ -52,9 +63,10 @@ static inline int sframe_add_section(unsigned long sframe_start, unsigned long s
return -ENOSYS;
}
static inline int sframe_remove_section(unsigned long sframe_addr) { return -ENOSYS; }
-static inline int sframe_find(unsigned long ip, struct unwind_user_frame *frame) { return -ENOSYS; }
static inline bool current_has_sframe(void) { return false; }
+static inline int sframe_find_user(unsigned long ip, struct unwind_frame *frame) { return -ENOSYS; }
+
#endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
#endif /* _LINUX_SFRAME_H */
diff --git a/include/linux/unwind_types.h b/include/linux/unwind_types.h
new file mode 100644
index 000000000000..08bcb0aa04aa
--- /dev/null
+++ b/include/linux/unwind_types.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_UNWIND_TYPES_H
+#define _LINUX_UNWIND_TYPES_H
+
+#define UNWIND_RULE_DEREF BIT(31)
+
+enum unwind_cfa_rule {
+ UNWIND_CFA_RULE_SP_OFFSET, /* CFA = SP + offset */
+ UNWIND_CFA_RULE_FP_OFFSET, /* CFA = FP + offset */
+ UNWIND_CFA_RULE_REG_OFFSET, /* CFA = reg + offset */
+ /* DEREF variants */
+ UNWIND_CFA_RULE_REG_OFFSET_DEREF = /* CFA = *(reg + offset) */
+ UNWIND_CFA_RULE_REG_OFFSET | UNWIND_RULE_DEREF,
+};
+
+struct unwind_cfa_rule_data {
+ enum unwind_cfa_rule rule;
+ s32 offset;
+ unsigned int regnum;
+};
+
+enum unwind_rule {
+ UNWIND_RULE_RETAIN, /* entity = entity */
+ UNWIND_RULE_CFA_OFFSET, /* entity = CFA + offset */
+ UNWIND_RULE_REG_OFFSET, /* entity = register + offset */
+ /* DEREF variants */
+ UNWIND_RULE_CFA_OFFSET_DEREF = /* entity = *(CFA + offset) */
+ UNWIND_RULE_CFA_OFFSET | UNWIND_RULE_DEREF,
+ UNWIND_RULE_REG_OFFSET_DEREF = /* entity = *(register + offset) */
+ UNWIND_RULE_REG_OFFSET | UNWIND_RULE_DEREF,
+};
+
+struct unwind_rule_data {
+ enum unwind_rule rule;
+ s32 offset;
+ unsigned int regnum;
+};
+
+struct unwind_frame {
+ struct unwind_cfa_rule_data cfa;
+ struct unwind_rule_data ra;
+ struct unwind_rule_data fp;
+ bool outermost;
+};
+
+#endif /* _LINUX_UNWIND_TYPES_H */
diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_types.h
index 059e5c76f2f3..646e5fb774db 100644
--- a/include/linux/unwind_user_types.h
+++ b/include/linux/unwind_user_types.h
@@ -27,47 +27,6 @@ struct unwind_stacktrace {
unsigned long *entries;
};
-#define UNWIND_USER_RULE_DEREF BIT(31)
-
-enum unwind_user_cfa_rule {
- UNWIND_USER_CFA_RULE_SP_OFFSET, /* CFA = SP + offset */
- UNWIND_USER_CFA_RULE_FP_OFFSET, /* CFA = FP + offset */
- UNWIND_USER_CFA_RULE_REG_OFFSET, /* CFA = reg + offset */
- /* DEREF variants */
- UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF = /* CFA = *(reg + offset) */
- UNWIND_USER_CFA_RULE_REG_OFFSET | UNWIND_USER_RULE_DEREF,
-};
-
-struct unwind_user_cfa_rule_data {
- enum unwind_user_cfa_rule rule;
- s32 offset;
- unsigned int regnum;
-};
-
-enum unwind_user_rule {
- UNWIND_USER_RULE_RETAIN, /* entity = entity */
- UNWIND_USER_RULE_CFA_OFFSET, /* entity = CFA + offset */
- UNWIND_USER_RULE_REG_OFFSET, /* entity = register + offset */
- /* DEREF variants */
- UNWIND_USER_RULE_CFA_OFFSET_DEREF = /* entity = *(CFA + offset) */
- UNWIND_USER_RULE_CFA_OFFSET | UNWIND_USER_RULE_DEREF,
- UNWIND_USER_RULE_REG_OFFSET_DEREF = /* entity = *(register + offset) */
- UNWIND_USER_RULE_REG_OFFSET | UNWIND_USER_RULE_DEREF,
-};
-
-struct unwind_user_rule_data {
- enum unwind_user_rule rule;
- s32 offset;
- unsigned int regnum;
-};
-
-struct unwind_user_frame {
- struct unwind_user_cfa_rule_data cfa;
- struct unwind_user_rule_data ra;
- struct unwind_user_rule_data fp;
- bool outermost;
-};
-
struct unwind_user_state {
unsigned long ip;
unsigned long sp;
diff --git a/kernel/unwind/Makefile b/kernel/unwind/Makefile
index 146038165865..c5f9f8124564 100644
--- a/kernel/unwind/Makefile
+++ b/kernel/unwind/Makefile
@@ -1,2 +1,2 @@
obj-$(CONFIG_UNWIND_USER) += user.o deferred.o
- obj-$(CONFIG_HAVE_UNWIND_USER_SFRAME) += sframe.o
+ obj-$(CONFIG_UNWIND_SFRAME_LOOKUP) += sframe.o
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index f24997e84e05..89dd8c5a6a10 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -12,8 +12,8 @@
#include <linux/mm.h>
#include <linux/string_helpers.h>
#include <linux/sframe.h>
-#include <asm/unwind_user_sframe.h>
-#include <linux/unwind_user_types.h>
+#include <linux/unwind_types.h>
+#include <asm/unwind_sframe.h>
#include "sframe.h"
#include "sframe_debug.h"
@@ -44,8 +44,6 @@ struct sframe_fre_internal {
unsigned char dw_size;
};
-DEFINE_STATIC_SRCU(sframe_srcu);
-
static __always_inline unsigned char fre_type_to_size(unsigned char fre_type)
{
if (fre_type > 2)
@@ -60,6 +58,77 @@ static __always_inline unsigned char dataword_size_enum_to_size(unsigned char da
return 1 << dataword_size;
}
+#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+
+DEFINE_STATIC_SRCU(sframe_srcu);
+
+#define UNSAFE_USER_COPY(to, from, size, label) \
+ unsafe_copy_from_user(to, (void __user *)from, size, label)
+
+#define UNSAFE_USER_GET(to, from, type, label) \
+ unsafe_get_user(to, (type __user *)from, label)
+
+#else /* !CONFIG_HAVE_UNWIND_USER_SFRAME */
+
+#define UNSAFE_USER_COPY(to, from, size, label) do { \
+ (void)to; (void)from; (void)size; \
+ goto label; \
+} while (0)
+
+#define UNSAFE_USER_GET(to, from, type, label) do { \
+ (void)to; (void)from; \
+ goto label; \
+} while (0)
+
+#endif /* !CONFIG_HAVE_UNWIND_USER_SFRAME */
+
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+#define KERNEL_COPY(to, from, size, label) memcpy(to, (void *)from, size)
+#define KERNEL_GET(to, from, type, label) ({ (to) = *(type *)(from); })
+
+#else /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
+#define KERNEL_COPY(to, from, size, label) do { \
+ (void)(to); (void)(from); (void)size; \
+ goto label; \
+} while (0)
+
+#define KERNEL_GET(to, from, type, label) do { \
+ (void)(to); (void)(from); \
+ goto label; \
+} while (0)
+
+#endif /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
+#define DATA_COPY(sec, to, from, size, label) \
+({ \
+ switch (sec->sec_type) { \
+ case SFRAME_KERNEL: \
+ KERNEL_COPY(to, from, size, label); \
+ break; \
+ case SFRAME_USER: \
+ UNSAFE_USER_COPY(to, from, size, label); \
+ break; \
+ default: \
+ goto label; \
+ } \
+})
+
+#define DATA_GET(sec, to, from, type, label) \
+({ \
+ switch (sec->sec_type) { \
+ case SFRAME_KERNEL: \
+ KERNEL_GET(to, from, type, label); \
+ break; \
+ case SFRAME_USER: \
+ UNSAFE_USER_GET(to, from, type, label); \
+ break; \
+ default: \
+ goto label; \
+ } \
+})
+
static __always_inline int __read_fde(struct sframe_section *sec,
unsigned int fde_num,
struct sframe_fde_internal *fde)
@@ -69,8 +138,8 @@ static __always_inline int __read_fde(struct sframe_section *sec,
struct sframe_fda_v3 _fda;
fde_addr = sec->fdes_start + (fde_num * sizeof(struct sframe_fde_v3));
- unsafe_copy_from_user(&_fde, (void __user *)fde_addr,
- sizeof(struct sframe_fde_v3), Efault);
+ DATA_COPY(sec, &_fde, fde_addr,
+ sizeof(struct sframe_fde_v3), Efault);
func_addr = fde_addr + _fde.func_start_off;
if (func_addr < sec->text_start || func_addr > sec->text_end)
@@ -79,8 +148,8 @@ static __always_inline int __read_fde(struct sframe_section *sec,
fda_addr = sec->fres_start + _fde.fres_off;
if (fda_addr + sizeof(struct sframe_fda_v3) > sec->fres_end)
return -EINVAL;
- unsafe_copy_from_user(&_fda, (void __user *)fda_addr,
- sizeof(struct sframe_fda_v3), Efault);
+ DATA_COPY(sec, &_fda, fda_addr,
+ sizeof(struct sframe_fda_v3), Efault);
fde->func_addr = func_addr;
fde->func_size = _fde.func_size;
@@ -102,21 +171,21 @@ static __always_inline int __find_fde(struct sframe_section *sec,
struct sframe_fde_internal *fde)
{
unsigned long func_addr_low = 0, func_addr_high = ULONG_MAX;
- struct sframe_fde_v3 __user *first, *low, *high, *found = NULL;
+ struct sframe_fde_v3 *first, *low, *high, *found = NULL;
int ret;
- first = (void __user *)sec->fdes_start;
+ first = (void *)sec->fdes_start;
low = first;
high = first + sec->num_fdes - 1;
while (low <= high) {
- struct sframe_fde_v3 __user *mid;
+ struct sframe_fde_v3 *mid;
s64 func_off;
unsigned long func_addr;
mid = low + ((high - low) / 2);
- unsafe_get_user(func_off, (s64 __user *)mid, Efault);
+ DATA_GET(sec, func_off, mid, s64, Efault);
func_addr = (unsigned long)mid + func_off;
if (ip >= func_addr) {
@@ -154,47 +223,47 @@ static __always_inline int __find_fde(struct sframe_section *sec,
return -EFAULT;
}
-#define ____UNSAFE_GET_USER_INC(to, from, type, label) \
+#define ____GET_INC(sec, to, from, type, label) \
({ \
type __to; \
- unsafe_get_user(__to, (type __user *)from, label); \
+ DATA_GET(sec, __to, from, type, label); \
from += sizeof(__to); \
to = __to; \
})
-#define __UNSAFE_GET_USER_INC(to, from, size, label, u_or_s) \
+#define __GET_INC(sec, to, from, size, label, u_or_s) \
({ \
switch (size) { \
case 1: \
- ____UNSAFE_GET_USER_INC(to, from, u_or_s##8, label); \
+ ____GET_INC(sec, to, from, u_or_s##8, label); \
break; \
case 2: \
- ____UNSAFE_GET_USER_INC(to, from, u_or_s##16, label); \
+ ____GET_INC(sec, to, from, u_or_s##16, label); \
break; \
case 4: \
- ____UNSAFE_GET_USER_INC(to, from, u_or_s##32, label); \
+ ____GET_INC(sec, to, from, u_or_s##32, label); \
break; \
default: \
return -EFAULT; \
} \
})
-#define UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label) \
- __UNSAFE_GET_USER_INC(to, from, size, label, u)
+#define GET_UNSIGNED_INC(sec, to, from, size, label) \
+ __GET_INC(sec, to, from, size, label, u)
-#define UNSAFE_GET_USER_SIGNED_INC(to, from, size, label) \
- __UNSAFE_GET_USER_INC(to, from, size, label, s)
+#define GET_SIGNED_INC(sec, to, from, size, label) \
+ __GET_INC(sec, to, from, size, label, s)
-#define UNSAFE_GET_USER_INC(to, from, size, label) \
- _Generic(to, \
- u8 : UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \
- u16 : UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \
- u32 : UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \
- u64 : UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label), \
- s8 : UNSAFE_GET_USER_SIGNED_INC(to, from, size, label), \
- s16 : UNSAFE_GET_USER_SIGNED_INC(to, from, size, label), \
- s32 : UNSAFE_GET_USER_SIGNED_INC(to, from, size, label), \
- s64 : UNSAFE_GET_USER_SIGNED_INC(to, from, size, label))
+#define GET_INC(sec, to, from, size, label) \
+ _Generic(to, \
+ u8 : GET_UNSIGNED_INC(sec, to, from, size, label), \
+ u16 : GET_UNSIGNED_INC(sec, to, from, size, label), \
+ u32 : GET_UNSIGNED_INC(sec, to, from, size, label), \
+ u64 : GET_UNSIGNED_INC(sec, to, from, size, label), \
+ s8 : GET_SIGNED_INC(sec, to, from, size, label), \
+ s16 : GET_SIGNED_INC(sec, to, from, size, label), \
+ s32 : GET_SIGNED_INC(sec, to, from, size, label), \
+ s64 : GET_SIGNED_INC(sec, to, from, size, label))
static __always_inline int
__read_regular_fre_datawords(struct sframe_section *sec,
@@ -207,19 +276,19 @@ __read_regular_fre_datawords(struct sframe_section *sec,
s32 cfa_off, ra_off, fp_off;
unsigned int cfa_regnum;
- UNSAFE_GET_USER_INC(cfa_off, cur, dataword_size, Efault);
+ GET_INC(sec, cfa_off, cur, dataword_size, Efault);
dataword_count--;
ra_off = sec->ra_off;
if (!ra_off && dataword_count) {
dataword_count--;
- UNSAFE_GET_USER_INC(ra_off, cur, dataword_size, Efault);
+ GET_INC(sec, ra_off, cur, dataword_size, Efault);
}
fp_off = sec->fp_off;
if (!fp_off && dataword_count) {
dataword_count--;
- UNSAFE_GET_USER_INC(fp_off, cur, dataword_size, Efault);
+ GET_INC(sec, fp_off, cur, dataword_size, Efault);
}
if (dataword_count)
@@ -255,17 +324,17 @@ __read_flex_fde_fre_datawords(struct sframe_section *sec,
if (dataword_count < 2)
return -EFAULT;
- UNSAFE_GET_USER_INC(cfa_ctl, cur, dataword_size, Efault);
- UNSAFE_GET_USER_INC(cfa_off, cur, dataword_size, Efault);
+ GET_INC(sec, cfa_ctl, cur, dataword_size, Efault);
+ GET_INC(sec, cfa_off, cur, dataword_size, Efault);
dataword_count -= 2;
ra_off = sec->ra_off;
ra_ctl = ra_off ? 2 : 0; /* regnum=0, deref_p=(ra_off != 0), reg_p=0 */
if (dataword_count >= 2) {
- UNSAFE_GET_USER_INC(ra_ctl, cur, dataword_size, Efault);
+ GET_INC(sec, ra_ctl, cur, dataword_size, Efault);
dataword_count--;
if (ra_ctl) {
- UNSAFE_GET_USER_INC(ra_off, cur, dataword_size, Efault);
+ GET_INC(sec, ra_off, cur, dataword_size, Efault);
dataword_count--;
} else {
/* Padding RA location info */
@@ -276,10 +345,10 @@ __read_flex_fde_fre_datawords(struct sframe_section *sec,
fp_off = sec->fp_off;
fp_ctl = fp_off ? 2 : 0; /* regnum=0, deref_p=(fp_off != 0), reg_p=0 */
if (dataword_count >= 2) {
- UNSAFE_GET_USER_INC(fp_ctl, cur, dataword_size, Efault);
+ GET_INC(sec, fp_ctl, cur, dataword_size, Efault);
dataword_count--;
if (fp_ctl) {
- UNSAFE_GET_USER_INC(fp_off, cur, dataword_size, Efault);
+ GET_INC(sec, fp_off, cur, dataword_size, Efault);
dataword_count--;
} else {
/* Padding FP location info */
@@ -353,11 +422,11 @@ static __always_inline int __read_fre(struct sframe_section *sec,
if (fre_addr + addr_size + 1 > sec->fres_end)
return -EFAULT;
- UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault);
+ GET_INC(sec, ip_off, cur, addr_size, Efault);
if (fde_pctype == SFRAME_FDE_PCTYPE_INC && ip_off > fde->func_size)
return -EFAULT;
- UNSAFE_GET_USER_INC(info, cur, 1, Efault);
+ GET_INC(sec, info, cur, 1, Efault);
dataword_count = SFRAME_V3_FRE_DATAWORD_COUNT(info);
dataword_size = dataword_size_enum_to_size(SFRAME_V3_FRE_DATAWORD_SIZE(info));
if (!dataword_size)
@@ -380,7 +449,7 @@ static __always_inline int __read_fre(struct sframe_section *sec,
}
static __always_inline int
-sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
+sframe_init_cfa_rule_data(struct unwind_cfa_rule_data *cfa_rule_data,
u32 ctlword, s32 offset)
{
bool deref_p = SFRAME_V3_FLEX_FDE_CTLWORD_DEREF_P(ctlword);
@@ -391,13 +460,13 @@ sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
switch (regnum) {
case SFRAME_REG_SP:
- cfa_rule_data->rule = UNWIND_USER_CFA_RULE_SP_OFFSET;
+ cfa_rule_data->rule = UNWIND_CFA_RULE_SP_OFFSET;
break;
case SFRAME_REG_FP:
- cfa_rule_data->rule = UNWIND_USER_CFA_RULE_FP_OFFSET;
+ cfa_rule_data->rule = UNWIND_CFA_RULE_FP_OFFSET;
break;
default:
- cfa_rule_data->rule = UNWIND_USER_CFA_RULE_REG_OFFSET;
+ cfa_rule_data->rule = UNWIND_CFA_RULE_REG_OFFSET;
cfa_rule_data->regnum = regnum;
}
} else {
@@ -405,7 +474,7 @@ sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
}
if (deref_p)
- cfa_rule_data->rule |= UNWIND_USER_RULE_DEREF;
+ cfa_rule_data->rule |= UNWIND_RULE_DEREF;
cfa_rule_data->offset = offset;
@@ -413,27 +482,27 @@ sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
}
static __always_inline void
-sframe_init_rule_data(struct unwind_user_rule_data *rule_data,
+sframe_init_rule_data(struct unwind_rule_data *rule_data,
u32 ctlword, s32 offset)
{
bool deref_p = SFRAME_V3_FLEX_FDE_CTLWORD_DEREF_P(ctlword);
bool reg_p = SFRAME_V3_FLEX_FDE_CTLWORD_REG_P(ctlword);
if (!ctlword && !offset) {
- rule_data->rule = UNWIND_USER_RULE_RETAIN;
+ rule_data->rule = UNWIND_RULE_RETAIN;
return;
}
if (reg_p) {
unsigned int regnum = SFRAME_V3_FLEX_FDE_CTLWORD_REGNUM(ctlword);
- rule_data->rule = UNWIND_USER_RULE_REG_OFFSET;
+ rule_data->rule = UNWIND_RULE_REG_OFFSET;
rule_data->regnum = regnum;
} else {
- rule_data->rule = UNWIND_USER_RULE_CFA_OFFSET;
+ rule_data->rule = UNWIND_RULE_CFA_OFFSET;
}
if (deref_p)
- rule_data->rule |= UNWIND_USER_RULE_DEREF;
+ rule_data->rule |= UNWIND_RULE_DEREF;
rule_data->offset = offset;
}
@@ -441,7 +510,7 @@ sframe_init_rule_data(struct unwind_user_rule_data *rule_data,
static __always_inline int __find_fre(struct sframe_section *sec,
struct sframe_fde_internal *fde,
unsigned long ip,
- struct unwind_user_frame *frame)
+ struct unwind_frame *frame)
{
unsigned char fde_pctype = SFRAME_V3_FDE_PCTYPE(fde->info);
struct sframe_fre_internal *fre, *prev_fre = NULL;
@@ -501,40 +570,18 @@ static __always_inline int __find_fre(struct sframe_section *sec,
return 0;
}
-int sframe_find(unsigned long ip, struct unwind_user_frame *frame)
+static __always_inline int __sframe_find(struct sframe_section *sec,
+ unsigned long ip,
+ struct unwind_frame *frame)
{
- struct mm_struct *mm = current->mm;
- struct sframe_section *sec;
struct sframe_fde_internal fde;
int ret;
- if (!mm)
- return -EINVAL;
-
- guard(srcu)(&sframe_srcu);
-
- sec = mtree_load(&mm->sframe_mt, ip);
- if (!sec)
- return -EINVAL;
-
- if (!user_read_access_begin((void __user *)sec->sframe_start,
- sec->sframe_end - sec->sframe_start))
- return -EFAULT;
-
ret = __find_fde(sec, ip, &fde);
if (ret)
- goto end;
-
- ret = __find_fre(sec, &fde, ip, frame);
-end:
- user_read_access_end();
-
- if (ret == -EFAULT) {
- dbg_sec("removing bad .sframe section\n");
- WARN_ON_ONCE(sframe_remove_section(sec->sframe_start));
- }
+ return ret;
- return ret;
+ return __find_fre(sec, &fde, ip, frame);
}
#ifdef CONFIG_SFRAME_VALIDATION
@@ -657,20 +704,23 @@ static int sframe_validate_section(struct sframe_section *sec) { return 0; }
#endif /* !CONFIG_SFRAME_VALIDATION */
-static void free_section(struct sframe_section *sec)
-{
- dbg_free(sec);
- kfree(sec);
-}
-
static int sframe_read_header(struct sframe_section *sec)
{
unsigned long header_end, fdes_start, fdes_end, fres_start, fres_end;
struct sframe_header shdr;
unsigned int num_fdes;
- if (copy_from_user(&shdr, (void __user *)sec->sframe_start, sizeof(shdr))) {
- dbg_sec("header usercopy failed\n");
+ switch (sec->sec_type) {
+ case SFRAME_USER:
+ if (copy_from_user(&shdr, (void __user *)sec->sframe_start, sizeof(shdr))) {
+ dbg_sec("header usercopy failed\n");
+ return -EFAULT;
+ }
+ break;
+ case SFRAME_KERNEL:
+ shdr = *(struct sframe_header *)sec->sframe_start;
+ break;
+ default:
return -EFAULT;
}
@@ -717,6 +767,45 @@ static int sframe_read_header(struct sframe_section *sec)
return 0;
}
+#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+
+int sframe_find_user(unsigned long ip, struct unwind_frame *frame)
+{
+ struct mm_struct *mm = current->mm;
+ struct sframe_section *sec;
+ int ret;
+
+ if (!mm)
+ return -EINVAL;
+
+ guard(srcu)(&sframe_srcu);
+
+ sec = mtree_load(&mm->sframe_mt, ip);
+ if (!sec)
+ return -EINVAL;
+
+ if (!user_read_access_begin((void __user *)sec->sframe_start,
+ sec->sframe_end - sec->sframe_start))
+ return -EFAULT;
+
+ ret = __sframe_find(sec, ip, frame);
+
+ user_read_access_end();
+
+ if (ret == -EFAULT) {
+ dbg_sec("removing bad .sframe section\n");
+ WARN_ON_ONCE(sframe_remove_section(sec->sframe_start));
+ }
+
+ return ret;
+}
+
+static void free_section(struct sframe_section *sec)
+{
+ dbg_free(sec);
+ kfree(sec);
+}
+
int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
unsigned long text_start, unsigned long text_end)
{
@@ -753,6 +842,7 @@ int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
if (!sec)
return -ENOMEM;
+ sec->sec_type = SFRAME_USER;
sec->sframe_start = sframe_start;
sec->sframe_end = sframe_end;
sec->text_start = text_start;
@@ -838,3 +928,5 @@ void sframe_free_mm(struct mm_struct *mm)
mtree_destroy(&mm->sframe_mt);
}
+
+#endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c
index eb7d9489f671..9e57dd79559a 100644
--- a/kernel/unwind/user.c
+++ b/kernel/unwind/user.c
@@ -8,6 +8,7 @@
#include <linux/unwind_user.h>
#include <linux/uaccess.h>
#include <linux/sframe.h>
+#include <linux/unwind_types.h>
#define for_each_user_frame(state) \
for (unwind_user_start(state); !(state)->done; unwind_user_next(state))
@@ -28,7 +29,7 @@ get_user_word(unsigned long *word, unsigned long base, int off, unsigned int ws)
}
static int unwind_user_next_common(struct unwind_user_state *state,
- const struct unwind_user_frame *frame)
+ const struct unwind_frame *frame)
{
unsigned long cfa, fp, ra;
@@ -40,16 +41,16 @@ static int unwind_user_next_common(struct unwind_user_state *state,
/* Get the Canonical Frame Address (CFA) */
switch (frame->cfa.rule) {
- case UNWIND_USER_CFA_RULE_SP_OFFSET:
+ case UNWIND_CFA_RULE_SP_OFFSET:
cfa = state->sp;
break;
- case UNWIND_USER_CFA_RULE_FP_OFFSET:
+ case UNWIND_CFA_RULE_FP_OFFSET:
if (state->fp < state->sp)
return -EINVAL;
cfa = state->fp;
break;
- case UNWIND_USER_CFA_RULE_REG_OFFSET:
- case UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF:
+ case UNWIND_CFA_RULE_REG_OFFSET:
+ case UNWIND_CFA_RULE_REG_OFFSET_DEREF:
if (!state->topmost || unwind_user_get_reg(&cfa, frame->cfa.regnum))
return -EINVAL;
break;
@@ -58,7 +59,7 @@ static int unwind_user_next_common(struct unwind_user_state *state,
return -EINVAL;
}
cfa += frame->cfa.offset;
- if (frame->cfa.rule & UNWIND_USER_RULE_DEREF &&
+ if (frame->cfa.rule & UNWIND_RULE_DEREF &&
get_user_word(&cfa, cfa, 0, state->ws))
return -EINVAL;
@@ -76,16 +77,16 @@ static int unwind_user_next_common(struct unwind_user_state *state,
/* Get the Return Address (RA) */
switch (frame->ra.rule) {
- case UNWIND_USER_RULE_RETAIN:
+ case UNWIND_RULE_RETAIN:
if (!state->topmost || unwind_user_get_ra_reg(&ra))
return -EINVAL;
break;
/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
- case UNWIND_USER_RULE_CFA_OFFSET_DEREF:
+ case UNWIND_RULE_CFA_OFFSET_DEREF:
ra = cfa + frame->ra.offset;
break;
- case UNWIND_USER_RULE_REG_OFFSET:
- case UNWIND_USER_RULE_REG_OFFSET_DEREF:
+ case UNWIND_RULE_REG_OFFSET:
+ case UNWIND_RULE_REG_OFFSET_DEREF:
if (!state->topmost || unwind_user_get_reg(&ra, frame->ra.regnum))
return -EINVAL;
ra += frame->ra.offset;
@@ -94,21 +95,21 @@ static int unwind_user_next_common(struct unwind_user_state *state,
WARN_ON_ONCE(1);
return -EINVAL;
}
- if (frame->ra.rule & UNWIND_USER_RULE_DEREF &&
+ if (frame->ra.rule & UNWIND_RULE_DEREF &&
get_user_word(&ra, ra, 0, state->ws))
return -EINVAL;
/* Get the Frame Pointer (FP) */
switch (frame->fp.rule) {
- case UNWIND_USER_RULE_RETAIN:
+ case UNWIND_RULE_RETAIN:
fp = state->fp;
break;
/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
- case UNWIND_USER_RULE_CFA_OFFSET_DEREF:
+ case UNWIND_RULE_CFA_OFFSET_DEREF:
fp = cfa + frame->fp.offset;
break;
- case UNWIND_USER_RULE_REG_OFFSET:
- case UNWIND_USER_RULE_REG_OFFSET_DEREF:
+ case UNWIND_RULE_REG_OFFSET:
+ case UNWIND_RULE_REG_OFFSET_DEREF:
if (!state->topmost || unwind_user_get_reg(&fp, frame->fp.regnum))
return -EINVAL;
fp += frame->fp.offset;
@@ -117,7 +118,7 @@ static int unwind_user_next_common(struct unwind_user_state *state,
WARN_ON_ONCE(1);
return -EINVAL;
}
- if (frame->fp.rule & UNWIND_USER_RULE_DEREF &&
+ if (frame->fp.rule & UNWIND_RULE_DEREF &&
get_user_word(&fp, fp, 0, state->ws))
return -EINVAL;
@@ -133,13 +134,13 @@ static int unwind_user_next_fp(struct unwind_user_state *state)
struct pt_regs *regs = task_pt_regs(current);
if (state->topmost && unwind_user_at_function_start(regs)) {
- const struct unwind_user_frame fp_entry_frame = {
+ const struct unwind_frame fp_entry_frame = {
ARCH_INIT_USER_FP_ENTRY_FRAME(state->ws)
};
return unwind_user_next_common(state, &fp_entry_frame);
}
- const struct unwind_user_frame fp_frame = {
+ const struct unwind_frame fp_frame = {
ARCH_INIT_USER_FP_FRAME(state->ws)
};
return unwind_user_next_common(state, &fp_frame);
@@ -147,10 +148,10 @@ static int unwind_user_next_fp(struct unwind_user_state *state)
static int unwind_user_next_sframe(struct unwind_user_state *state)
{
- struct unwind_user_frame frame;
+ struct unwind_frame frame;
/* sframe expects the frame to be local storage */
- if (sframe_find(state->ip, &frame))
+ if (sframe_find_user(state->ip, &frame))
return -ENOENT;
return unwind_user_next_common(state, &frame);
}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 3/8] arm64: entry: add unwind info for various kernel entries
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
From: Weinan Liu <wnliu@google.com>
DWARF CFI (Call Frame Information) specifies how to recover the return
address and callee-saved registers at each PC in a given function.
Compilers are able to generate the CFI annotations when they compile
the code to assembly language. For handcrafted assembly, we need to
annotate them by hand.
Annotate minimal CFI to enable stacktracing using SFrame for kernel
exception entries through el1*_64_*() paths and irq entries through
call_on_irq_stack()
Signed-off-by: Weinan Liu <wnliu@google.com>
Suggested-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
arch/arm64/kernel/entry.S | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index f8018b5c1f9a..dc55b0b19cfa 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -30,6 +30,12 @@
#include <asm/asm-uaccess.h>
#include <asm/unistd.h>
+/*
+ * Do not generate .eh_frame. Only generate .debug_frame and optionally
+ * .sframe (via assembler option --gsframe[-N]).
+ */
+ .cfi_sections .debug_frame
+
.macro clear_gp_regs
.irp n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
mov x\n, xzr
@@ -575,7 +581,16 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label)
.if \el == 0
b ret_to_user
.else
+ /*
+ * Minimal DWARF CFI for unwinding across the call above.
+ * Enable unwinding for el1*_64_*() path only.
+ */
+ .cfi_startproc
+ .cfi_def_cfa_offset PT_REGS_SIZE
+ .cfi_offset 29, S_FP - PT_REGS_SIZE
+ .cfi_offset 30, S_LR - PT_REGS_SIZE
b ret_to_kernel
+ .cfi_endproc
.endif
SYM_CODE_END(el\el\ht\()_\regsize\()_\label)
.endm
@@ -872,6 +887,7 @@ NOKPROBE(ret_from_fork)
* Calls func(regs) using this CPU's irq stack and shadow irq stack.
*/
SYM_FUNC_START(call_on_irq_stack)
+ .cfi_startproc
save_and_disable_daif x9
#ifdef CONFIG_SHADOW_CALL_STACK
get_current_task x16
@@ -882,6 +898,9 @@ SYM_FUNC_START(call_on_irq_stack)
/* Create a frame record to save our LR and SP (implicit in FP) */
stp x29, x30, [sp, #-16]!
mov x29, sp
+ .cfi_def_cfa 29, 16
+ .cfi_offset 29, -16
+ .cfi_offset 30, -8
ldr_this_cpu x16, irq_stack_ptr, x17
@@ -897,9 +916,13 @@ SYM_FUNC_START(call_on_irq_stack)
*/
mov sp, x29
ldp x29, x30, [sp], #16
+ .cfi_restore 29
+ .cfi_restore 30
+ .cfi_def_cfa 31, 0
scs_load_current
restore_irq x9
ret
+ .cfi_endproc
SYM_FUNC_END(call_on_irq_stack)
NOKPROBE(call_on_irq_stack)
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 4/8] sframe: Provide PC lookup for vmlinux .sframe section
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
With SFRAME_UNWINDER, read in the .sframe section at boot. This provides
unwind data as an alternative/supplement to frame pointer-based
unwinding.
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
arch/arm64/kernel/setup.c | 2 ++
include/linux/sframe.h | 14 ++++++++++++++
kernel/unwind/sframe.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 52 insertions(+)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 23c05dc7a8f2..4a633bc7aefb 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -32,6 +32,7 @@
#include <linux/sched/task.h>
#include <linux/scs.h>
#include <linux/mm.h>
+#include <linux/sframe.h>
#include <asm/acpi.h>
#include <asm/fixmap.h>
@@ -375,6 +376,7 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
"This indicates a broken bootloader or old kernel\n",
boot_args[1], boot_args[2], boot_args[3]);
}
+ init_sframe_table();
}
static inline bool cpu_can_disable(unsigned int cpu)
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 0cb2924367bc..5b7341b61a7c 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -69,4 +69,18 @@ static inline int sframe_find_user(unsigned long ip, struct unwind_frame *frame)
#endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+void __init init_sframe_table(void);
+void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
+ void *text, size_t text_size);
+
+extern int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame);
+
+#else
+
+static inline void __init init_sframe_table(void) {}
+
+#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
#endif /* _LINUX_SFRAME_H */
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index 89dd8c5a6a10..430bff9533ee 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -14,10 +14,20 @@
#include <linux/sframe.h>
#include <linux/unwind_types.h>
#include <asm/unwind_sframe.h>
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+#include <linux/kallsyms.h>
+#endif
#include "sframe.h"
#include "sframe_debug.h"
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+static bool sframe_init __ro_after_init;
+static struct sframe_section kernel_sfsec __ro_after_init;
+
+#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
struct sframe_fde_internal {
unsigned long func_addr;
u32 func_size;
@@ -930,3 +940,29 @@ void sframe_free_mm(struct mm_struct *mm)
}
#endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
+
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame)
+{
+ if (!frame || !sframe_init)
+ return -EINVAL;
+
+ return __sframe_find(&kernel_sfsec, ip, frame);
+}
+
+void __init init_sframe_table(void)
+{
+ kernel_sfsec.sec_type = SFRAME_KERNEL;
+ kernel_sfsec.sframe_start = (unsigned long)__start_sframe;
+ kernel_sfsec.sframe_end = (unsigned long)__end_sframe;
+ kernel_sfsec.text_start = (unsigned long)_stext;
+ kernel_sfsec.text_end = (unsigned long)_etext;
+
+ if (WARN_ON(sframe_read_header(&kernel_sfsec)))
+ return;
+
+ sframe_init = true;
+}
+
+#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 5/8] sframe: Allow unsorted FDEs
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
The .sframe in kernel modules is built without SFRAME_F_FDE_SORTED set.
In order to allow sframe PC lookup in modules, add a code path to handle
unsorted FDE tables by doing a simple linear search.
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
include/linux/sframe.h | 1 +
kernel/unwind/sframe.c | 45 +++++++++++++++++++++++++++++++++++++-----
2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 5b7341b61a7c..8ae31ed36226 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -28,6 +28,7 @@ struct sframe_section {
unsigned long fres_start;
unsigned long fres_end;
unsigned int num_fdes;
+ bool fdes_sorted;
signed char ra_off;
signed char fp_off;
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index 430bff9533ee..dcf4deb378dc 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -176,9 +176,35 @@ static __always_inline int __read_fde(struct sframe_section *sec,
return -EFAULT;
}
-static __always_inline int __find_fde(struct sframe_section *sec,
- unsigned long ip,
- struct sframe_fde_internal *fde)
+static __always_inline int __find_fde_unsorted(struct sframe_section *sec,
+ unsigned long ip,
+ struct sframe_fde_internal *fde)
+{
+ struct sframe_fde_v3 *cur, *start, *end;
+
+ start = (struct sframe_fde_v3 *)sec->fdes_start;
+ end = start + sec->num_fdes;
+
+ for (cur = start; cur < end; cur++) {
+ s64 func_off;
+ u32 func_size;
+ unsigned long func_addr;
+
+ DATA_GET(sec, func_off, &cur->func_start_off, s64, Efault);
+ DATA_GET(sec, func_size, &cur->func_size, u32, Efault);
+ func_addr = (unsigned long)cur + func_off;
+
+ if (ip >= func_addr && ip < func_addr + func_size)
+ return __read_fde(sec, cur - start, fde);
+ }
+ return -EINVAL;
+Efault:
+ return -EFAULT;
+}
+
+static __always_inline int __find_fde_sorted(struct sframe_section *sec,
+ unsigned long ip,
+ struct sframe_fde_internal *fde)
{
unsigned long func_addr_low = 0, func_addr_high = ULONG_MAX;
struct sframe_fde_v3 *first, *low, *high, *found = NULL;
@@ -233,6 +259,15 @@ static __always_inline int __find_fde(struct sframe_section *sec,
return -EFAULT;
}
+static __always_inline int __find_fde(struct sframe_section *sec,
+ unsigned long ip,
+ struct sframe_fde_internal *fde)
+{
+ if (sec->fdes_sorted)
+ return __find_fde_sorted(sec, ip, fde);
+ return __find_fde_unsorted(sec, ip, fde);
+}
+
#define ____GET_INC(sec, to, from, type, label) \
({ \
type __to; \
@@ -657,7 +692,7 @@ static int sframe_validate_section(struct sframe_section *sec)
return ret;
ip = fde.func_addr;
- if (ip <= prev_ip) {
+ if (sec->fdes_sorted && ip <= prev_ip) {
dbg_sec("fde %u not sorted\n", i);
return -EFAULT;
}
@@ -736,7 +771,6 @@ static int sframe_read_header(struct sframe_section *sec)
if (shdr.preamble.magic != SFRAME_MAGIC ||
shdr.preamble.version != SFRAME_VERSION_3 ||
- !(shdr.preamble.flags & SFRAME_F_FDE_SORTED) ||
!(shdr.preamble.flags & SFRAME_F_FDE_FUNC_START_PCREL) ||
shdr.auxhdr_len) {
dbg_sec("bad/unsupported sframe header\n");
@@ -766,6 +800,7 @@ static int sframe_read_header(struct sframe_section *sec)
return -EINVAL;
}
+ sec->fdes_sorted = shdr.preamble.flags & SFRAME_F_FDE_SORTED;
sec->num_fdes = num_fdes;
sec->fdes_start = fdes_start;
sec->fres_start = fres_start;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 7/8] sframe: Introduce in-kernel SFRAME_VALIDATION
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
Generalize the __safe* helpers to support a non-user-access code path.
This requires arch-specific function address validation. This is because
arm64 vmlinux keeps .exit.text (normally discarded), and .rodata.text
sections both of which lie outside the bounds of the normal .text.
.rodata.text contains code that is never executed by the kernel mapping,
but for which the toolchain nonetheless generates sframe data, and needs
to be considered valid for a PC lookup.
Additionally .init.text lies outside .text for all arches and must be
accounted for as well.
Suggested-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
arch/Kconfig | 2 +-
arch/arm64/include/asm/sections.h | 1 +
arch/arm64/include/asm/unwind_sframe.h | 47 ++++++++++++++++++++++++++
arch/arm64/kernel/vmlinux.lds.S | 2 ++
include/linux/sframe.h | 2 ++
kernel/unwind/sframe.c | 25 ++++++++++++--
6 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 8d27b3249e7a..a528f5b23647 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -503,7 +503,7 @@ config HAVE_UNWIND_USER_SFRAME
config SFRAME_VALIDATION
bool "Enable .sframe section debugging"
- depends on HAVE_UNWIND_USER_SFRAME
+ depends on UNWIND_SFRAME_LOOKUP
depends on DYNAMIC_DEBUG
help
When adding an .sframe section for a task, validate the entire
diff --git a/arch/arm64/include/asm/sections.h b/arch/arm64/include/asm/sections.h
index 51b0d594239e..5edb4304f661 100644
--- a/arch/arm64/include/asm/sections.h
+++ b/arch/arm64/include/asm/sections.h
@@ -23,6 +23,7 @@ extern char __irqentry_text_start[], __irqentry_text_end[];
extern char __mmuoff_data_start[], __mmuoff_data_end[];
extern char __entry_tramp_text_start[], __entry_tramp_text_end[];
extern char __relocate_new_kernel_start[], __relocate_new_kernel_end[];
+extern char _srodatatext[], _erodatatext[];
static inline size_t entry_tramp_text_size(void)
{
diff --git a/arch/arm64/include/asm/unwind_sframe.h b/arch/arm64/include/asm/unwind_sframe.h
index 876412881196..66ebe5f38bd0 100644
--- a/arch/arm64/include/asm/unwind_sframe.h
+++ b/arch/arm64/include/asm/unwind_sframe.h
@@ -2,7 +2,54 @@
#ifndef _ASM_ARM64_UNWIND_SFRAME_H
#define _ASM_ARM64_UNWIND_SFRAME_H
+#include <linux/module.h>
+#include <linux/sframe.h>
+#include <asm/sections.h>
+
#define SFRAME_REG_SP 31
#define SFRAME_REG_FP 29
+static inline bool sframe_func_start_addr_valid(struct sframe_section *sec,
+ unsigned long func_addr)
+{
+ /* Common case for unwinding */
+ if (sec->text_start <= func_addr && func_addr < sec->text_end)
+ return true;
+
+ if (sec->sec_type != SFRAME_KERNEL)
+ return false;
+
+ /*
+ * Account for vmlinux and module code outside the normal .text section.
+ * The toolchain still generates sframe data for these functions, so
+ * sframe lookups on them should be allowed.
+ */
+ if (sec == &kernel_sfsec) {
+ if (is_kernel_inittext(func_addr))
+ return true;
+
+ /* .exit.text is retained in vmlinux on arm64. */
+ if (func_addr >= (unsigned long)__exittext_begin &&
+ func_addr < (unsigned long)__exittext_end)
+ return true;
+
+
+ /*
+ * .rodata.text is never executed from the kernel mapping, but
+ * still has sframe data
+ */
+ if (func_addr >= (unsigned long)_srodatatext &&
+ func_addr < (unsigned long)_erodatatext)
+ return true;
+ } else {
+ struct module *mod = container_of(sec, struct module,
+ arch.sframe_sec);
+ if (within_module_mem_type(func_addr, mod, MOD_INIT_TEXT))
+ return true;
+ }
+
+ return false;
+}
+#define sframe_func_start_addr_valid sframe_func_start_addr_valid
+
#endif /* _ASM_ARM64_UNWIND_SFRAME_H */
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 2964aad0362e..8c2dae6e7a86 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -213,12 +213,14 @@ SECTIONS
/* code sections that are never executed via the kernel mapping */
.rodata.text : {
+ _srodatatext = .;
TRAMP_TEXT
HIBERNATE_TEXT
KEXEC_TEXT
IDMAP_TEXT
. = ALIGN(PAGE_SIZE);
}
+ _erodatatext = .;
idmap_pg_dir = .;
. += PAGE_SIZE;
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 27f5a66190af..ac3aa9db7d91 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -34,6 +34,8 @@ struct sframe_section {
signed char fp_off;
};
+extern struct sframe_section kernel_sfsec __ro_after_init;
+
#endif /* CONFIG_UNWIND_SFRAME_LOOKUP */
#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index 70001c8e586d..99c2a39c51ce 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -21,10 +21,18 @@
#include "sframe.h"
#include "sframe_debug.h"
+#ifndef sframe_func_start_addr_valid
+static inline bool sframe_func_start_addr_valid(struct sframe_section *sec,
+ unsigned long func_addr)
+{
+ return (sec->text_start <= func_addr && func_addr < sec->text_end);
+}
+#endif
+
#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
static bool sframe_init __ro_after_init;
-static struct sframe_section kernel_sfsec __ro_after_init;
+struct sframe_section kernel_sfsec __ro_after_init;
#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
@@ -152,7 +160,7 @@ static __always_inline int __read_fde(struct sframe_section *sec,
sizeof(struct sframe_fde_v3), Efault);
func_addr = fde_addr + _fde.func_start_off;
- if (func_addr < sec->text_start || func_addr > sec->text_end)
+ if (!sframe_func_start_addr_valid(sec, func_addr))
return -EINVAL;
fda_addr = sec->fres_start + _fde.fres_off;
@@ -636,6 +644,9 @@ static int safe_read_fde(struct sframe_section *sec,
{
int ret;
+ if (sec->sec_type == SFRAME_KERNEL)
+ return __read_fde(sec, fde_num, fde);
+
if (!user_read_access_begin((void __user *)sec->sframe_start,
sec->sframe_end - sec->sframe_start))
return -EFAULT;
@@ -651,6 +662,9 @@ static int safe_read_fre(struct sframe_section *sec,
{
int ret;
+ if (sec->sec_type == SFRAME_KERNEL)
+ return __read_fre(sec, fde, fre_addr, fre);
+
if (!user_read_access_begin((void __user *)sec->sframe_start,
sec->sframe_end - sec->sframe_start))
return -EFAULT;
@@ -665,6 +679,9 @@ static int safe_read_fre_datawords(struct sframe_section *sec,
{
int ret;
+ if (sec->sec_type == SFRAME_KERNEL)
+ return __read_fre_datawords(sec, fde, fre);
+
if (!user_read_access_begin((void __user *)sec->sframe_start,
sec->sframe_end - sec->sframe_start))
return -EFAULT;
@@ -1013,6 +1030,8 @@ void __init init_sframe_table(void)
if (WARN_ON(sframe_read_header(&kernel_sfsec)))
return;
+ if (WARN_ON(sframe_validate_section(&kernel_sfsec)))
+ return;
sframe_init = true;
}
@@ -1031,6 +1050,8 @@ void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
if (WARN_ON(sframe_read_header(&sec)))
return;
+ if (WARN_ON(sframe_validate_section(&sec)))
+ return;
mod->arch.sframe_sec = sec;
mod->arch.sframe_init = true;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 6/8] arm64/module, sframe: Add sframe support for modules
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
Add sframe table to mod_arch_specific and support sframe PC lookups when
an .sframe section can be found on incoming modules.
Signed-off-by: Weinan Liu <wnliu@google.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
arch/arm64/include/asm/module.h | 6 +++++
arch/arm64/kernel/module.c | 8 +++++++
include/linux/sframe.h | 2 ++
kernel/unwind/sframe.c | 40 +++++++++++++++++++++++++++++++--
4 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index fb9b88eebeb1..07f309c51eee 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -6,6 +6,7 @@
#define __ASM_MODULE_H
#include <asm-generic/module.h>
+#include <linux/sframe.h>
struct mod_plt_sec {
int plt_shndx;
@@ -17,6 +18,11 @@ struct mod_arch_specific {
struct mod_plt_sec core;
struct mod_plt_sec init;
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ struct sframe_section sframe_sec;
+ bool sframe_init;
+#endif
+
/* for CONFIG_DYNAMIC_FTRACE */
struct plt_entry *ftrace_trampolines;
struct plt_entry *init_ftrace_trampolines;
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 24adb581af0e..427f187e9531 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -18,6 +18,7 @@
#include <linux/moduleloader.h>
#include <linux/random.h>
#include <linux/scs.h>
+#include <linux/sframe.h>
#include <asm/alternative.h>
#include <asm/insn.h>
@@ -515,5 +516,12 @@ int module_finalize(const Elf_Ehdr *hdr,
}
}
+ s = find_section(hdr, sechdrs, ".sframe");
+ if (s) {
+ struct module_memory *t = &me->mem[MOD_TEXT];
+
+ sframe_module_init(me, (void *)s->sh_addr, s->sh_size,
+ t->base, t->size);
+ }
return module_init_ftrace_plt(hdr, sechdrs, me);
}
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 8ae31ed36226..27f5a66190af 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -81,6 +81,8 @@ extern int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame);
#else
static inline void __init init_sframe_table(void) {}
+static inline void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
+ void *text, size_t text_size) {}
#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index dcf4deb378dc..70001c8e586d 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -980,10 +980,27 @@ void sframe_free_mm(struct mm_struct *mm)
int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame)
{
- if (!frame || !sframe_init)
+ struct sframe_section *sec;
+
+ if (!frame)
return -EINVAL;
- return __sframe_find(&kernel_sfsec, ip, frame);
+ if (is_ksym_addr(ip)) {
+ if (!sframe_init)
+ return -EINVAL;
+
+ sec = &kernel_sfsec;
+ } else {
+ struct module *mod;
+
+ mod = __module_address(ip);
+ if (!mod || !mod->arch.sframe_init)
+ return -EINVAL;
+
+ sec = &mod->arch.sframe_sec;
+ }
+
+ return __sframe_find(sec, ip, frame);
}
void __init init_sframe_table(void)
@@ -1000,4 +1017,23 @@ void __init init_sframe_table(void)
sframe_init = true;
}
+void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
+ void *text, size_t text_size)
+{
+ struct sframe_section sec;
+
+ memset(&sec, 0, sizeof(sec));
+ sec.sec_type = SFRAME_KERNEL;
+ sec.sframe_start = (unsigned long)sframe;
+ sec.sframe_end = (unsigned long)sframe + sframe_size;
+ sec.text_start = (unsigned long)text;
+ sec.text_end = (unsigned long)text + text_size;
+
+ if (WARN_ON(sframe_read_header(&sec)))
+ return;
+
+ mod->arch.sframe_sec = sec;
+ mod->arch.sframe_init = true;
+}
+
#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH v5 8/8] unwind: arm64: Use sframe to unwind interrupt frames
From: Dylan Hatch @ 2026-04-28 18:36 UTC (permalink / raw)
To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus
Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260428183643.3796063-1-dylanbhatch@google.com>
Add unwind_next_frame_sframe() function to unwind by sframe info if
present. Use this method at exception boundaries, falling back to
frame-pointer unwind only on failure. In such failure cases, the
stacktrace is considered unreliable.
During normal unwind, prefer frame pointer unwind (for better
performance) with sframe as a backup.
This change restores the LR behavior originally introduced in commit
c2c6b27b5aa14fa2 ("arm64: stacktrace: unwind exception boundaries"),
But later removed in commit 32ed1205682e ("arm64: stacktrace: Skip
reporting LR at exception boundaries")
This can be done because the sframe data can be used to determine
whether the LR is current for the PC value recovered from pt_regs at the
exception boundary.
Signed-off-by: Weinan Liu <wnliu@google.com>
Reviewed-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
arch/arm64/include/asm/stacktrace/common.h | 6 +
arch/arm64/kernel/stacktrace.c | 246 +++++++++++++++++++--
2 files changed, 232 insertions(+), 20 deletions(-)
diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 821a8fdd31af..4df68181e1b5 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -21,6 +21,8 @@ struct stack_info {
*
* @fp: The fp value in the frame record (or the real fp)
* @pc: The lr value in the frame record (or the real lr)
+ * @sp: The sp value at the call site of the current function.
+ * @unreliable: Stacktrace is unreliable.
*
* @stack: The stack currently being unwound.
* @stacks: An array of stacks which can be unwound.
@@ -29,7 +31,11 @@ struct stack_info {
struct unwind_state {
unsigned long fp;
unsigned long pc;
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ unsigned long sp;
+#endif
+ bool unreliable;
struct stack_info stack;
struct stack_info *stacks;
int nr_stacks;
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 3ebcf8c53fb0..c935323f393b 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -14,6 +14,7 @@
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
#include <linux/stacktrace.h>
+#include <linux/sframe.h>
#include <asm/efi.h>
#include <asm/irq.h>
@@ -26,6 +27,7 @@ enum kunwind_source {
KUNWIND_SOURCE_CALLER,
KUNWIND_SOURCE_TASK,
KUNWIND_SOURCE_REGS_PC,
+ KUNWIND_SOURCE_REGS_LR,
};
union unwind_flags {
@@ -85,6 +87,9 @@ kunwind_init_from_regs(struct kunwind_state *state,
state->regs = regs;
state->common.fp = regs->regs[29];
state->common.pc = regs->pc;
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ state->common.sp = regs->sp;
+#endif
state->source = KUNWIND_SOURCE_REGS_PC;
}
@@ -103,6 +108,9 @@ kunwind_init_from_caller(struct kunwind_state *state)
state->common.fp = (unsigned long)__builtin_frame_address(1);
state->common.pc = (unsigned long)__builtin_return_address(0);
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ state->common.sp = (unsigned long)__builtin_frame_address(0);
+#endif
state->source = KUNWIND_SOURCE_CALLER;
}
@@ -124,6 +132,9 @@ kunwind_init_from_task(struct kunwind_state *state,
state->common.fp = thread_saved_fp(task);
state->common.pc = thread_saved_pc(task);
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ state->common.sp = thread_saved_sp(task);
+#endif
state->source = KUNWIND_SOURCE_TASK;
}
@@ -181,7 +192,6 @@ int kunwind_next_regs_pc(struct kunwind_state *state)
state->regs = regs;
state->common.pc = regs->pc;
state->common.fp = regs->regs[29];
- state->regs = NULL;
state->source = KUNWIND_SOURCE_REGS_PC;
return 0;
}
@@ -237,6 +247,9 @@ kunwind_next_frame_record(struct kunwind_state *state)
unwind_consume_stack(&state->common, info, fp, sizeof(*record));
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ state->common.sp = state->common.fp;
+#endif
state->common.fp = new_fp;
state->common.pc = new_pc;
state->source = KUNWIND_SOURCE_FRAME;
@@ -244,6 +257,176 @@ kunwind_next_frame_record(struct kunwind_state *state)
return 0;
}
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+static __always_inline struct stack_info *
+get_word(struct unwind_state *state, unsigned long *word)
+{
+ unsigned long addr = *word;
+ struct stack_info *info;
+
+ info = unwind_find_stack(state, addr, sizeof(addr));
+ if (!info)
+ return info;
+
+ *word = READ_ONCE(*(unsigned long *)addr);
+
+ return info;
+}
+
+static __always_inline int
+get_consume_word(struct unwind_state *state, unsigned long *word)
+{
+ struct stack_info *info;
+ unsigned long addr = *word;
+
+ info = get_word(state, word);
+ if (!info)
+ return -EINVAL;
+
+ unwind_consume_stack(state, info, addr, sizeof(addr));
+ return 0;
+}
+
+/*
+ * Unwind to the next frame according to sframe.
+ */
+static __always_inline int
+unwind_next_frame_sframe(struct kunwind_state *state)
+{
+ struct unwind_frame frame;
+ unsigned long cfa, fp, ra;
+ enum kunwind_source source = KUNWIND_SOURCE_FRAME;
+ struct pt_regs *regs = state->regs;
+
+ int err;
+
+ /* FP/SP alignment 8 bytes */
+ if (state->common.fp & 0x7 || state->common.sp & 0x7)
+ return -EINVAL;
+
+ /*
+ * Most/all outermost functions are not visible to sframe. So, check for
+ * a meta frame record if the sframe lookup fails.
+ */
+ err = sframe_find_kernel(state->common.pc, &frame);
+ if (err)
+ return kunwind_next_frame_record_meta(state);
+
+ if (frame.outermost)
+ return -ENOENT;
+
+ /* Get the Canonical Frame Address (CFA) */
+ switch (frame.cfa.rule) {
+ case UNWIND_CFA_RULE_SP_OFFSET:
+ cfa = state->common.sp;
+ break;
+ case UNWIND_CFA_RULE_FP_OFFSET:
+ if (state->common.fp < state->common.sp)
+ return -EINVAL;
+ cfa = state->common.fp;
+ break;
+ case UNWIND_CFA_RULE_REG_OFFSET:
+ case UNWIND_CFA_RULE_REG_OFFSET_DEREF:
+ /* regs only available in topmost/interrupt frame */
+ if (!regs || frame.cfa.regnum > 30)
+ return -EINVAL;
+ cfa = regs->regs[frame.cfa.regnum];
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+ cfa += frame.cfa.offset;
+
+ /*
+ * CFA typically points to a higher address than RA or FP, so don't
+ * consume from the stack when we read it.
+ */
+ if (frame.cfa.rule & UNWIND_RULE_DEREF &&
+ !get_word(&state->common, &cfa))
+ return -EINVAL;
+
+ /* CFA alignment 8 bytes */
+ if (cfa & 0x7)
+ return -EINVAL;
+
+ /* Get the Return Address (RA) */
+ switch (frame.ra.rule) {
+ case UNWIND_RULE_RETAIN:
+ /* regs only available in topmost/interrupt frame */
+ if (!regs)
+ return -EINVAL;
+ ra = regs->regs[30];
+ source = KUNWIND_SOURCE_REGS_LR;
+ break;
+ /* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
+ case UNWIND_RULE_CFA_OFFSET_DEREF:
+ ra = cfa + frame.ra.offset;
+ break;
+ case UNWIND_RULE_REG_OFFSET:
+ case UNWIND_RULE_REG_OFFSET_DEREF:
+ /* regs only available in topmost/interrupt frame */
+ if (!regs)
+ return -EINVAL;
+ ra = regs->regs[frame.cfa.regnum];
+ ra += frame.ra.offset;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ /* Get the Frame Pointer (FP) */
+ switch (frame.fp.rule) {
+ case UNWIND_RULE_RETAIN:
+ fp = state->common.fp;
+ break;
+ /* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
+ case UNWIND_RULE_CFA_OFFSET_DEREF:
+ fp = cfa + frame.fp.offset;
+ break;
+ case UNWIND_RULE_REG_OFFSET:
+ case UNWIND_RULE_REG_OFFSET_DEREF:
+ /* regs only available in topmost/interrupt frame */
+ if (!regs)
+ return -EINVAL;
+ fp = regs->regs[frame.fp.regnum];
+ fp += frame.fp.offset;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ /*
+ * Consume RA and FP from the stack. The frame record puts FP at a lower
+ * address than RA, so we always read FP first.
+ */
+ if (frame.fp.rule & UNWIND_RULE_DEREF &&
+ !get_word(&state->common, &fp))
+ return -EINVAL;
+
+ if (frame.ra.rule & UNWIND_RULE_DEREF &&
+ get_consume_word(&state->common, &ra))
+ return -EINVAL;
+
+ state->common.pc = ra;
+ state->common.sp = cfa;
+ state->common.fp = fp;
+
+ state->source = source;
+
+ return 0;
+}
+
+#else /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
+static __always_inline int
+unwind_next_frame_sframe(struct kunwind_state *state) { return -EINVAL; }
+
+#endif /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME*/
+
/*
* Unwind from one frame record (A) to the next frame record (B).
*
@@ -259,12 +442,25 @@ kunwind_next(struct kunwind_state *state)
state->flags.all = 0;
switch (state->source) {
+ case KUNWIND_SOURCE_REGS_PC:
+ err = unwind_next_frame_sframe(state);
+
+ if (err && err != -ENOENT) {
+ /* Fallback to FP based unwinder */
+ err = kunwind_next_frame_record(state);
+ state->common.unreliable = true;
+ }
+ state->regs = NULL;
+ break;
case KUNWIND_SOURCE_FRAME:
case KUNWIND_SOURCE_CALLER:
case KUNWIND_SOURCE_TASK:
- case KUNWIND_SOURCE_REGS_PC:
+ case KUNWIND_SOURCE_REGS_LR:
err = kunwind_next_frame_record(state);
+ if (err && err != -ENOENT)
+ err = unwind_next_frame_sframe(state);
break;
+
default:
err = -EINVAL;
}
@@ -350,6 +546,9 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
.common = {
.stacks = stacks,
.nr_stacks = ARRAY_SIZE(stacks),
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+ .sp = 0,
+#endif
},
};
@@ -390,34 +589,40 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
}
+struct kunwind_reliable_consume_entry_data {
+ stack_trace_consume_fn consume_entry;
+ void *cookie;
+ bool unreliable;
+};
+
static __always_inline bool
-arch_reliable_kunwind_consume_entry(const struct kunwind_state *state, void *cookie)
+arch_kunwind_reliable_consume_entry(const struct kunwind_state *state, void *cookie)
{
- /*
- * At an exception boundary we can reliably consume the saved PC. We do
- * not know whether the LR was live when the exception was taken, and
- * so we cannot perform the next unwind step reliably.
- *
- * All that matters is whether the *entire* unwind is reliable, so give
- * up as soon as we hit an exception boundary.
- */
- if (state->source == KUNWIND_SOURCE_REGS_PC)
- return false;
+ struct kunwind_reliable_consume_entry_data *data = cookie;
- return arch_kunwind_consume_entry(state, cookie);
+ if (state->common.unreliable) {
+ data->unreliable = true;
+ return false;
+ }
+ return data->consume_entry(data->cookie, state->common.pc);
}
-noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
- void *cookie,
- struct task_struct *task)
+noinline notrace int arch_stack_walk_reliable(
+ stack_trace_consume_fn consume_entry,
+ void *cookie, struct task_struct *task)
{
- struct kunwind_consume_entry_data data = {
+ struct kunwind_reliable_consume_entry_data data = {
.consume_entry = consume_entry,
.cookie = cookie,
+ .unreliable = false,
};
- return kunwind_stack_walk(arch_reliable_kunwind_consume_entry, &data,
- task, NULL);
+ kunwind_stack_walk(arch_kunwind_reliable_consume_entry, &data, task, NULL);
+
+ if (data.unreliable)
+ return -EINVAL;
+
+ return 0;
}
struct bpf_unwind_consume_entry_data {
@@ -452,6 +657,7 @@ static const char *state_source_string(const struct kunwind_state *state)
case KUNWIND_SOURCE_CALLER: return "C";
case KUNWIND_SOURCE_TASK: return "T";
case KUNWIND_SOURCE_REGS_PC: return "P";
+ case KUNWIND_SOURCE_REGS_LR: return "L";
default: return "U";
}
}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH 5.15.y] arm64/mm: Enable batched TLB flush in unmap_hotplug_range()
From: Sasha Levin @ 2026-04-28 18:53 UTC (permalink / raw)
To: stable
Cc: Anshuman Khandual, Will Deacon, linux-arm-kernel, linux-kernel,
David Hildenbrand (Arm), Ryan Roberts, Catalin Marinas,
Sasha Levin
In-Reply-To: <2026042728-drier-spotty-9450@gregkh>
From: Anshuman Khandual <anshuman.khandual@arm.com>
[ Upstream commit 48478b9f791376b4b89018d7afdfd06865498f65 ]
During a memory hot remove operation, both linear and vmemmap mappings for
the memory range being removed, get unmapped via unmap_hotplug_range() but
mapped pages get freed only for vmemmap mapping. This is just a sequential
operation where each table entry gets cleared, followed by a leaf specific
TLB flush, and then followed by memory free operation when applicable.
This approach was simple and uniform both for vmemmap and linear mappings.
But linear mapping might contain CONT marked block memory where it becomes
necessary to first clear out all entire in the range before a TLB flush.
This is as per the architecture requirement. Hence batch all TLB flushes
during the table tear down walk and finally do it in unmap_hotplug_range().
Prior to this fix, it was hypothetically possible for a speculative access
to a higher address in the contiguous block to fill the TLB with shattered
entries for the entire contiguous range after a lower address had already
been cleared and invalidated. Due to the table entries being shattered, the
subsequent TLB invalidation for the higher address would not then clear the
TLB entries for the lower address, meaning stale TLB entries could persist.
Besides it also helps in improving the performance via TLBI range operation
along with reduced synchronization instructions. The time spent executing
unmap_hotplug_range() improved 97% measured over a 2GB memory hot removal
in KVM guest.
This scheme is not applicable during vmemmap mapping tear down where memory
needs to be freed and hence a TLB flush is required after clearing out page
table entry.
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Closes: https://lore.kernel.org/all/aWZYXhrT6D2M-7-N@willie-the-truck/
Fixes: bbd6ec605c0f ("arm64/mm: Enable memory hot remove")
Cc: stable@vger.kernel.org
Reviewed-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
[ replaced `__pte_clear()` with `pte_clear()` ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/arm64/mm/mmu.c | 36 ++++++++++++++++++++----------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index e3e4defdea422..739d00a69be10 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -886,10 +886,14 @@ static void unmap_hotplug_pte_range(pmd_t *pmdp, unsigned long addr,
WARN_ON(!pte_present(pte));
pte_clear(&init_mm, addr, ptep);
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
- if (free_mapped)
+ if (free_mapped) {
+ /* CONT blocks are not supported in the vmemmap */
+ WARN_ON(pte_cont(pte));
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
free_hotplug_page_range(pte_page(pte),
PAGE_SIZE, altmap);
+ }
+ /* unmap_hotplug_range() flushes TLB for !free_mapped */
} while (addr += PAGE_SIZE, addr < end);
}
@@ -910,15 +914,14 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
WARN_ON(!pmd_present(pmd));
if (pmd_sect(pmd)) {
pmd_clear(pmdp);
-
- /*
- * One TLBI should be sufficient here as the PMD_SIZE
- * range is mapped with a single block entry.
- */
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
- if (free_mapped)
+ if (free_mapped) {
+ /* CONT blocks are not supported in the vmemmap */
+ WARN_ON(pmd_cont(pmd));
+ flush_tlb_kernel_range(addr, addr + PMD_SIZE);
free_hotplug_page_range(pmd_page(pmd),
PMD_SIZE, altmap);
+ }
+ /* unmap_hotplug_range() flushes TLB for !free_mapped */
continue;
}
WARN_ON(!pmd_table(pmd));
@@ -943,15 +946,12 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
WARN_ON(!pud_present(pud));
if (pud_sect(pud)) {
pud_clear(pudp);
-
- /*
- * One TLBI should be sufficient here as the PUD_SIZE
- * range is mapped with a single block entry.
- */
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
- if (free_mapped)
+ if (free_mapped) {
+ flush_tlb_kernel_range(addr, addr + PUD_SIZE);
free_hotplug_page_range(pud_page(pud),
PUD_SIZE, altmap);
+ }
+ /* unmap_hotplug_range() flushes TLB for !free_mapped */
continue;
}
WARN_ON(!pud_table(pud));
@@ -981,6 +981,7 @@ static void unmap_hotplug_p4d_range(pgd_t *pgdp, unsigned long addr,
static void unmap_hotplug_range(unsigned long addr, unsigned long end,
bool free_mapped, struct vmem_altmap *altmap)
{
+ unsigned long start = addr;
unsigned long next;
pgd_t *pgdp, pgd;
@@ -1002,6 +1003,9 @@ static void unmap_hotplug_range(unsigned long addr, unsigned long end,
WARN_ON(!pgd_present(pgd));
unmap_hotplug_p4d_range(pgdp, addr, next, free_mapped, altmap);
} while (addr = next, addr < end);
+
+ if (!free_mapped)
+ flush_tlb_kernel_range(start, end);
}
static void free_empty_pte_table(pmd_t *pmdp, unsigned long addr,
--
2.53.0
^ permalink raw reply related
* [PATCH] ARM: dts: ixp4xx: use phandle-based GPIOs in mi424wr
From: Mohamed Ayman @ 2026-04-28 19:10 UTC (permalink / raw)
To: Linus Walleij, Imre Kaloz, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, moderated list:ARM/INTEL IXP4XX ARM ARCHITECTURE,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
Cc: Mohamed Ayman, moderated list:ARM/INTEL IXP4XX ARM ARCHITECTURE,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
Convert remaining legacy integer GPIO specifiers to phandle-based
descriptors in intel-ixp42x-actiontec-mi424wr.dtsi.
All other GPIOs in this file already use &gpio0/&gpio1. These are the
last remaining legacy users in the IXP4xx DTS files.
Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com>
---
.../boot/dts/intel/ixp/intel-ixp42x-actiontec-mi424wr.dtsi | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-actiontec-mi424wr.dtsi b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-actiontec-mi424wr.dtsi
index 9b54e3c01a34..3043ae7232dd 100644
--- a/arch/arm/boot/dts/intel/ixp/intel-ixp42x-actiontec-mi424wr.dtsi
+++ b/arch/arm/boot/dts/intel/ixp/intel-ixp42x-actiontec-mi424wr.dtsi
@@ -195,19 +195,19 @@ gpio1: gpio@1,0 {
pci-reset-hog {
gpio-hog;
- gpios = <7 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "PCI reset";
};
pstn-relay-hog-1 {
gpio-hog;
- gpios = <11 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
output-low;
line-name = "PSTN relay control 1";
};
pstn-relay-hog-2 {
gpio-hog;
- gpios = <12 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
output-low;
line-name = "PSTN relay control 2";
};
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 02/11] media: Reformat v4l2-requests trace event printk
From: Nicolas Dufresne @ 2026-04-28 19:28 UTC (permalink / raw)
To: Detlev Casanova, linux-kernel
Cc: Benjamin Gaignard, Philipp Zabel, Mauro Carvalho Chehab,
Heiko Stuebner, Daniel Almeida, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Hans Verkuil, Laurent Pinchart,
Ricardo Ribalda, Yunke Cao, Sakari Ailus, Pavan Bobba,
James Cowgill, Ma Ke, Jacopo Mondi, Daniel Scally, linux-media,
linux-rockchip, linux-arm-kernel, linux-trace-kernel, kernel
In-Reply-To: <20260212162328.192217-3-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 39894 bytes --]
Le jeudi 12 février 2026 à 11:23 -0500, Detlev Casanova a écrit :
> When printing the v4l2-request traces the format was not stable.
> Sometimes using a ':' separator, sometimes with an extra space and using
> new lines.
>
> Reformat the printk calls to match the format used in v4l2.h so that
> parsers can use the same format for all events.
>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Could easily be done against visl now and merged early if you have time.
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> ---
> include/trace/events/v4l2_requests.h | 649 ++++++++++++++-------------
> 1 file changed, 328 insertions(+), 321 deletions(-)
>
> diff --git a/include/trace/events/v4l2_requests.h
> b/include/trace/events/v4l2_requests.h
> index 1e137d39d5fe..34f4a74df5ea 100644
> --- a/include/trace/events/v4l2_requests.h
> +++ b/include/trace/events/v4l2_requests.h
> @@ -14,8 +14,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_seq_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_sequence, s)),
> TP_fast_assign(__entry->s = *s;),
> - TP_printk("\nflags %s\nseq_profile: %u\norder_hint_bits:
> %u\nbit_depth: %u\n"
> - "max_frame_width_minus_1: %u\nmax_frame_height_minus_1:
> %u\n",
> + TP_printk("flags = %s, seq_profile = %u, order_hint_bits = %u,
> bit_depth = %u, "
> + "max_frame_width_minus_1 = %u, max_frame_height_minus_1 =
> %u",
> __print_flags(__entry->s.flags, "|",
> {V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE, "STILL_PICTURE"},
> {V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK,
> "USE_128X128_SUPERBLOCK"},
> @@ -50,7 +50,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_tge_tmpl,
> TP_ARGS(t),
> TP_STRUCT__entry(__field_struct(struct
> v4l2_ctrl_av1_tile_group_entry, t)),
> TP_fast_assign(__entry->t = *t;),
> - TP_printk("\ntile_offset: %u\n tile_size: %u\n tile_row:
> %u\ntile_col: %u\n",
> + TP_printk("tile_offset = %u, tile_size = %u, tile_row = %u, tile_col
> = %u",
> __entry->t.tile_offset,
> __entry->t.tile_size,
> __entry->t.tile_row,
> @@ -63,30 +63,30 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
> TP_ARGS(f),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_frame, f)),
> TP_fast_assign(__entry->f = *f;),
> - TP_printk("\ntile_info.flags: %s\ntile_info.context_update_tile_id:
> %u\n"
> - "tile_info.tile_cols: %u\ntile_info.tile_rows: %u\n"
> - "tile_info.mi_col_starts: %s\ntile_info.mi_row_starts:
> %s\n"
> - "tile_info.width_in_sbs_minus_1:
> %s\ntile_info.height_in_sbs_minus_1: %s\n"
> - "tile_info.tile_size_bytes: %u\nquantization.flags: %s\n"
> - "quantization.base_q_idx: %u\nquantization.delta_q_y_dc:
> %d\n"
> - "quantization.delta_q_u_dc: %d\nquantization.delta_q_u_ac:
> %d\n"
> - "quantization.delta_q_v_dc: %d\nquantization.delta_q_v_ac:
> %d\n"
> - "quantization.qm_y: %u\nquantization.qm_u:
> %u\nquantization.qm_v: %u\n"
> - "quantization.delta_q_res: %u\nsuperres_denom:
> %u\nsegmentation.flags: %s\n"
> - "segmentation.last_active_seg_id:
> %u\nsegmentation.feature_enabled:%s\n"
> - "loop_filter.flags: %s\nloop_filter.level:
> %s\nloop_filter.sharpness: %u\n"
> - "loop_filter.ref_deltas: %s\nloop_filter.mode_deltas: %s\n"
> - "loop_filter.delta_lf_res: %u\ncdef.damping_minus_3:
> %u\ncdef.bits: %u\n"
> - "cdef.y_pri_strength: %s\ncdef.y_sec_strength: %s\n"
> - "cdef.uv_pri_strength:
> %s\ncdef.uv_sec_strength:%s\nskip_mode_frame: %s\n"
> - "primary_ref_frame: %u\nloop_restoration.flags: %s\n"
> - "loop_restoration.lr_unit_shift:
> %u\nloop_restoration.lr_uv_shift: %u\n"
> - "loop_restoration.frame_restoration_type: %s\n"
> - "loop_restoration.loop_restoration_size: %s\nflags:
> %s\norder_hint: %u\n"
> - "upscaled_width: %u\nframe_width_minus_1:
> %u\nframe_height_minus_1: %u\n"
> - "render_width_minus_1: %u\nrender_height_minus_1:
> %u\ncurrent_frame_id: %u\n"
> - "buffer_removal_time: %s\norder_hints:
> %s\nreference_frame_ts: %s\n"
> - "ref_frame_idx: %s\nrefresh_frame_flags: %u\n",
> + TP_printk("tile_info.flags = %s, tile_info.context_update_tile_id =
> %u, "
> + "tile_info.tile_cols = %u, tile_info.tile_rows = %u, "
> + "tile_info.mi_col_starts = %s, tile_info.mi_row_starts =
> %s, "
> + "tile_info.width_in_sbs_minus_1 = %s,
> tile_info.height_in_sbs_minus_1 = %s, "
> + "tile_info.tile_size_bytes = %u, quantization.flags = %s, "
> + "quantization.base_q_idx = %u, quantization.delta_q_y_dc =
> %d, "
> + "quantization.delta_q_u_dc = %d, quantization.delta_q_u_ac
> = %d, "
> + "quantization.delta_q_v_dc = %d, quantization.delta_q_v_ac
> = %d, "
> + "quantization.qm_y = %u, quantization.qm_u = %u,
> quantization.qm_v = %u, "
> + "quantization.delta_q_res = %u, superres_denom = %u,
> segmentation.flags = %s, "
> + "segmentation.last_active_seg_id = %u,
> segmentation.feature_enabled = %s, "
> + "loop_filter.flags = %s, loop_filter.level = %s,
> loop_filter.sharpness = %u, "
> + "loop_filter.ref_deltas = %s, loop_filter.mode_deltas = %s,
> "
> + "loop_filter.delta_lf_res = %u, cdef.damping_minus_3 = %u,
> cdef.bits = %u, "
> + "cdef.y_pri_strength = %s, cdef.y_sec_strength = %s, "
> + "cdef.uv_pri_strength = %s, cdef.uv_sec_strength = %s,
> skip_mode_frame = %s, "
> + "primary_ref_frame = %u, loop_restoration.flags = %s, "
> + "loop_restoration.lr_unit_shift = %u,
> loop_restoration.lr_uv_shift = %u, "
> + "loop_restoration.frame_restoration_type = %s, "
> + "loop_restoration.loop_restoration_size = %s, flags = %s,
> order_hint = %u, "
> + "upscaled_width = %u, frame_width_minus_1 = %u,
> frame_height_minus_1 = %u, "
> + "render_width_minus_1 = %u, render_height_minus_1 = %u,
> current_frame_id = %u, "
> + "buffer_removal_time = %s, order_hints = %s,
> reference_frame_ts = %s, "
> + "ref_frame_idx = %s, refresh_frame_flags = %u",
> __print_flags(__entry->f.tile_info.flags, "|",
> {V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING,
> "UNIFORM_TILE_SPACING"}),
> __entry->f.tile_info.context_update_tile_id,
> @@ -226,15 +226,15 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
> TP_ARGS(f),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_film_grain, f)),
> TP_fast_assign(__entry->f = *f;),
> - TP_printk("\nflags %s\ncr_mult: %u\ngrain_seed: %u\n"
> - "film_grain_params_ref_idx: %u\nnum_y_points:
> %u\npoint_y_value: %s\n"
> - "point_y_scaling: %s\nnum_cb_points: %u\npoint_cb_value:
> %s\n"
> - "point_cb_scaling: %s\nnum_cr_points: %u\npoint_cr_value:
> %s\n"
> - "point_cr_scaling: %s\ngrain_scaling_minus_8:
> %u\nar_coeff_lag: %u\n"
> - "ar_coeffs_y_plus_128: %s\nar_coeffs_cb_plus_128: %s\n"
> - "ar_coeffs_cr_plus_128: %s\nar_coeff_shift_minus_6: %u\n"
> - "grain_scale_shift: %u\ncb_mult: %u\ncb_luma_mult:
> %u\ncr_luma_mult: %u\n"
> - "cb_offset: %u\ncr_offset: %u\n",
> + TP_printk("flags = %s, cr_mult = %u, grain_seed = %u, "
> + "film_grain_params_ref_idx = %u, num_y_points = %u,
> point_y_value = %s, "
> + "point_y_scaling = %s, num_cb_points = %u, point_cb_value =
> %s, "
> + "point_cb_scaling = %s, num_cr_points = %u, point_cr_value
> = %s, "
> + "point_cr_scaling = %s, grain_scaling_minus_8 = %u,
> ar_coeff_lag = %u, "
> + "ar_coeffs_y_plus_128 = %s, ar_coeffs_cb_plus_128 = %s, "
> + "ar_coeffs_cr_plus_128 = %s, ar_coeff_shift_minus_6 = %u, "
> + "grain_scale_shift = %u, cb_mult = %u, cb_luma_mult = %u,
> cr_luma_mult = %u, "
> + "cb_offset = %u, cr_offset = %u",
> __print_flags(__entry->f.flags, "|",
> {V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN, "APPLY_GRAIN"},
> {V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN, "UPDATE_GRAIN"},
> @@ -333,7 +333,15 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
> __entry->ycbcr_enc = p->ycbcr_enc;
> __entry->quantization = p->quantization;
> ),
> - TP_printk("backward_ref_ts %llu version %u width %u height %u flags
> %s colorspace %u xfer_func %u ycbcr_enc %u quantization %u",
> + TP_printk("backward_ref_ts = %llu, "
> + "version = %u, "
> + "width = %u, "
> + "height = %u, "
> + "flags = %s, "
> + "colorspace = %u, "
> + "xfer_func = %u, "
> + "ycbcr_enc = %u, "
> + "quantization = %u",
> __entry->backward_ref_ts, __entry->version, __entry->width,
> __entry->height,
> __print_flags(__entry->flags, "|",
> {V4L2_FWHT_FL_IS_INTERLACED, "IS_INTERLACED"},
> @@ -364,24 +372,24 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_sps, s)),
> TP_fast_assign(__entry->s = *s),
> - TP_printk("\nprofile_idc %u\n"
> - "constraint_set_flags %s\n"
> - "level_idc %u\n"
> - "seq_parameter_set_id %u\n"
> - "chroma_format_idc %u\n"
> - "bit_depth_luma_minus8 %u\n"
> - "bit_depth_chroma_minus8 %u\n"
> - "log2_max_frame_num_minus4 %u\n"
> - "pic_order_cnt_type %u\n"
> - "log2_max_pic_order_cnt_lsb_minus4 %u\n"
> - "max_num_ref_frames %u\n"
> - "num_ref_frames_in_pic_order_cnt_cycle %u\n"
> - "offset_for_ref_frame %s\n"
> - "offset_for_non_ref_pic %d\n"
> - "offset_for_top_to_bottom_field %d\n"
> - "pic_width_in_mbs_minus1 %u\n"
> - "pic_height_in_map_units_minus1 %u\n"
> - "flags %s",
> + TP_printk("profile_idc = %u, "
> + "constraint_set_flags = %s, "
> + "level_idc = %u, "
> + "seq_parameter_set_id = %u, "
> + "chroma_format_idc = %u, "
> + "bit_depth_luma_minus8 = %u, "
> + "bit_depth_chroma_minus8 = %u, "
> + "log2_max_frame_num_minus4 = %u, "
> + "pic_order_cnt_type = %u, "
> + "log2_max_pic_order_cnt_lsb_minus4 = %u, "
> + "max_num_ref_frames = %u, "
> + "num_ref_frames_in_pic_order_cnt_cycle = %u, "
> + "offset_for_ref_frame = %s, "
> + "offset_for_non_ref_pic = %d, "
> + "offset_for_top_to_bottom_field = %d, "
> + "pic_width_in_mbs_minus1 = %u, "
> + "pic_height_in_map_units_minus1 = %u, "
> + "flags = %s",
> __entry->s.profile_idc,
> __print_flags(__entry->s.constraint_set_flags, "|",
> {V4L2_H264_SPS_CONSTRAINT_SET0_FLAG,
> "CONSTRAINT_SET0_FLAG"},
> @@ -423,17 +431,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
> TP_ARGS(p),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_pps, p)),
> TP_fast_assign(__entry->p = *p),
> - TP_printk("\npic_parameter_set_id %u\n"
> - "seq_parameter_set_id %u\n"
> - "num_slice_groups_minus1 %u\n"
> - "num_ref_idx_l0_default_active_minus1 %u\n"
> - "num_ref_idx_l1_default_active_minus1 %u\n"
> - "weighted_bipred_idc %u\n"
> - "pic_init_qp_minus26 %d\n"
> - "pic_init_qs_minus26 %d\n"
> - "chroma_qp_index_offset %d\n"
> - "second_chroma_qp_index_offset %d\n"
> - "flags %s",
> + TP_printk("pic_parameter_set_id = %u, "
> + "seq_parameter_set_id = %u, "
> + "num_slice_groups_minus1 = %u, "
> + "num_ref_idx_l0_default_active_minus1 = %u, "
> + "num_ref_idx_l1_default_active_minus1 = %u, "
> + "weighted_bipred_idc = %u, "
> + "pic_init_qp_minus26 = %d, "
> + "pic_init_qs_minus26 = %d, "
> + "chroma_qp_index_offset = %d, "
> + "second_chroma_qp_index_offset = %d, "
> + "flags = %s",
> __entry->p.pic_parameter_set_id,
> __entry->p.seq_parameter_set_id,
> __entry->p.num_slice_groups_minus1,
> @@ -461,7 +469,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_scaling_matrix_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_scaling_matrix,
> s)),
> TP_fast_assign(__entry->s = *s),
> - TP_printk("\nscaling_list_4x4 {%s}\nscaling_list_8x8 {%s}",
> + TP_printk("scaling_list_4x4 = {%s}, scaling_list_8x8 = {%s}",
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->s.scaling_list_4x4,
> sizeof(__entry->s.scaling_list_4x4),
> @@ -478,16 +486,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
> TP_ARGS(p),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_pred_weights,
> p)),
> TP_fast_assign(__entry->p = *p),
> - TP_printk("\nluma_log2_weight_denom %u\n"
> - "chroma_log2_weight_denom %u\n"
> - "weight_factor[0].luma_weight %s\n"
> - "weight_factor[0].luma_offset %s\n"
> - "weight_factor[0].chroma_weight {%s}\n"
> - "weight_factor[0].chroma_offset {%s}\n"
> - "weight_factor[1].luma_weight %s\n"
> - "weight_factor[1].luma_offset %s\n"
> - "weight_factor[1].chroma_weight {%s}\n"
> - "weight_factor[1].chroma_offset {%s}\n",
> + TP_printk("luma_log2_weight_denom = %u, "
> + "chroma_log2_weight_denom = %u, "
> + "weight_factor[0].luma_weight = %s, "
> + "weight_factor[0].luma_offset = %s, "
> + "weight_factor[0].chroma_weight = {%s}, "
> + "weight_factor[0].chroma_offset = {%s}, "
> + "weight_factor[1].luma_weight = %s, "
> + "weight_factor[1].luma_offset = %s, "
> + "weight_factor[1].chroma_weight = {%s}, "
> + "weight_factor[1].chroma_offset = {%s}",
> __entry->p.luma_log2_weight_denom,
> __entry->p.chroma_log2_weight_denom,
> __print_array(__entry->p.weight_factors[0].luma_weight,
> @@ -526,20 +534,20 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_slice_params,
> s)),
> TP_fast_assign(__entry->s = *s),
> - TP_printk("\nheader_bit_size %u\n"
> - "first_mb_in_slice %u\n"
> - "slice_type %s\n"
> - "colour_plane_id %u\n"
> - "redundant_pic_cnt %u\n"
> - "cabac_init_idc %u\n"
> - "slice_qp_delta %d\n"
> - "slice_qs_delta %d\n"
> - "disable_deblocking_filter_idc %u\n"
> - "slice_alpha_c0_offset_div2 %u\n"
> - "slice_beta_offset_div2 %u\n"
> - "num_ref_idx_l0_active_minus1 %u\n"
> - "num_ref_idx_l1_active_minus1 %u\n"
> - "flags %s",
> + TP_printk("header_bit_size = %u, "
> + "first_mb_in_slice = %u, "
> + "slice_type = %s, "
> + "colour_plane_id = %u, "
> + "redundant_pic_cnt = %u, "
> + "cabac_init_idc = %u, "
> + "slice_qp_delta = %d, "
> + "slice_qs_delta = %d, "
> + "disable_deblocking_filter_idc = %u, "
> + "slice_alpha_c0_offset_div2 = %u, "
> + "slice_beta_offset_div2 = %u, "
> + "num_ref_idx_l0_active_minus1 = %u, "
> + "num_ref_idx_l1_active_minus1 = %u, "
> + "flags = %s",
> __entry->s.header_bit_size,
> __entry->s.first_mb_in_slice,
> __print_symbolic(__entry->s.slice_type,
> @@ -570,7 +578,7 @@ DECLARE_EVENT_CLASS(v4l2_h264_reference_tmpl,
> TP_STRUCT__entry(__field_struct(struct v4l2_h264_reference, r)
> __field(int, i)),
> TP_fast_assign(__entry->r = *r; __entry->i = i;),
> - TP_printk("[%d]: fields %s index %u",
> + TP_printk("[%d]: fields = %s, index = %u",
> __entry->i,
> __print_flags(__entry->r.fields, "|",
> {V4L2_H264_TOP_FIELD_REF, "TOP_FIELD_REF"},
> @@ -585,19 +593,19 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
> TP_ARGS(d),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_decode_params,
> d)),
> TP_fast_assign(__entry->d = *d),
> - TP_printk("\nnal_ref_idc %u\n"
> - "frame_num %u\n"
> - "top_field_order_cnt %d\n"
> - "bottom_field_order_cnt %d\n"
> - "idr_pic_id %u\n"
> - "pic_order_cnt_lsb %u\n"
> - "delta_pic_order_cnt_bottom %d\n"
> - "delta_pic_order_cnt0 %d\n"
> - "delta_pic_order_cnt1 %d\n"
> - "dec_ref_pic_marking_bit_size %u\n"
> - "pic_order_cnt_bit_size %u\n"
> - "slice_group_change_cycle %u\n"
> - "flags %s\n",
> + TP_printk("nal_ref_idc = %u, "
> + "frame_num = %u, "
> + "top_field_order_cnt = %d, "
> + "bottom_field_order_cnt = %d, "
> + "idr_pic_id = %u, "
> + "pic_order_cnt_lsb = %u, "
> + "delta_pic_order_cnt_bottom = %d, "
> + "delta_pic_order_cnt0 = %d, "
> + "delta_pic_order_cnt1 = %d, "
> + "dec_ref_pic_marking_bit_size = %u, "
> + "pic_order_cnt_bit_size = %u, "
> + "slice_group_change_cycle = %u, "
> + "flags = %s",
> __entry->d.nal_ref_idc,
> __entry->d.frame_num,
> __entry->d.top_field_order_cnt,
> @@ -625,8 +633,8 @@ DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
> TP_STRUCT__entry(__field_struct(struct v4l2_h264_dpb_entry, e)
> __field(int, i)),
> TP_fast_assign(__entry->e = *e; __entry->i = i;),
> - TP_printk("[%d]: reference_ts %llu, pic_num %u frame_num %u fields %s
> "
> - "top_field_order_cnt %d bottom_field_order_cnt %d flags
> %s",
> + TP_printk("[%d]: reference_ts = %llu, pic_num = %u, frame_num = %u,
> fields = %s "
> + "top_field_order_cnt = %d, bottom_field_order_cnt = %d,
> flags = %s",
> __entry->i,
> __entry->e.reference_ts,
> __entry->e.pic_num,
> @@ -642,7 +650,6 @@ DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
> {V4L2_H264_DPB_ENTRY_FLAG_ACTIVE, "ACTIVE"},
> {V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM, "LONG_TERM"},
> {V4L2_H264_DPB_ENTRY_FLAG_FIELD, "FIELD"})
> -
> )
> );
>
> @@ -698,31 +705,31 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_sps, s)),
> TP_fast_assign(__entry->s = *s),
> - TP_printk("\nvideo_parameter_set_id %u\n"
> - "seq_parameter_set_id %u\n"
> - "pic_width_in_luma_samples %u\n"
> - "pic_height_in_luma_samples %u\n"
> - "bit_depth_luma_minus8 %u\n"
> - "bit_depth_chroma_minus8 %u\n"
> - "log2_max_pic_order_cnt_lsb_minus4 %u\n"
> - "sps_max_dec_pic_buffering_minus1 %u\n"
> - "sps_max_num_reorder_pics %u\n"
> - "sps_max_latency_increase_plus1 %u\n"
> - "log2_min_luma_coding_block_size_minus3 %u\n"
> - "log2_diff_max_min_luma_coding_block_size %u\n"
> - "log2_min_luma_transform_block_size_minus2 %u\n"
> - "log2_diff_max_min_luma_transform_block_size %u\n"
> - "max_transform_hierarchy_depth_inter %u\n"
> - "max_transform_hierarchy_depth_intra %u\n"
> - "pcm_sample_bit_depth_luma_minus1 %u\n"
> - "pcm_sample_bit_depth_chroma_minus1 %u\n"
> - "log2_min_pcm_luma_coding_block_size_minus3 %u\n"
> - "log2_diff_max_min_pcm_luma_coding_block_size %u\n"
> - "num_short_term_ref_pic_sets %u\n"
> - "num_long_term_ref_pics_sps %u\n"
> - "chroma_format_idc %u\n"
> - "sps_max_sub_layers_minus1 %u\n"
> - "flags %s",
> + TP_printk("video_parameter_set_id = %u, "
> + "seq_parameter_set_id = %u, "
> + "pic_width_in_luma_samples = %u, "
> + "pic_height_in_luma_samples = %u, "
> + "bit_depth_luma_minus8 = %u, "
> + "bit_depth_chroma_minus8 = %u, "
> + "log2_max_pic_order_cnt_lsb_minus4 = %u, "
> + "sps_max_dec_pic_buffering_minus1 = %u, "
> + "sps_max_num_reorder_pics = %u, "
> + "sps_max_latency_increase_plus1 = %u, "
> + "log2_min_luma_coding_block_size_minus3 = %u, "
> + "log2_diff_max_min_luma_coding_block_size = %u, "
> + "log2_min_luma_transform_block_size_minus2 = %u, "
> + "log2_diff_max_min_luma_transform_block_size = %u, "
> + "max_transform_hierarchy_depth_inter = %u, "
> + "max_transform_hierarchy_depth_intra = %u, "
> + "pcm_sample_bit_depth_luma_minus1 = %u, "
> + "pcm_sample_bit_depth_chroma_minus1 = %u, "
> + "log2_min_pcm_luma_coding_block_size_minus3 = %u, "
> + "log2_diff_max_min_pcm_luma_coding_block_size = %u, "
> + "num_short_term_ref_pic_sets = %u, "
> + "num_long_term_ref_pics_sps = %u, "
> + "chroma_format_idc = %u, "
> + "sps_max_sub_layers_minus1 = %u, "
> + "flags = %s",
> __entry->s.video_parameter_set_id,
> __entry->s.seq_parameter_set_id,
> __entry->s.pic_width_in_luma_samples,
> @@ -767,22 +774,22 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
> TP_ARGS(p),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_pps, p)),
> TP_fast_assign(__entry->p = *p),
> - TP_printk("\npic_parameter_set_id %u\n"
> - "num_extra_slice_header_bits %u\n"
> - "num_ref_idx_l0_default_active_minus1 %u\n"
> - "num_ref_idx_l1_default_active_minus1 %u\n"
> - "init_qp_minus26 %d\n"
> - "diff_cu_qp_delta_depth %u\n"
> - "pps_cb_qp_offset %d\n"
> - "pps_cr_qp_offset %d\n"
> - "num_tile_columns_minus1 %d\n"
> - "num_tile_rows_minus1 %d\n"
> - "column_width_minus1 %s\n"
> - "row_height_minus1 %s\n"
> - "pps_beta_offset_div2 %d\n"
> - "pps_tc_offset_div2 %d\n"
> - "log2_parallel_merge_level_minus2 %u\n"
> - "flags %s",
> + TP_printk("pic_parameter_set_id = %u, "
> + "num_extra_slice_header_bits = %u, "
> + "num_ref_idx_l0_default_active_minus1 = %u, "
> + "num_ref_idx_l1_default_active_minus1 = %u, "
> + "init_qp_minus26 = %d, "
> + "diff_cu_qp_delta_depth = %u, "
> + "pps_cb_qp_offset = %d, "
> + "pps_cr_qp_offset = %d, "
> + "num_tile_columns_minus1 = %d, "
> + "num_tile_rows_minus1 = %d, "
> + "column_width_minus1 = %s, "
> + "row_height_minus1 = %s, "
> + "pps_beta_offset_div2 = %d, "
> + "pps_tc_offset_div2 = %d, "
> + "log2_parallel_merge_level_minus2 = %u, "
> + "flags = %s",
> __entry->p.pic_parameter_set_id,
> __entry->p.num_extra_slice_header_bits,
> __entry->p.num_ref_idx_l0_default_active_minus1,
> @@ -834,33 +841,33 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_slice_params,
> s)),
> TP_fast_assign(__entry->s = *s),
> - TP_printk("\nbit_size %u\n"
> - "data_byte_offset %u\n"
> - "num_entry_point_offsets %u\n"
> - "nal_unit_type %u\n"
> - "nuh_temporal_id_plus1 %u\n"
> - "slice_type %u\n"
> - "colour_plane_id %u\n"
> - "slice_pic_order_cnt %d\n"
> - "num_ref_idx_l0_active_minus1 %u\n"
> - "num_ref_idx_l1_active_minus1 %u\n"
> - "collocated_ref_idx %u\n"
> - "five_minus_max_num_merge_cand %u\n"
> - "slice_qp_delta %d\n"
> - "slice_cb_qp_offset %d\n"
> - "slice_cr_qp_offset %d\n"
> - "slice_act_y_qp_offset %d\n"
> - "slice_act_cb_qp_offset %d\n"
> - "slice_act_cr_qp_offset %d\n"
> - "slice_beta_offset_div2 %d\n"
> - "slice_tc_offset_div2 %d\n"
> - "pic_struct %u\n"
> - "slice_segment_addr %u\n"
> - "ref_idx_l0 %s\n"
> - "ref_idx_l1 %s\n"
> - "short_term_ref_pic_set_size %u\n"
> - "long_term_ref_pic_set_size %u\n"
> - "flags %s",
> + TP_printk("bit_size = %u, "
> + "data_byte_offset = %u, "
> + "num_entry_point_offsets = %u, "
> + "nal_unit_type = %u, "
> + "nuh_temporal_id_plus1 = %u, "
> + "slice_type = %u, "
> + "colour_plane_id = %u, "
> + "slice_pic_order_cnt = %d, "
> + "num_ref_idx_l0_active_minus1 = %u, "
> + "num_ref_idx_l1_active_minus1 = %u, "
> + "collocated_ref_idx = %u, "
> + "five_minus_max_num_merge_cand = %u, "
> + "slice_qp_delta = %d, "
> + "slice_cb_qp_offset = %d, "
> + "slice_cr_qp_offset = %d, "
> + "slice_act_y_qp_offset = %d, "
> + "slice_act_cb_qp_offset = %d, "
> + "slice_act_cr_qp_offset = %d, "
> + "slice_beta_offset_div2 = %d, "
> + "slice_tc_offset_div2 = %d, "
> + "pic_struct = %u, "
> + "slice_segment_addr = %u, "
> + "ref_idx_l0 = %s, "
> + "ref_idx_l1 = %s, "
> + "short_term_ref_pic_set_size = %u, "
> + "long_term_ref_pic_set_size = %u, "
> + "flags = %s",
> __entry->s.bit_size,
> __entry->s.data_byte_offset,
> __entry->s.num_entry_point_offsets,
> @@ -911,16 +918,16 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
> TP_ARGS(p),
> TP_STRUCT__entry(__field_struct(struct v4l2_hevc_pred_weight_table,
> p)),
> TP_fast_assign(__entry->p = *p),
> - TP_printk("\ndelta_luma_weight_l0 %s\n"
> - "luma_offset_l0 %s\n"
> - "delta_chroma_weight_l0 {%s}\n"
> - "chroma_offset_l0 {%s}\n"
> - "delta_luma_weight_l1 %s\n"
> - "luma_offset_l1 %s\n"
> - "delta_chroma_weight_l1 {%s}\n"
> - "chroma_offset_l1 {%s}\n"
> - "luma_log2_weight_denom %d\n"
> - "delta_chroma_log2_weight_denom %d\n",
> + TP_printk("delta_luma_weight_l0 = %s, "
> + "luma_offset_l0 = %s, "
> + "delta_chroma_weight_l0 = {%s}, "
> + "chroma_offset_l0 = {%s}, "
> + "delta_luma_weight_l1 = %s, "
> + "luma_offset_l1 = %s, "
> + "delta_chroma_weight_l1 = {%s}, "
> + "chroma_offset_l1 = {%s}, "
> + "luma_log2_weight_denom = %d, "
> + "delta_chroma_log2_weight_denom = %d",
> __print_array(__entry->p.delta_luma_weight_l0,
> ARRAY_SIZE(__entry->p.delta_luma_weight_l0),
> sizeof(__entry->p.delta_luma_weight_l0[0])),
> @@ -959,12 +966,12 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_scaling_matrix_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_scaling_matrix,
> s)),
> TP_fast_assign(__entry->s = *s),
> - TP_printk("\nscaling_list_4x4 {%s}\n"
> - "scaling_list_8x8 {%s}\n"
> - "scaling_list_16x16 {%s}\n"
> - "scaling_list_32x32 {%s}\n"
> - "scaling_list_dc_coef_16x16 %s\n"
> - "scaling_list_dc_coef_32x32 %s\n",
> + TP_printk("scaling_list_4x4 = {%s}, "
> + "scaling_list_8x8 = {%s}, "
> + "scaling_list_16x16 = {%s}, "
> + "scaling_list_32x32 = {%s}, "
> + "scaling_list_dc_coef_16x16 = %s, "
> + "scaling_list_dc_coef_32x32 = %s",
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->s.scaling_list_4x4,
> sizeof(__entry->s.scaling_list_4x4),
> @@ -994,17 +1001,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
> TP_ARGS(d),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_decode_params,
> d)),
> TP_fast_assign(__entry->d = *d),
> - TP_printk("\npic_order_cnt_val %d\n"
> - "short_term_ref_pic_set_size %u\n"
> - "long_term_ref_pic_set_size %u\n"
> - "num_active_dpb_entries %u\n"
> - "num_poc_st_curr_before %u\n"
> - "num_poc_st_curr_after %u\n"
> - "num_poc_lt_curr %u\n"
> - "poc_st_curr_before %s\n"
> - "poc_st_curr_after %s\n"
> - "poc_lt_curr %s\n"
> - "flags %s",
> + TP_printk("pic_order_cnt_val = %d, "
> + "short_term_ref_pic_set_size = %u, "
> + "long_term_ref_pic_set_size = %u, "
> + "num_active_dpb_entries = %u, "
> + "num_poc_st_curr_before = %u, "
> + "num_poc_st_curr_after = %u, "
> + "num_poc_lt_curr = %u, "
> + "poc_st_curr_before = %s, "
> + "poc_st_curr_after = %s, "
> + "poc_lt_curr = %s, "
> + "flags = %s",
> __entry->d.pic_order_cnt_val,
> __entry->d.short_term_ref_pic_set_size,
> __entry->d.long_term_ref_pic_set_size,
> @@ -1033,8 +1040,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl,
> TP_ARGS(lt),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_ext_sps_lt_rps,
> lt)),
> TP_fast_assign(__entry->lt = *lt),
> - TP_printk("\nflags %s\n"
> - "lt_ref_pic_poc_lsb_sps %x\n",
> + TP_printk("flags = %s, "
> + "lt_ref_pic_poc_lsb_sps = %x",
> __print_flags(__entry->lt.flags, "|",
> {V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT, "USED_LT"}
> ),
> @@ -1047,16 +1054,16 @@
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
> TP_ARGS(st),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_ext_sps_st_rps,
> st)),
> TP_fast_assign(__entry->st = *st),
> - TP_printk("\nflags %s\n"
> - "delta_idx_minus1: %u\n"
> - "delta_rps_sign: %u\n"
> - "abs_delta_rps_minus1: %u\n"
> - "num_negative_pics: %u\n"
> - "num_positive_pics: %u\n"
> - "used_by_curr_pic: %08x\n"
> - "use_delta_flag: %08x\n"
> - "delta_poc_s0_minus1: %s\n"
> - "delta_poc_s1_minus1: %s\n",
> + TP_printk("flags = %s, "
> + "delta_idx_minus1 = %u, "
> + "delta_rps_sign = %u, "
> + "abs_delta_rps_minus1 = %u, "
> + "num_negative_pics = %u, "
> + "num_positive_pics = %u, "
> + "used_by_curr_pic = %08x, "
> + "use_delta_flag = %08x, "
> + "delta_poc_s0_minus1 = %s, "
> + "delta_poc_s1_minus1 = %s",
> __print_flags(__entry->st.flags, "|",
> {V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED,
> "INTER_REF_PIC_SET_PRED"}
> ),
> @@ -1081,10 +1088,10 @@ DECLARE_EVENT_CLASS(v4l2_hevc_dpb_entry_tmpl,
> TP_ARGS(e),
> TP_STRUCT__entry(__field_struct(struct v4l2_hevc_dpb_entry, e)),
> TP_fast_assign(__entry->e = *e),
> - TP_printk("\ntimestamp %llu\n"
> - "flags %s\n"
> - "field_pic %u\n"
> - "pic_order_cnt_val %d\n",
> + TP_printk("timestamp = %llu, "
> + "flags = %s, "
> + "field_pic = %u, "
> + "pic_order_cnt_val = %d",
> __entry->e.timestamp,
> __print_flags(__entry->e.flags, "|",
> {V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE,
> "LONG_TERM_REFERENCE"}
> @@ -1145,8 +1152,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_seq_tmpl,
> TP_ARGS(s),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_mpeg2_sequence, s)),
> TP_fast_assign(__entry->s = *s;),
> - TP_printk("\nhorizontal_size %u\nvertical_size %u\nvbv_buffer_size
> %u\n"
> - "profile_and_level_indication %u\nchroma_format %u\nflags
> %s\n",
> + TP_printk("horizontal_size = %u, vertical_size = %u, vbv_buffer_size
> = %u, "
> + "profile_and_level_indication = %u, chroma_format = %u,
> flags = %s",
> __entry->s.horizontal_size,
> __entry->s.vertical_size,
> __entry->s.vbv_buffer_size,
> @@ -1162,8 +1169,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_pic_tmpl,
> TP_ARGS(p),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_mpeg2_picture, p)),
> TP_fast_assign(__entry->p = *p;),
> - TP_printk("\nbackward_ref_ts %llu\nforward_ref_ts %llu\nflags
> %s\nf_code {%s}\n"
> - "picture_coding_type: %u\npicture_structure
> %u\nintra_dc_precision %u\n",
> + TP_printk("backward_ref_ts = %llu, forward_ref_ts = %llu, flags = %s,
> f_code = {%s}, "
> + "picture_coding_type = %u, picture_structure = %u,
> intra_dc_precision = %u",
> __entry->p.backward_ref_ts,
> __entry->p.forward_ref_ts,
> __print_flags(__entry->p.flags, "|",
> @@ -1190,8 +1197,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_quant_tmpl,
> TP_ARGS(q),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_mpeg2_quantisation,
> q)),
> TP_fast_assign(__entry->q = *q;),
> - TP_printk("\nintra_quantiser_matrix %s\nnon_intra_quantiser_matrix
> %s\n"
> - "chroma_intra_quantiser_matrix
> %s\nchroma_non_intra_quantiser_matrix %s\n",
> + TP_printk("intra_quantiser_matrix = %s, non_intra_quantiser_matrix =
> %s, "
> + "chroma_intra_quantiser_matrix = %s,
> chroma_non_intra_quantiser_matrix = %s",
> __print_array(__entry->q.intra_quantiser_matrix,
> ARRAY_SIZE(__entry-
> >q.intra_quantiser_matrix),
> sizeof(__entry-
> >q.intra_quantiser_matrix[0])),
> @@ -1229,10 +1236,10 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_entropy_tmpl,
> TP_ARGS(f),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp8_frame, f)),
> TP_fast_assign(__entry->f = *f;),
> - TP_printk("\nentropy.coeff_probs {%s}\n"
> - "entropy.y_mode_probs %s\n"
> - "entropy.uv_mode_probs %s\n"
> - "entropy.mv_probs {%s}",
> + TP_printk("entropy.coeff_probs = {%s}, "
> + "entropy.y_mode_probs = %s, "
> + "entropy.uv_mode_probs = %s, "
> + "entropy.mv_probs = {%s}",
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->f.entropy.coeff_probs,
> sizeof(__entry->f.entropy.coeff_probs),
> @@ -1255,41 +1262,41 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
> TP_ARGS(f),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp8_frame, f)),
> TP_fast_assign(__entry->f = *f;),
> - TP_printk("\nsegment.quant_update %s\n"
> - "segment.lf_update %s\n"
> - "segment.segment_probs %s\n"
> - "segment.flags %s\n"
> - "lf.ref_frm_delta %s\n"
> - "lf.mb_mode_delta %s\n"
> - "lf.sharpness_level %u\n"
> - "lf.level %u\n"
> - "lf.flags %s\n"
> - "quant.y_ac_qi %u\n"
> - "quant.y_dc_delta %d\n"
> - "quant.y2_dc_delta %d\n"
> - "quant.y2_ac_delta %d\n"
> - "quant.uv_dc_delta %d\n"
> - "quant.uv_ac_delta %d\n"
> - "coder_state.range %u\n"
> - "coder_state.value %u\n"
> - "coder_state.bit_count %u\n"
> - "width %u\n"
> - "height %u\n"
> - "horizontal_scale %u\n"
> - "vertical_scale %u\n"
> - "version %u\n"
> - "prob_skip_false %u\n"
> - "prob_intra %u\n"
> - "prob_last %u\n"
> - "prob_gf %u\n"
> - "num_dct_parts %u\n"
> - "first_part_size %u\n"
> - "first_part_header_bits %u\n"
> - "dct_part_sizes %s\n"
> - "last_frame_ts %llu\n"
> - "golden_frame_ts %llu\n"
> - "alt_frame_ts %llu\n"
> - "flags %s",
> + TP_printk("segment.quant_update = %s, "
> + "segment.lf_update = %s, "
> + "segment.segment_probs = %s, "
> + "segment.flags = %s, "
> + "lf.ref_frm_delta = %s, "
> + "lf.mb_mode_delta = %s, "
> + "lf.sharpness_level = %u, "
> + "lf.level = %u, "
> + "lf.flags = %s, "
> + "quant.y_ac_qi = %u, "
> + "quant.y_dc_delta = %d, "
> + "quant.y2_dc_delta = %d, "
> + "quant.y2_ac_delta = %d, "
> + "quant.uv_dc_delta = %d, "
> + "quant.uv_ac_delta = %d, "
> + "coder_state.range = %u, "
> + "coder_state.value = %u, "
> + "coder_state.bit_count = %u, "
> + "width = %u, "
> + "height = %u, "
> + "horizontal_scale = %u, "
> + "vertical_scale = %u, "
> + "version = %u, "
> + "prob_skip_false = %u, "
> + "prob_intra = %u, "
> + "prob_last = %u, "
> + "prob_gf = %u, "
> + "num_dct_parts = %u, "
> + "first_part_size = %u, "
> + "first_part_header_bits = %u, "
> + "dct_part_sizes = %s, "
> + "last_frame_ts = %llu, "
> + "golden_frame_ts = %llu, "
> + "alt_frame_ts = %llu, "
> + "flags = %s",
> __print_array(__entry->f.segment.quant_update,
> ARRAY_SIZE(__entry->f.segment.quant_update),
> sizeof(__entry->f.segment.quant_update[0])),
> @@ -1370,39 +1377,39 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
> TP_ARGS(f),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp9_frame, f)),
> TP_fast_assign(__entry->f = *f;),
> - TP_printk("\nlf.ref_deltas %s\n"
> - "lf.mode_deltas %s\n"
> - "lf.level %u\n"
> - "lf.sharpness %u\n"
> - "lf.flags %s\n"
> - "quant.base_q_idx %u\n"
> - "quant.delta_q_y_dc %d\n"
> - "quant.delta_q_uv_dc %d\n"
> - "quant.delta_q_uv_ac %d\n"
> - "seg.feature_data {%s}\n"
> - "seg.feature_enabled %s\n"
> - "seg.tree_probs %s\n"
> - "seg.pred_probs %s\n"
> - "seg.flags %s\n"
> - "flags %s\n"
> - "compressed_header_size %u\n"
> - "uncompressed_header_size %u\n"
> - "frame_width_minus_1 %u\n"
> - "frame_height_minus_1 %u\n"
> - "render_width_minus_1 %u\n"
> - "render_height_minus_1 %u\n"
> - "last_frame_ts %llu\n"
> - "golden_frame_ts %llu\n"
> - "alt_frame_ts %llu\n"
> - "ref_frame_sign_bias %s\n"
> - "reset_frame_context %s\n"
> - "frame_context_idx %u\n"
> - "profile %u\n"
> - "bit_depth %u\n"
> - "interpolation_filter %s\n"
> - "tile_cols_log2 %u\n"
> - "tile_rows_log_2 %u\n"
> - "reference_mode %s\n",
> + TP_printk("lf.ref_deltas = %s, "
> + "lf.mode_deltas = %s, "
> + "lf.level = %u, "
> + "lf.sharpness = %u, "
> + "lf.flags = %s, "
> + "quant.base_q_idx = %u, "
> + "quant.delta_q_y_dc = %d, "
> + "quant.delta_q_uv_dc = %d, "
> + "quant.delta_q_uv_ac = %d, "
> + "seg.feature_data = {%s}, "
> + "seg.feature_enabled = %s, "
> + "seg.tree_probs = %s, "
> + "seg.pred_probs = %s, "
> + "seg.flags = %s, "
> + "flags = %s, "
> + "compressed_header_size = %u, "
> + "uncompressed_header_size = %u, "
> + "frame_width_minus_1 = %u, "
> + "frame_height_minus_1 = %u, "
> + "render_width_minus_1 = %u, "
> + "render_height_minus_1 = %u, "
> + "last_frame_ts = %llu, "
> + "golden_frame_ts = %llu, "
> + "alt_frame_ts = %llu, "
> + "ref_frame_sign_bias = %s, "
> + "reset_frame_context = %s, "
> + "frame_context_idx = %u, "
> + "profile = %u, "
> + "bit_depth = %u, "
> + "interpolation_filter = %s, "
> + "tile_cols_log2 = %u, "
> + "tile_rows_log_2 = %u, "
> + "reference_mode = %s",
> __print_array(__entry->f.lf.ref_deltas,
> ARRAY_SIZE(__entry->f.lf.ref_deltas),
> sizeof(__entry->f.lf.ref_deltas[0])),
> @@ -1487,20 +1494,20 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
> TP_ARGS(h),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp9_compressed_hdr,
> h)),
> TP_fast_assign(__entry->h = *h;),
> - TP_printk("\ntx_mode %s\n"
> - "tx8 {%s}\n"
> - "tx16 {%s}\n"
> - "tx32 {%s}\n"
> - "skip %s\n"
> - "inter_mode {%s}\n"
> - "interp_filter {%s}\n"
> - "is_inter %s\n"
> - "comp_mode %s\n"
> - "single_ref {%s}\n"
> - "comp_ref %s\n"
> - "y_mode {%s}\n"
> - "uv_mode {%s}\n"
> - "partition {%s}\n",
> + TP_printk("tx_mode = %s, "
> + "tx8 = {%s}, "
> + "tx16 = {%s}, "
> + "tx32 = {%s}, "
> + "skip = %s, "
> + "inter_mode = {%s}, "
> + "interp_filter = {%s}, "
> + "is_inter = %s, "
> + "comp_mode = %s, "
> + "single_ref = {%s}, "
> + "comp_ref = %s, "
> + "y_mode = {%s}, "
> + "uv_mode = {%s}, "
> + "partition = {%s}",
> __print_symbolic(__entry->h.tx_mode,
> {V4L2_VP9_TX_MODE_ONLY_4X4, "TX_MODE_ONLY_4X4"},
> {V4L2_VP9_TX_MODE_ALLOW_8X8, "TX_MODE_ALLOW_8X8"},
> @@ -1563,7 +1570,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_coef_tmpl,
> TP_ARGS(h),
> TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp9_compressed_hdr,
> h)),
> TP_fast_assign(__entry->h = *h;),
> - TP_printk("\n coef {%s}",
> + TP_printk("coef = {%s}",
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->h.coef,
> sizeof(__entry->h.coef),
> @@ -1576,15 +1583,15 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
> TP_ARGS(p),
> TP_STRUCT__entry(__field_struct(struct v4l2_vp9_mv_probs, p)),
> TP_fast_assign(__entry->p = *p;),
> - TP_printk("\n joint %s\n"
> - "sign %s\n"
> - "classes {%s}\n"
> - "class0_bit %s\n"
> - "bits {%s}\n"
> - "class0_fr {%s}\n"
> - "fr {%s}\n"
> - "class0_hp %s\n"
> - "hp %s\n",
> + TP_printk("joint = %s, "
> + "sign = %s, "
> + "classes = {%s}, "
> + "class0_bit = %s, "
> + "bits = {%s}, "
> + "class0_fr = {%s}, "
> + "fr = {%s}, "
> + "class0_hp = %s, "
> + "hp = %s",
> __print_array(__entry->p.joint,
> ARRAY_SIZE(__entry->p.joint),
> sizeof(__entry->p.joint[0])),
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 03/11] media: Add tgid and fd fields in v4l2_fh struct
From: Nicolas Dufresne @ 2026-04-28 19:31 UTC (permalink / raw)
To: Detlev Casanova, linux-kernel
Cc: Benjamin Gaignard, Philipp Zabel, Mauro Carvalho Chehab,
Heiko Stuebner, Daniel Almeida, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Hans Verkuil, Laurent Pinchart,
Ricardo Ribalda, Yunke Cao, Sakari Ailus, Pavan Bobba,
James Cowgill, Ma Ke, Jacopo Mondi, Daniel Scally, linux-media,
linux-rockchip, linux-arm-kernel, linux-trace-kernel, kernel
In-Reply-To: <20260212162328.192217-4-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 3783 bytes --]
Le jeudi 12 février 2026 à 11:23 -0500, Detlev Casanova a écrit :
> These fields will be used in traces to help userspace tracing tools
> identify streams.
>
> The tgid field will keep the PID of the process that opened the video
> file.
> That is needed because trace calls can happen in IRQs, for which there is
> no current PID.
>
> The fd field helps identify the context in case the same process opens the
> video device multiple times.
> Note that the fd field is set in the __video_do_ioctl() function.
> That is because the file descriptor has not been allocated yet when
> v4l2_open() is called.
Unless someone have a better idea with this last part (in this case please
reply):
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
> ---
> drivers/media/v4l2-core/v4l2-fh.c | 1 +
> drivers/media/v4l2-core/v4l2-ioctl.c | 17 +++++++++++++++++
> include/media/v4l2-fh.h | 4 ++++
> 3 files changed, 22 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-
> fh.c
> index df3ba9d4674b..86e8223b46cb 100644
> --- a/drivers/media/v4l2-core/v4l2-fh.c
> +++ b/drivers/media/v4l2-core/v4l2-fh.c
> @@ -37,6 +37,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device
> *vdev)
> INIT_LIST_HEAD(&fh->available);
> INIT_LIST_HEAD(&fh->subscribed);
> fh->sequence = -1;
> + fh->tgid = current->tgid;
> mutex_init(&fh->subscribe_lock);
> }
> EXPORT_SYMBOL_GPL(v4l2_fh_init);
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-
> core/v4l2-ioctl.c
> index 37d33d4a363d..a3b6df0571d6 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -9,6 +9,7 @@
> */
>
> #include <linux/compat.h>
> +#include <linux/fdtable.h>
> #include <linux/mm.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> @@ -3061,6 +3062,16 @@ void v4l_printk_ioctl(const char *prefix, unsigned int
> cmd)
> }
> EXPORT_SYMBOL(v4l_printk_ioctl);
>
> +static int _file_iterate(const void *priv, struct file *filp, unsigned int
> fd)
> +{
> + const struct file *fh_filp = priv;
> +
> + if (fh_filp == filp)
> + return fd;
> +
> + return 0;
> +}
> +
> static long __video_do_ioctl(struct file *file,
> unsigned int cmd, void *arg)
> {
> @@ -3081,6 +3092,12 @@ static long __video_do_ioctl(struct file *file,
> return ret;
> }
>
> + if (unlikely(!vfh->fd)) {
> + vfh->fd = iterate_fd(current->files, 0, _file_iterate, file);
> + if (!vfh->fd)
> + vfh->fd = -1;
> + }
> +
> /*
> * We need to serialize streamon/off with queueing new requests.
> * These ioctls may trigger the cancellation of a streaming
> diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h
> index aad4b3689d7e..4ef4e58ab8d1 100644
> --- a/include/media/v4l2-fh.h
> +++ b/include/media/v4l2-fh.h
> @@ -28,6 +28,8 @@ struct v4l2_ctrl_handler;
> * @vdev: pointer to &struct video_device
> * @ctrl_handler: pointer to &struct v4l2_ctrl_handler
> * @prio: priority of the file handler, as defined by &enum v4l2_priority
> + * @tgid: process id that initialized the v4l2_fh
> + * @fd: file descriptor associated to this v4l2_fh for the process id in tgid
> *
> * @wait: event' s wait queue
> * @subscribe_lock: serialise changes to the subscribed list; guarantee that
> @@ -44,6 +46,8 @@ struct v4l2_fh {
> struct video_device *vdev;
> struct v4l2_ctrl_handler *ctrl_handler;
> enum v4l2_priority prio;
> + uint32_t tgid;
> + int fd;
>
> /* Events */
> wait_queue_head_t wait;
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 04/11] media: Add tgid and fd to the v4l2-requests trace fields
From: Nicolas Dufresne @ 2026-04-28 19:32 UTC (permalink / raw)
To: Detlev Casanova, linux-kernel
Cc: Benjamin Gaignard, Philipp Zabel, Mauro Carvalho Chehab,
Heiko Stuebner, Daniel Almeida, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Hans Verkuil, Laurent Pinchart,
Ricardo Ribalda, Yunke Cao, Sakari Ailus, Pavan Bobba,
James Cowgill, Ma Ke, Jacopo Mondi, Daniel Scally, linux-media,
linux-rockchip, linux-arm-kernel, linux-trace-kernel, kernel
In-Reply-To: <20260212162328.192217-5-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 53197 bytes --]
Le jeudi 12 février 2026 à 11:23 -0500, Detlev Casanova a écrit :
> With these fields, userspace can better track which trace event matches
> with a given stream.
>
> Even though the trace shows the PID (based on current->tgid), trace
> functions could be called from other contexts, therefore showing the wrong
> PID, or none at all.
>
> These will ensure that the trace event can be matched with the PID/FD that
> opened and configured the video device file.
>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> ---
> drivers/media/test-drivers/visl/visl-dec.c | 68 +--
> include/trace/events/v4l2_requests.h | 622 +++++++++++++--------
> 2 files changed, 439 insertions(+), 251 deletions(-)
>
> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
> index d49208e83726..fc216da17048 100644
> --- a/drivers/media/test-drivers/visl/visl-dec.c
> +++ b/drivers/media/test-drivers/visl/visl-dec.c
> @@ -489,67 +489,71 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
> static void visl_trace_ctrls(struct visl_ctx *ctx, struct visl_run *run)
> {
> int i;
> + struct v4l2_fh *fh = &ctx->fh;
>
> switch (ctx->current_codec) {
> default:
> case VISL_CODEC_NONE:
> break;
> case VISL_CODEC_FWHT:
> - trace_v4l2_ctrl_fwht_params(run->fwht.params);
> + trace_v4l2_ctrl_fwht_params(fh->tgid, fh->fd, run->fwht.params);
> break;
> case VISL_CODEC_MPEG2:
> - trace_v4l2_ctrl_mpeg2_sequence(run->mpeg2.seq);
> - trace_v4l2_ctrl_mpeg2_picture(run->mpeg2.pic);
> - trace_v4l2_ctrl_mpeg2_quantisation(run->mpeg2.quant);
> + trace_v4l2_ctrl_mpeg2_sequence(fh->tgid, fh->fd, run->mpeg2.seq);
> + trace_v4l2_ctrl_mpeg2_picture(fh->tgid, fh->fd, run->mpeg2.pic);
> + trace_v4l2_ctrl_mpeg2_quantisation(fh->tgid, fh->fd, run->mpeg2.quant);
> break;
> case VISL_CODEC_VP8:
> - trace_v4l2_ctrl_vp8_frame(run->vp8.frame);
> - trace_v4l2_ctrl_vp8_entropy(run->vp8.frame);
> + trace_v4l2_ctrl_vp8_frame(fh->tgid, fh->fd, run->vp8.frame);
> + trace_v4l2_ctrl_vp8_entropy(fh->tgid, fh->fd, run->vp8.frame);
> break;
> case VISL_CODEC_VP9:
> - trace_v4l2_ctrl_vp9_frame(run->vp9.frame);
> - trace_v4l2_ctrl_vp9_compressed_hdr(run->vp9.probs);
> - trace_v4l2_ctrl_vp9_compressed_coeff(run->vp9.probs);
> - trace_v4l2_vp9_mv_probs(&run->vp9.probs->mv);
> + trace_v4l2_ctrl_vp9_frame(fh->tgid, fh->fd, run->vp9.frame);
> + trace_v4l2_ctrl_vp9_compressed_hdr(fh->tgid, fh->fd, run->vp9.probs);
> + trace_v4l2_ctrl_vp9_compressed_coeff(fh->tgid, fh->fd, run->vp9.probs);
> + trace_v4l2_vp9_mv_probs(fh->tgid, fh->fd, &run->vp9.probs->mv);
> break;
> case VISL_CODEC_H264:
> - trace_v4l2_ctrl_h264_sps(run->h264.sps);
> - trace_v4l2_ctrl_h264_pps(run->h264.pps);
> - trace_v4l2_ctrl_h264_scaling_matrix(run->h264.sm);
> - trace_v4l2_ctrl_h264_slice_params(run->h264.spram);
> + trace_v4l2_ctrl_h264_sps(fh->tgid, fh->fd, run->h264.sps);
> + trace_v4l2_ctrl_h264_pps(fh->tgid, fh->fd, run->h264.pps);
> + trace_v4l2_ctrl_h264_scaling_matrix(fh->tgid, fh->fd, run->h264.sm);
> + trace_v4l2_ctrl_h264_slice_params(fh->tgid, fh->fd, run->h264.spram);
>
> for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
> - trace_v4l2_h264_ref_pic_list0(&run->h264.spram->ref_pic_list0[i], i);
> + trace_v4l2_h264_ref_pic_list0(fh->tgid, fh->fd,
> + &run->h264.spram->ref_pic_list0[i], i);
> for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
> - trace_v4l2_h264_ref_pic_list1(&run->h264.spram->ref_pic_list1[i], i);
> + trace_v4l2_h264_ref_pic_list1(fh->tgid, fh->fd,
> + &run->h264.spram->ref_pic_list1[i], i);
>
> - trace_v4l2_ctrl_h264_decode_params(run->h264.dpram);
> + trace_v4l2_ctrl_h264_decode_params(fh->tgid, fh->fd, run->h264.dpram);
>
> for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++)
> - trace_v4l2_h264_dpb_entry(&run->h264.dpram->dpb[i], i);
> + trace_v4l2_h264_dpb_entry(fh->tgid, fh->fd, &run->h264.dpram->dpb[i], i);
>
> - trace_v4l2_ctrl_h264_pred_weights(run->h264.pwht);
> + trace_v4l2_ctrl_h264_pred_weights(fh->tgid, fh->fd, run->h264.pwht);
> break;
> case VISL_CODEC_HEVC:
> - trace_v4l2_ctrl_hevc_sps(run->hevc.sps);
> - trace_v4l2_ctrl_hevc_pps(run->hevc.pps);
> - trace_v4l2_ctrl_hevc_slice_params(run->hevc.spram);
> - trace_v4l2_ctrl_hevc_scaling_matrix(run->hevc.sm);
> - trace_v4l2_ctrl_hevc_decode_params(run->hevc.dpram);
> + trace_v4l2_ctrl_hevc_sps(fh->tgid, fh->fd, run->hevc.sps);
> + trace_v4l2_ctrl_hevc_pps(fh->tgid, fh->fd, run->hevc.pps);
> + trace_v4l2_ctrl_hevc_slice_params(fh->tgid, fh->fd, run->hevc.spram);
> + trace_v4l2_ctrl_hevc_scaling_matrix(fh->tgid, fh->fd, run->hevc.sm);
> + trace_v4l2_ctrl_hevc_decode_params(fh->tgid, fh->fd, run->hevc.dpram);
>
> for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++)
> - trace_v4l2_hevc_dpb_entry(&run->hevc.dpram->dpb[i]);
> + trace_v4l2_hevc_dpb_entry(fh->tgid, fh->fd, &run->hevc.dpram->dpb[i]);
>
> - trace_v4l2_hevc_pred_weight_table(&run->hevc.spram->pred_weight_table);
> - trace_v4l2_ctrl_hevc_ext_sps_lt_rps(run->hevc.rps_lt);
> - trace_v4l2_ctrl_hevc_ext_sps_st_rps(run->hevc.rps_st);
>
> + trace_v4l2_hevc_pred_weight_table(fh->tgid, fh->fd,
> + &run->hevc.spram->pred_weight_table);
> + trace_v4l2_ctrl_hevc_ext_sps_lt_rps(fh->tgid, fh->fd, run->hevc.rps_lt);
> + trace_v4l2_ctrl_hevc_ext_sps_st_rps(fh->tgid, fh->fd, run->hevc.rps_st);
> break;
> case VISL_CODEC_AV1:
> - trace_v4l2_ctrl_av1_sequence(run->av1.seq);
> - trace_v4l2_ctrl_av1_frame(run->av1.frame);
> - trace_v4l2_ctrl_av1_film_grain(run->av1.grain);
> - trace_v4l2_ctrl_av1_tile_group_entry(run->av1.tge);
> + trace_v4l2_ctrl_av1_sequence(fh->tgid, fh->fd, run->av1.seq);
> + trace_v4l2_ctrl_av1_frame(fh->tgid, fh->fd, run->av1.frame);
> + trace_v4l2_ctrl_av1_film_grain(fh->tgid, fh->fd, run->av1.grain);
> + trace_v4l2_ctrl_av1_tile_group_entry(fh->tgid, fh->fd, run->av1.tge);
> break;
> }
> }
> diff --git a/include/trace/events/v4l2_requests.h b/include/trace/events/v4l2_requests.h
> index 34f4a74df5ea..ab6718f40e28 100644
> --- a/include/trace/events/v4l2_requests.h
> +++ b/include/trace/events/v4l2_requests.h
> @@ -10,12 +10,18 @@
>
> /* AV1 controls */
> DECLARE_EVENT_CLASS(v4l2_ctrl_av1_seq_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_av1_sequence *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_sequence, s)),
> - TP_fast_assign(__entry->s = *s;),
> - TP_printk("flags = %s, seq_profile = %u, order_hint_bits = %u, bit_depth = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_sequence *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_av1_sequence, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s;),
> + TP_printk("tgid = %u, fd = %u, "
> + "flags = %s, seq_profile = %u, order_hint_bits = %u, bit_depth = %u, "
> "max_frame_width_minus_1 = %u, max_frame_height_minus_1 = %u",
> + __entry->tgid, __entry->fd,
> __print_flags(__entry->s.flags, "|",
> {V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE, "STILL_PICTURE"},
> {V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK, "USE_128X128_SUPERBLOCK"},
> @@ -46,11 +52,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_seq_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_av1_tge_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_av1_tile_group_entry *t),
> - TP_ARGS(t),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_tile_group_entry, t)),
> - TP_fast_assign(__entry->t = *t;),
> - TP_printk("tile_offset = %u, tile_size = %u, tile_row = %u, tile_col = %u",
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_tile_group_entry *t),
> + TP_ARGS(tgid, fd, t),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_av1_tile_group_entry, t)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->t = *t;),
> + TP_printk("tgid = %u, fd = %u, "
> + "tile_offset = %u, tile_size = %u, tile_row = %u, tile_col = %u",
> + __entry->tgid, __entry->fd,
> __entry->t.tile_offset,
> __entry->t.tile_size,
> __entry->t.tile_row,
> @@ -59,11 +71,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_tge_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_av1_frame *f),
> - TP_ARGS(f),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_frame, f)),
> - TP_fast_assign(__entry->f = *f;),
> - TP_printk("tile_info.flags = %s, tile_info.context_update_tile_id = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_frame *f),
> + TP_ARGS(tgid, fd, f),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_av1_frame, f)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->f = *f;),
> + TP_printk("tgid = %u, fd = %u, "
> + "tile_info.flags = %s, tile_info.context_update_tile_id = %u, "
> "tile_info.tile_cols = %u, tile_info.tile_rows = %u, "
> "tile_info.mi_col_starts = %s, tile_info.mi_row_starts = %s, "
> "tile_info.width_in_sbs_minus_1 = %s, tile_info.height_in_sbs_minus_1 = %s, "
> @@ -87,6 +104,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
> "render_width_minus_1 = %u, render_height_minus_1 = %u, current_frame_id = %u, "
> "buffer_removal_time = %s, order_hints = %s, reference_frame_ts = %s, "
> "ref_frame_idx = %s, refresh_frame_flags = %u",
> + __entry->tgid, __entry->fd,
> __print_flags(__entry->f.tile_info.flags, "|",
> {V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING, "UNIFORM_TILE_SPACING"}),
> __entry->f.tile_info.context_update_tile_id,
> @@ -222,11 +240,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_frame_tmpl,
>
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_av1_film_grain *f),
> - TP_ARGS(f),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_av1_film_grain, f)),
> - TP_fast_assign(__entry->f = *f;),
> - TP_printk("flags = %s, cr_mult = %u, grain_seed = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_film_grain *f),
> + TP_ARGS(tgid, fd, f),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_av1_film_grain, f)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->f = *f;),
> + TP_printk("tgid = %u, fd = %u, "
> + "flags = %s, cr_mult = %u, grain_seed = %u, "
> "film_grain_params_ref_idx = %u, num_y_points = %u, point_y_value = %s, "
> "point_y_scaling = %s, num_cb_points = %u, point_cb_value = %s, "
> "point_cb_scaling = %s, num_cr_points = %u, point_cr_value = %s, "
> @@ -235,6 +258,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
> "ar_coeffs_cr_plus_128 = %s, ar_coeff_shift_minus_6 = %u, "
> "grain_scale_shift = %u, cb_mult = %u, cb_luma_mult = %u, cr_luma_mult = %u, "
> "cb_offset = %u, cr_offset = %u",
> + __entry->tgid, __entry->fd,
> __print_flags(__entry->f.flags, "|",
> {V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN, "APPLY_GRAIN"},
> {V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN, "UPDATE_GRAIN"},
> @@ -287,31 +311,32 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_av1_film_grain_tmpl,
> )
>
> DEFINE_EVENT(v4l2_ctrl_av1_seq_tmpl, v4l2_ctrl_av1_sequence,
> - TP_PROTO(const struct v4l2_ctrl_av1_sequence *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_sequence *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_ctrl_av1_frame_tmpl, v4l2_ctrl_av1_frame,
> - TP_PROTO(const struct v4l2_ctrl_av1_frame *f),
> - TP_ARGS(f)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_frame *f),
> + TP_ARGS(tgid, fd, f)
> );
>
> DEFINE_EVENT(v4l2_ctrl_av1_tge_tmpl, v4l2_ctrl_av1_tile_group_entry,
> - TP_PROTO(const struct v4l2_ctrl_av1_tile_group_entry *t),
> - TP_ARGS(t)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_tile_group_entry *t),
> + TP_ARGS(tgid, fd, t)
> );
>
> DEFINE_EVENT(v4l2_ctrl_av1_film_grain_tmpl, v4l2_ctrl_av1_film_grain,
> - TP_PROTO(const struct v4l2_ctrl_av1_film_grain *f),
> - TP_ARGS(f)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_av1_film_grain *f),
> + TP_ARGS(tgid, fd, f)
> );
>
> /* FWHT controls */
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_fwht_params *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_fwht_params *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> __field(u64, backward_ref_ts)
> __field(u32, version)
> __field(u32, width)
> @@ -322,7 +347,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
> __field(u32, ycbcr_enc)
> __field(u32, quantization)
> ),
> - TP_fast_assign(
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> __entry->backward_ref_ts = p->backward_ref_ts;
> __entry->version = p->version;
> __entry->width = p->width;
> @@ -333,7 +359,8 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
> __entry->ycbcr_enc = p->ycbcr_enc;
> __entry->quantization = p->quantization;
> ),
> - TP_printk("backward_ref_ts = %llu, "
> + TP_printk("tgid = %u, fd = %u, "
> + "backward_ref_ts = %llu, "
> "version = %u, "
> "width = %u, "
> "height = %u, "
> @@ -342,6 +369,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
> "xfer_func = %u, "
> "ycbcr_enc = %u, "
> "quantization = %u",
> + __entry->tgid, __entry->fd,
> __entry->backward_ref_ts, __entry->version, __entry->width, __entry->height,
> __print_flags(__entry->flags, "|",
> {V4L2_FWHT_FL_IS_INTERLACED, "IS_INTERLACED"},
> @@ -361,18 +389,23 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_fwht_params_tmpl,
> );
>
> DEFINE_EVENT(v4l2_ctrl_fwht_params_tmpl, v4l2_ctrl_fwht_params,
> - TP_PROTO(const struct v4l2_ctrl_fwht_params *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_fwht_params *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> /* H264 controls */
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_h264_sps *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_sps, s)),
> - TP_fast_assign(__entry->s = *s),
> - TP_printk("profile_idc = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_sps *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_h264_sps, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s),
> + TP_printk("tgid = %u, fd = %u, "
> + "profile_idc = %u, "
> "constraint_set_flags = %s, "
> "level_idc = %u, "
> "seq_parameter_set_id = %u, "
> @@ -390,6 +423,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
> "pic_width_in_mbs_minus1 = %u, "
> "pic_height_in_map_units_minus1 = %u, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->s.profile_idc,
> __print_flags(__entry->s.constraint_set_flags, "|",
> {V4L2_H264_SPS_CONSTRAINT_SET0_FLAG, "CONSTRAINT_SET0_FLAG"},
> @@ -427,11 +461,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_sps_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_h264_pps *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_pps, p)),
> - TP_fast_assign(__entry->p = *p),
> - TP_printk("pic_parameter_set_id = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pps *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_h264_pps, p)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->p = *p),
> + TP_printk("tgid = %u, fd = %u, "
> + "pic_parameter_set_id = %u, "
> "seq_parameter_set_id = %u, "
> "num_slice_groups_minus1 = %u, "
> "num_ref_idx_l0_default_active_minus1 = %u, "
> @@ -442,6 +481,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
> "chroma_qp_index_offset = %d, "
> "second_chroma_qp_index_offset = %d, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->p.pic_parameter_set_id,
> __entry->p.seq_parameter_set_id,
> __entry->p.num_slice_groups_minus1,
> @@ -465,11 +505,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pps_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_h264_scaling_matrix_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_h264_scaling_matrix *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_scaling_matrix, s)),
> - TP_fast_assign(__entry->s = *s),
> - TP_printk("scaling_list_4x4 = {%s}, scaling_list_8x8 = {%s}",
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_scaling_matrix *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_h264_scaling_matrix, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s),
> + TP_printk("tgid = %u, fd = %u, "
> + "scaling_list_4x4 = {%s}, scaling_list_8x8 = {%s}",
> + __entry->tgid, __entry->fd,
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->s.scaling_list_4x4,
> sizeof(__entry->s.scaling_list_4x4),
> @@ -482,11 +528,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_scaling_matrix_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_h264_pred_weights *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_pred_weights, p)),
> - TP_fast_assign(__entry->p = *p),
> - TP_printk("luma_log2_weight_denom = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pred_weights *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_h264_pred_weights, p)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->p = *p),
> + TP_printk("tgid = %u, fd = %u, "
> + "luma_log2_weight_denom = %u, "
> "chroma_log2_weight_denom = %u, "
> "weight_factor[0].luma_weight = %s, "
> "weight_factor[0].luma_offset = %s, "
> @@ -496,6 +547,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
> "weight_factor[1].luma_offset = %s, "
> "weight_factor[1].chroma_weight = {%s}, "
> "weight_factor[1].chroma_offset = {%s}",
> + __entry->tgid, __entry->fd,
> __entry->p.luma_log2_weight_denom,
> __entry->p.chroma_log2_weight_denom,
> __print_array(__entry->p.weight_factors[0].luma_weight,
> @@ -530,11 +582,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_pred_weights_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_h264_slice_params *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_slice_params, s)),
> - TP_fast_assign(__entry->s = *s),
> - TP_printk("header_bit_size = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_slice_params *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_h264_slice_params, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s),
> + TP_printk("tgid = %u, fd = %u, "
> + "header_bit_size = %u, "
> "first_mb_in_slice = %u, "
> "slice_type = %s, "
> "colour_plane_id = %u, "
> @@ -548,6 +605,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
> "num_ref_idx_l0_active_minus1 = %u, "
> "num_ref_idx_l1_active_minus1 = %u, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->s.header_bit_size,
> __entry->s.first_mb_in_slice,
> __print_symbolic(__entry->s.slice_type,
> @@ -573,12 +631,18 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_slice_params_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_h264_reference_tmpl,
> - TP_PROTO(const struct v4l2_h264_reference *r, int i),
> - TP_ARGS(r, i),
> - TP_STRUCT__entry(__field_struct(struct v4l2_h264_reference, r)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_reference *r, int i),
> + TP_ARGS(tgid, fd, r, i),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_h264_reference, r)
> __field(int, i)),
> - TP_fast_assign(__entry->r = *r; __entry->i = i;),
> - TP_printk("[%d]: fields = %s, index = %u",
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->r = *r; __entry->i = i;),
> + TP_printk("tgid = %u, fd = %u, "
> + "[%d]: fields = %s, index = %u",
> + __entry->tgid, __entry->fd,
> __entry->i,
> __print_flags(__entry->r.fields, "|",
> {V4L2_H264_TOP_FIELD_REF, "TOP_FIELD_REF"},
> @@ -589,11 +653,16 @@ DECLARE_EVENT_CLASS(v4l2_h264_reference_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_h264_decode_params *d),
> - TP_ARGS(d),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_h264_decode_params, d)),
> - TP_fast_assign(__entry->d = *d),
> - TP_printk("nal_ref_idc = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_decode_params *d),
> + TP_ARGS(tgid, fd, d),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_h264_decode_params, d)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->d = *d),
> + TP_printk("tgid = %u, fd = %u, "
> + "nal_ref_idc = %u, "
> "frame_num = %u, "
> "top_field_order_cnt = %d, "
> "bottom_field_order_cnt = %d, "
> @@ -606,6 +675,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
> "pic_order_cnt_bit_size = %u, "
> "slice_group_change_cycle = %u, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->d.nal_ref_idc,
> __entry->d.frame_num,
> __entry->d.top_field_order_cnt,
> @@ -628,13 +698,19 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_h264_decode_params_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
> - TP_PROTO(const struct v4l2_h264_dpb_entry *e, int i),
> - TP_ARGS(e, i),
> - TP_STRUCT__entry(__field_struct(struct v4l2_h264_dpb_entry, e)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_dpb_entry *e, int i),
> + TP_ARGS(tgid, fd, e, i),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_h264_dpb_entry, e)
> __field(int, i)),
> - TP_fast_assign(__entry->e = *e; __entry->i = i;),
> - TP_printk("[%d]: reference_ts = %llu, pic_num = %u, frame_num = %u, fields = %s "
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->e = *e; __entry->i = i;),
> + TP_printk("tgid = %u, fd = %u, "
> + "[%d]: reference_ts = %llu, pic_num = %u, frame_num = %u, fields = %s, "
> "top_field_order_cnt = %d, bottom_field_order_cnt = %d, flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->i,
> __entry->e.reference_ts,
> __entry->e.pic_num,
> @@ -654,58 +730,63 @@ DECLARE_EVENT_CLASS(v4l2_h264_dpb_entry_tmpl,
> );
>
> DEFINE_EVENT(v4l2_ctrl_h264_sps_tmpl, v4l2_ctrl_h264_sps,
> - TP_PROTO(const struct v4l2_ctrl_h264_sps *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_sps *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_ctrl_h264_pps_tmpl, v4l2_ctrl_h264_pps,
> - TP_PROTO(const struct v4l2_ctrl_h264_pps *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pps *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> DEFINE_EVENT(v4l2_ctrl_h264_scaling_matrix_tmpl, v4l2_ctrl_h264_scaling_matrix,
> - TP_PROTO(const struct v4l2_ctrl_h264_scaling_matrix *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_scaling_matrix *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_ctrl_h264_pred_weights_tmpl, v4l2_ctrl_h264_pred_weights,
> - TP_PROTO(const struct v4l2_ctrl_h264_pred_weights *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_pred_weights *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> DEFINE_EVENT(v4l2_ctrl_h264_slice_params_tmpl, v4l2_ctrl_h264_slice_params,
> - TP_PROTO(const struct v4l2_ctrl_h264_slice_params *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_slice_params *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_h264_reference_tmpl, v4l2_h264_ref_pic_list0,
> - TP_PROTO(const struct v4l2_h264_reference *r, int i),
> - TP_ARGS(r, i)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_reference *r, int i),
> + TP_ARGS(tgid, fd, r, i)
> );
>
> DEFINE_EVENT(v4l2_h264_reference_tmpl, v4l2_h264_ref_pic_list1,
> - TP_PROTO(const struct v4l2_h264_reference *r, int i),
> - TP_ARGS(r, i)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_reference *r, int i),
> + TP_ARGS(tgid, fd, r, i)
> );
>
> DEFINE_EVENT(v4l2_ctrl_h264_decode_params_tmpl, v4l2_ctrl_h264_decode_params,
> - TP_PROTO(const struct v4l2_ctrl_h264_decode_params *d),
> - TP_ARGS(d)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_h264_decode_params *d),
> + TP_ARGS(tgid, fd, d)
> );
>
> DEFINE_EVENT(v4l2_h264_dpb_entry_tmpl, v4l2_h264_dpb_entry,
> - TP_PROTO(const struct v4l2_h264_dpb_entry *e, int i),
> - TP_ARGS(e, i)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_h264_dpb_entry *e, int i),
> + TP_ARGS(tgid, fd, e, i)
> );
>
> /* HEVC controls */
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_sps *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_sps, s)),
> - TP_fast_assign(__entry->s = *s),
> - TP_printk("video_parameter_set_id = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_sps *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_sps, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s),
> + TP_printk("tgid = %u, fd = %u, "
> + "video_parameter_set_id = %u, "
> "seq_parameter_set_id = %u, "
> "pic_width_in_luma_samples = %u, "
> "pic_height_in_luma_samples = %u, "
> @@ -730,6 +811,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
> "chroma_format_idc = %u, "
> "sps_max_sub_layers_minus1 = %u, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->s.video_parameter_set_id,
> __entry->s.seq_parameter_set_id,
> __entry->s.pic_width_in_luma_samples,
> @@ -770,11 +852,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_sps_tmpl,
>
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_pps *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_pps, p)),
> - TP_fast_assign(__entry->p = *p),
> - TP_printk("pic_parameter_set_id = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_pps *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_pps, p)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->p = *p),
> + TP_printk("tgid = %u, fd = %u, "
> + "pic_parameter_set_id = %u, "
> "num_extra_slice_header_bits = %u, "
> "num_ref_idx_l0_default_active_minus1 = %u, "
> "num_ref_idx_l1_default_active_minus1 = %u, "
> @@ -790,6 +877,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
> "pps_tc_offset_div2 = %d, "
> "log2_parallel_merge_level_minus2 = %u, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->p.pic_parameter_set_id,
> __entry->p.num_extra_slice_header_bits,
> __entry->p.num_ref_idx_l0_default_active_minus1,
> @@ -837,11 +925,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_pps_tmpl,
>
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_slice_params *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_slice_params, s)),
> - TP_fast_assign(__entry->s = *s),
> - TP_printk("bit_size = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_slice_params *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_slice_params, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s),
> + TP_printk("tgid = %u, fd = %u, "
> + "bit_size = %u, "
> "data_byte_offset = %u, "
> "num_entry_point_offsets = %u, "
> "nal_unit_type = %u, "
> @@ -868,6 +961,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
> "short_term_ref_pic_set_size = %u, "
> "long_term_ref_pic_set_size = %u, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->s.bit_size,
> __entry->s.data_byte_offset,
> __entry->s.num_entry_point_offsets,
> @@ -914,11 +1008,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_slice_params_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
> - TP_PROTO(const struct v4l2_hevc_pred_weight_table *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(__field_struct(struct v4l2_hevc_pred_weight_table, p)),
> - TP_fast_assign(__entry->p = *p),
> - TP_printk("delta_luma_weight_l0 = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_pred_weight_table *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_hevc_pred_weight_table, p)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->p = *p),
> + TP_printk("tgid = %u, fd = %u, "
> + "delta_luma_weight_l0 = %s, "
> "luma_offset_l0 = %s, "
> "delta_chroma_weight_l0 = {%s}, "
> "chroma_offset_l0 = {%s}, "
> @@ -928,6 +1027,7 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
> "chroma_offset_l1 = {%s}, "
> "luma_log2_weight_denom = %d, "
> "delta_chroma_log2_weight_denom = %d",
> + __entry->tgid, __entry->fd,
> __print_array(__entry->p.delta_luma_weight_l0,
> ARRAY_SIZE(__entry->p.delta_luma_weight_l0),
> sizeof(__entry->p.delta_luma_weight_l0[0])),
> @@ -962,16 +1062,22 @@ DECLARE_EVENT_CLASS(v4l2_hevc_pred_weight_table_tmpl,
> ))
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_scaling_matrix_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_scaling_matrix *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_scaling_matrix, s)),
> - TP_fast_assign(__entry->s = *s),
> - TP_printk("scaling_list_4x4 = {%s}, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_scaling_matrix *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_scaling_matrix, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s),
> + TP_printk("tgid = %u, fd = %u, "
> + "scaling_list_4x4 = {%s}, "
> "scaling_list_8x8 = {%s}, "
> "scaling_list_16x16 = {%s}, "
> "scaling_list_32x32 = {%s}, "
> "scaling_list_dc_coef_16x16 = %s, "
> "scaling_list_dc_coef_32x32 = %s",
> + __entry->tgid, __entry->fd,
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->s.scaling_list_4x4,
> sizeof(__entry->s.scaling_list_4x4),
> @@ -997,11 +1103,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_scaling_matrix_tmpl,
> ))
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_decode_params *d),
> - TP_ARGS(d),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_decode_params, d)),
> - TP_fast_assign(__entry->d = *d),
> - TP_printk("pic_order_cnt_val = %d, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_decode_params *d),
> + TP_ARGS(tgid, fd, d),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_decode_params, d)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->d = *d),
> + TP_printk("tgid = %u, fd = %u, "
> + "pic_order_cnt_val = %d, "
> "short_term_ref_pic_set_size = %u, "
> "long_term_ref_pic_set_size = %u, "
> "num_active_dpb_entries = %u, "
> @@ -1012,6 +1123,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
> "poc_st_curr_after = %s, "
> "poc_lt_curr = %s, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->d.pic_order_cnt_val,
> __entry->d.short_term_ref_pic_set_size,
> __entry->d.long_term_ref_pic_set_size,
> @@ -1036,12 +1148,18 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_decode_params_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
> - TP_ARGS(lt),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_ext_sps_lt_rps, lt)),
> - TP_fast_assign(__entry->lt = *lt),
> - TP_printk("flags = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
> + TP_ARGS(tgid, fd, lt),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_ext_sps_lt_rps, lt)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->lt = *lt),
> + TP_printk("tgid = %u, fd = %u, "
> + "flags = %s, "
> "lt_ref_pic_poc_lsb_sps = %x",
> + __entry->tgid, __entry->fd,
> __print_flags(__entry->lt.flags, "|",
> {V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT, "USED_LT"}
> ),
> @@ -1050,11 +1168,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
> - TP_ARGS(st),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_hevc_ext_sps_st_rps, st)),
> - TP_fast_assign(__entry->st = *st),
> - TP_printk("flags = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
> + TP_ARGS(tgid, fd, st),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_hevc_ext_sps_st_rps, st)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->st = *st),
> + TP_printk("tgid = %u, fd = %u, "
> + "flags = %s, "
> "delta_idx_minus1 = %u, "
> "delta_rps_sign = %u, "
> "abs_delta_rps_minus1 = %u, "
> @@ -1064,6 +1187,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
> "use_delta_flag = %08x, "
> "delta_poc_s0_minus1 = %s, "
> "delta_poc_s1_minus1 = %s",
> + __entry->tgid, __entry->fd,
> __print_flags(__entry->st.flags, "|",
> {V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED, "INTER_REF_PIC_SET_PRED"}
> ),
> @@ -1084,14 +1208,20 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_hevc_dpb_entry_tmpl,
> - TP_PROTO(const struct v4l2_hevc_dpb_entry *e),
> - TP_ARGS(e),
> - TP_STRUCT__entry(__field_struct(struct v4l2_hevc_dpb_entry, e)),
> - TP_fast_assign(__entry->e = *e),
> - TP_printk("timestamp = %llu, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_dpb_entry *e),
> + TP_ARGS(tgid, fd, e),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_hevc_dpb_entry, e)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->e = *e),
> + TP_printk("tgid = %u, fd = %u, "
> + "timestamp = %llu, "
> "flags = %s, "
> "field_pic = %u, "
> "pic_order_cnt_val = %d",
> + __entry->tgid, __entry->fd,
> __entry->e.timestamp,
> __print_flags(__entry->e.flags, "|",
> {V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE, "LONG_TERM_REFERENCE"}
> @@ -1101,59 +1231,65 @@ DECLARE_EVENT_CLASS(v4l2_hevc_dpb_entry_tmpl,
> ))
>
> DEFINE_EVENT(v4l2_ctrl_hevc_sps_tmpl, v4l2_ctrl_hevc_sps,
> - TP_PROTO(const struct v4l2_ctrl_hevc_sps *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_sps *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_ctrl_hevc_pps_tmpl, v4l2_ctrl_hevc_pps,
> - TP_PROTO(const struct v4l2_ctrl_hevc_pps *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_pps *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> DEFINE_EVENT(v4l2_ctrl_hevc_slice_params_tmpl, v4l2_ctrl_hevc_slice_params,
> - TP_PROTO(const struct v4l2_ctrl_hevc_slice_params *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_slice_params *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_hevc_pred_weight_table_tmpl, v4l2_hevc_pred_weight_table,
> - TP_PROTO(const struct v4l2_hevc_pred_weight_table *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_pred_weight_table *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> DEFINE_EVENT(v4l2_ctrl_hevc_scaling_matrix_tmpl, v4l2_ctrl_hevc_scaling_matrix,
> - TP_PROTO(const struct v4l2_ctrl_hevc_scaling_matrix *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_scaling_matrix *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_ctrl_hevc_decode_params_tmpl, v4l2_ctrl_hevc_decode_params,
> - TP_PROTO(const struct v4l2_ctrl_hevc_decode_params *d),
> - TP_ARGS(d)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_decode_params *d),
> + TP_ARGS(tgid, fd, d)
> );
>
> DEFINE_EVENT(v4l2_ctrl_hevc_ext_sps_lt_rps_tmpl, v4l2_ctrl_hevc_ext_sps_lt_rps,
> - TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
> - TP_ARGS(lt)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_lt_rps *lt),
> + TP_ARGS(tgid, fd, lt)
> );
>
> DEFINE_EVENT(v4l2_ctrl_hevc_ext_sps_st_rps_tmpl, v4l2_ctrl_hevc_ext_sps_st_rps,
> - TP_PROTO(const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
> - TP_ARGS(st)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_hevc_ext_sps_st_rps *st),
> + TP_ARGS(tgid, fd, st)
> );
>
> DEFINE_EVENT(v4l2_hevc_dpb_entry_tmpl, v4l2_hevc_dpb_entry,
> - TP_PROTO(const struct v4l2_hevc_dpb_entry *e),
> - TP_ARGS(e)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_hevc_dpb_entry *e),
> + TP_ARGS(tgid, fd, e)
> );
>
> /* MPEG2 controls */
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_seq_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_mpeg2_sequence *s),
> - TP_ARGS(s),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_mpeg2_sequence, s)),
> - TP_fast_assign(__entry->s = *s;),
> - TP_printk("horizontal_size = %u, vertical_size = %u, vbv_buffer_size = %u, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_sequence *s),
> + TP_ARGS(tgid, fd, s),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_mpeg2_sequence, s)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->s = *s;),
> + TP_printk("tgid = %u, fd = %u, "
> + "horizontal_size = %u, vertical_size = %u, vbv_buffer_size = %u, "
> "profile_and_level_indication = %u, chroma_format = %u, flags = %s",
> + __entry->tgid, __entry->fd,
> __entry->s.horizontal_size,
> __entry->s.vertical_size,
> __entry->s.vbv_buffer_size,
> @@ -1165,12 +1301,18 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_seq_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_pic_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_mpeg2_picture *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_mpeg2_picture, p)),
> - TP_fast_assign(__entry->p = *p;),
> - TP_printk("backward_ref_ts = %llu, forward_ref_ts = %llu, flags = %s, f_code = {%s}, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_picture *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_mpeg2_picture, p)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->p = *p;),
> + TP_printk("tgid = %u, fd = %u, "
> + "backward_ref_ts = %llu, forward_ref_ts = %llu, flags = %s, f_code = {%s}, "
> "picture_coding_type = %u, picture_structure = %u, intra_dc_precision = %u",
> + __entry->tgid, __entry->fd,
> __entry->p.backward_ref_ts,
> __entry->p.forward_ref_ts,
> __print_flags(__entry->p.flags, "|",
> @@ -1193,12 +1335,18 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_pic_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_quant_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_mpeg2_quantisation *q),
> - TP_ARGS(q),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_mpeg2_quantisation, q)),
> - TP_fast_assign(__entry->q = *q;),
> - TP_printk("intra_quantiser_matrix = %s, non_intra_quantiser_matrix = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_quantisation *q),
> + TP_ARGS(tgid, fd, q),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_mpeg2_quantisation, q)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->q = *q;),
> + TP_printk("tgid = %u, fd = %u, "
> + "intra_quantiser_matrix = %s, non_intra_quantiser_matrix = %s, "
> "chroma_intra_quantiser_matrix = %s, chroma_non_intra_quantiser_matrix = %s",
> + __entry->tgid, __entry->fd,
> __print_array(__entry->q.intra_quantiser_matrix,
> ARRAY_SIZE(__entry->q.intra_quantiser_matrix),
> sizeof(__entry->q.intra_quantiser_matrix[0])),
> @@ -1215,31 +1363,37 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_mpeg2_quant_tmpl,
> )
>
> DEFINE_EVENT(v4l2_ctrl_mpeg2_seq_tmpl, v4l2_ctrl_mpeg2_sequence,
> - TP_PROTO(const struct v4l2_ctrl_mpeg2_sequence *s),
> - TP_ARGS(s)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_sequence *s),
> + TP_ARGS(tgid, fd, s)
> );
>
> DEFINE_EVENT(v4l2_ctrl_mpeg2_pic_tmpl, v4l2_ctrl_mpeg2_picture,
> - TP_PROTO(const struct v4l2_ctrl_mpeg2_picture *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_picture *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> DEFINE_EVENT(v4l2_ctrl_mpeg2_quant_tmpl, v4l2_ctrl_mpeg2_quantisation,
> - TP_PROTO(const struct v4l2_ctrl_mpeg2_quantisation *q),
> - TP_ARGS(q)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_mpeg2_quantisation *q),
> + TP_ARGS(tgid, fd, q)
> );
>
> /* VP8 controls */
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_entropy_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
> - TP_ARGS(f),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp8_frame, f)),
> - TP_fast_assign(__entry->f = *f;),
> - TP_printk("entropy.coeff_probs = {%s}, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
> + TP_ARGS(tgid, fd, f),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_vp8_frame, f)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->f = *f;),
> + TP_printk("tgid = %u, fd = %u, "
> + "entropy.coeff_probs = {%s}, "
> "entropy.y_mode_probs = %s, "
> "entropy.uv_mode_probs = %s, "
> "entropy.mv_probs = {%s}",
> + __entry->tgid, __entry->fd,
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->f.entropy.coeff_probs,
> sizeof(__entry->f.entropy.coeff_probs),
> @@ -1258,11 +1412,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_entropy_tmpl,
> )
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
> - TP_ARGS(f),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp8_frame, f)),
> - TP_fast_assign(__entry->f = *f;),
> - TP_printk("segment.quant_update = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
> + TP_ARGS(tgid, fd, f),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_vp8_frame, f)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->f = *f;),
> + TP_printk("tgid = %u, fd = %u, "
> + "segment.quant_update = %s, "
> "segment.lf_update = %s, "
> "segment.segment_probs = %s, "
> "segment.flags = %s, "
> @@ -1297,6 +1456,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
> "golden_frame_ts = %llu, "
> "alt_frame_ts = %llu, "
> "flags = %s",
> + __entry->tgid, __entry->fd,
> __print_array(__entry->f.segment.quant_update,
> ARRAY_SIZE(__entry->f.segment.quant_update),
> sizeof(__entry->f.segment.quant_update[0])),
> @@ -1361,23 +1521,28 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp8_frame_tmpl,
> );
>
> DEFINE_EVENT(v4l2_ctrl_vp8_frame_tmpl, v4l2_ctrl_vp8_frame,
> - TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
> - TP_ARGS(f)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
> + TP_ARGS(tgid, fd, f)
> );
>
> DEFINE_EVENT(v4l2_ctrl_vp8_entropy_tmpl, v4l2_ctrl_vp8_entropy,
> - TP_PROTO(const struct v4l2_ctrl_vp8_frame *f),
> - TP_ARGS(f)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp8_frame *f),
> + TP_ARGS(tgid, fd, f)
> );
>
> /* VP9 controls */
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_vp9_frame *f),
> - TP_ARGS(f),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp9_frame, f)),
> - TP_fast_assign(__entry->f = *f;),
> - TP_printk("lf.ref_deltas = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_frame *f),
> + TP_ARGS(tgid, fd, f),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_vp9_frame, f)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->f = *f;),
> + TP_printk("tgid = %u, fd = %u, "
> + "lf.ref_deltas = %s, "
> "lf.mode_deltas = %s, "
> "lf.level = %u, "
> "lf.sharpness = %u, "
> @@ -1410,6 +1575,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
> "tile_cols_log2 = %u, "
> "tile_rows_log_2 = %u, "
> "reference_mode = %s",
> + __entry->tgid, __entry->fd,
> __print_array(__entry->f.lf.ref_deltas,
> ARRAY_SIZE(__entry->f.lf.ref_deltas),
> sizeof(__entry->f.lf.ref_deltas[0])),
> @@ -1490,11 +1656,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_frame_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
> - TP_ARGS(h),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp9_compressed_hdr, h)),
> - TP_fast_assign(__entry->h = *h;),
> - TP_printk("tx_mode = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
> + TP_ARGS(tgid, fd, h),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_vp9_compressed_hdr, h)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->h = *h;),
> + TP_printk("tgid = %u, fd = %u, "
> + "tx_mode = %s, "
> "tx8 = {%s}, "
> "tx16 = {%s}, "
> "tx32 = {%s}, "
> @@ -1508,6 +1679,7 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
> "y_mode = {%s}, "
> "uv_mode = {%s}, "
> "partition = {%s}",
> + __entry->tgid, __entry->fd,
> __print_symbolic(__entry->h.tx_mode,
> {V4L2_VP9_TX_MODE_ONLY_4X4, "TX_MODE_ONLY_4X4"},
> {V4L2_VP9_TX_MODE_ALLOW_8X8, "TX_MODE_ALLOW_8X8"},
> @@ -1566,11 +1738,17 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_hdr_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_coef_tmpl,
> - TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
> - TP_ARGS(h),
> - TP_STRUCT__entry(__field_struct(struct v4l2_ctrl_vp9_compressed_hdr, h)),
> - TP_fast_assign(__entry->h = *h;),
> - TP_printk("coef = {%s}",
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
> + TP_ARGS(tgid, fd, h),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_ctrl_vp9_compressed_hdr, h)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->h = *h;),
> + TP_printk("tgid = %u, fd = %u, "
> + "coef = {%s}",
> + __entry->tgid, __entry->fd,
> __print_hex_dump("", DUMP_PREFIX_NONE, 32, 1,
> __entry->h.coef,
> sizeof(__entry->h.coef),
> @@ -1579,11 +1757,16 @@ DECLARE_EVENT_CLASS(v4l2_ctrl_vp9_compressed_coef_tmpl,
> );
>
> DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
> - TP_PROTO(const struct v4l2_vp9_mv_probs *p),
> - TP_ARGS(p),
> - TP_STRUCT__entry(__field_struct(struct v4l2_vp9_mv_probs, p)),
> - TP_fast_assign(__entry->p = *p;),
> - TP_printk("joint = %s, "
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_vp9_mv_probs *p),
> + TP_ARGS(tgid, fd, p),
> + TP_STRUCT__entry(__field(u32, tgid)
> + __field(u32, fd)
> + __field_struct(struct v4l2_vp9_mv_probs, p)),
> + TP_fast_assign(__entry->tgid = tgid;
> + __entry->fd = fd;
> + __entry->p = *p;),
> + TP_printk("tgid = %u, fd = %u, "
> + "joint = %s, "
> "sign = %s, "
> "classes = {%s}, "
> "class0_bit = %s, "
> @@ -1592,6 +1775,7 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
> "fr = {%s}, "
> "class0_hp = %s, "
> "hp = %s",
> + __entry->tgid, __entry->fd,
> __print_array(__entry->p.joint,
> ARRAY_SIZE(__entry->p.joint),
> sizeof(__entry->p.joint[0])),
> @@ -1627,24 +1811,24 @@ DECLARE_EVENT_CLASS(v4l2_vp9_mv_probs_tmpl,
> );
>
> DEFINE_EVENT(v4l2_ctrl_vp9_frame_tmpl, v4l2_ctrl_vp9_frame,
> - TP_PROTO(const struct v4l2_ctrl_vp9_frame *f),
> - TP_ARGS(f)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_frame *f),
> + TP_ARGS(tgid, fd, f)
> );
>
> DEFINE_EVENT(v4l2_ctrl_vp9_compressed_hdr_tmpl, v4l2_ctrl_vp9_compressed_hdr,
> - TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
> - TP_ARGS(h)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
> + TP_ARGS(tgid, fd, h)
> );
>
> DEFINE_EVENT(v4l2_ctrl_vp9_compressed_coef_tmpl, v4l2_ctrl_vp9_compressed_coeff,
> - TP_PROTO(const struct v4l2_ctrl_vp9_compressed_hdr *h),
> - TP_ARGS(h)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_ctrl_vp9_compressed_hdr *h),
> + TP_ARGS(tgid, fd, h)
> );
>
>
> DEFINE_EVENT(v4l2_vp9_mv_probs_tmpl, v4l2_vp9_mv_probs,
> - TP_PROTO(const struct v4l2_vp9_mv_probs *p),
> - TP_ARGS(p)
> + TP_PROTO(u32 tgid, u32 fd, const struct v4l2_vp9_mv_probs *p),
> + TP_ARGS(tgid, fd, p)
> );
>
> #endif /* if !defined(_TRACE_V4L2_REQUESTS_H_) || defined(TRACE_HEADER_MULTI_READ) */
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 05/11] media: Add missing types to v4l2_ctrl_ptr
From: Nicolas Dufresne @ 2026-04-28 19:33 UTC (permalink / raw)
To: Detlev Casanova, linux-kernel
Cc: Benjamin Gaignard, Philipp Zabel, Mauro Carvalho Chehab,
Heiko Stuebner, Daniel Almeida, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Hans Verkuil, Laurent Pinchart,
Ricardo Ribalda, Yunke Cao, Sakari Ailus, Pavan Bobba,
James Cowgill, Ma Ke, Jacopo Mondi, Daniel Scally, linux-media,
linux-rockchip, linux-arm-kernel, linux-trace-kernel, kernel
In-Reply-To: <20260212162328.192217-6-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 1781 bytes --]
Le jeudi 12 février 2026 à 11:23 -0500, Detlev Casanova a écrit :
> The v4l2_ctrl_ptr union contains pointers for all control types, but
> v4l2_ctrl_hevc_decode_params and v4l2_ctrl_hevc_scaling_matrix are missing.
>
> Add them.
>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> ---
> include/media/v4l2-ctrls.h | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> index 327976b14d50..a2b4c96a9a6f 100644
> --- a/include/media/v4l2-ctrls.h
> +++ b/include/media/v4l2-ctrls.h
> @@ -49,6 +49,8 @@ struct video_device;
> * @p_hevc_sps: Pointer to an HEVC sequence parameter
> set structure.
> * @p_hevc_pps: Pointer to an HEVC picture parameter
> set structure.
> * @p_hevc_slice_params: Pointer to an HEVC slice parameters
> structure.
> + * @p_hevc_decode_params: Pointer to an HEVC decode parameters
> structure.
> + * @p_hevc_scaling_matrix Pointer to an HEVC scaling matrix structure.
> * @p_hdr10_cll: Pointer to an HDR10 Content Light Level
> structure.
> * @p_hdr10_mastering: Pointer to an HDR10 Mastering Display
> structure.
> * @p_area: Pointer to an area.
> @@ -81,6 +83,8 @@ union v4l2_ctrl_ptr {
> struct v4l2_ctrl_hevc_sps *p_hevc_sps;
> struct v4l2_ctrl_hevc_pps *p_hevc_pps;
> struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params;
> + struct v4l2_ctrl_hevc_decode_params *p_hevc_decode_params;
> + struct v4l2_ctrl_hevc_scaling_matrix *p_hevc_scaling_matrix;
> struct v4l2_ctrl_vp9_compressed_hdr *p_vp9_compressed_hdr_probs;
> struct v4l2_ctrl_vp9_frame *p_vp9_frame;
> struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll;
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH] phy: airoha: use C-style SPDX comment for header file
From: Aditya Dabhade @ 2026-04-28 19:34 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Vinod Koul, Neil Armstrong, linux-arm-kernel, linux-phy,
linux-kernel, Aditya Dabhade
checkpatch reports an improper SPDX comment style for this header:
WARNING: Improper SPDX comment style for
'drivers/phy/phy-airoha-pcie-regs.h', please use '/*' instead
Per Documentation/process/license-rules.rst, C header files must use the
'/* SPDX-License-Identifier: ... */' form instead of the '// ....' form
used in C source files. Fix it.
Signed-off-by: Aditya Dabhade <aditya.dabhade066@gmail.com>
---
drivers/phy/phy-airoha-pcie-regs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/phy-airoha-pcie-regs.h
index b938a7b468f..58572c79372 100644
--- a/drivers/phy/phy-airoha-pcie-regs.h
+++ b/drivers/phy/phy-airoha-pcie-regs.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-only
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 AIROHA Inc
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 06/11] media: Trace the stateless controls when set in v4l2-ctrls-core.c
From: Nicolas Dufresne @ 2026-04-28 19:37 UTC (permalink / raw)
To: Detlev Casanova, linux-kernel
Cc: Benjamin Gaignard, Philipp Zabel, Mauro Carvalho Chehab,
Heiko Stuebner, Daniel Almeida, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Hans Verkuil, Laurent Pinchart,
Ricardo Ribalda, Yunke Cao, Sakari Ailus, Pavan Bobba,
James Cowgill, Ma Ke, Jacopo Mondi, Daniel Scally, linux-media,
linux-rockchip, linux-arm-kernel, linux-trace-kernel, kernel
In-Reply-To: <20260212162328.192217-7-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 13188 bytes --]
Le jeudi 12 février 2026 à 11:23 -0500, Detlev Casanova a écrit :
> Also remove the trace from visl as the generic v4l2-requests traces can
> now be used instead.
>
> It allows all stateless drivers to inherit traceability, with just a small
> overhead when disabled in userspace.
>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
> ---
> drivers/media/test-drivers/visl/visl-dec.c | 74 -------------
> drivers/media/v4l2-core/v4l2-ctrls-api.c | 10 ++
> drivers/media/v4l2-core/v4l2-ctrls-core.c | 114 +++++++++++++++++++++
> include/media/v4l2-ctrls.h | 15 +++
> 4 files changed, 139 insertions(+), 74 deletions(-)
>
> diff --git a/drivers/media/test-drivers/visl/visl-dec.c b/drivers/media/test-drivers/visl/visl-dec.c
> index fc216da17048..9517830fb3e8 100644
> --- a/drivers/media/test-drivers/visl/visl-dec.c
> +++ b/drivers/media/test-drivers/visl/visl-dec.c
> @@ -12,7 +12,6 @@
> #include <linux/workqueue.h>
> #include <media/v4l2-mem2mem.h>
> #include <media/tpg/v4l2-tpg.h>
> -#include <trace/events/v4l2_requests.h>
>
> #define LAST_BUF_IDX (V4L2_AV1_REF_LAST_FRAME - V4L2_AV1_REF_LAST_FRAME)
> #define LAST2_BUF_IDX (V4L2_AV1_REF_LAST2_FRAME - V4L2_AV1_REF_LAST_FRAME)
> @@ -486,78 +485,6 @@ static void visl_tpg_fill(struct visl_ctx *ctx, struct visl_run *run)
> }
> }
>
> -static void visl_trace_ctrls(struct visl_ctx *ctx, struct visl_run *run)
> -{
> - int i;
> - struct v4l2_fh *fh = &ctx->fh;
> -
> - switch (ctx->current_codec) {
> - default:
> - case VISL_CODEC_NONE:
> - break;
> - case VISL_CODEC_FWHT:
> - trace_v4l2_ctrl_fwht_params(fh->tgid, fh->fd, run->fwht.params);
> - break;
> - case VISL_CODEC_MPEG2:
> - trace_v4l2_ctrl_mpeg2_sequence(fh->tgid, fh->fd, run->mpeg2.seq);
> - trace_v4l2_ctrl_mpeg2_picture(fh->tgid, fh->fd, run->mpeg2.pic);
> - trace_v4l2_ctrl_mpeg2_quantisation(fh->tgid, fh->fd, run->mpeg2.quant);
> - break;
> - case VISL_CODEC_VP8:
> - trace_v4l2_ctrl_vp8_frame(fh->tgid, fh->fd, run->vp8.frame);
> - trace_v4l2_ctrl_vp8_entropy(fh->tgid, fh->fd, run->vp8.frame);
> - break;
> - case VISL_CODEC_VP9:
> - trace_v4l2_ctrl_vp9_frame(fh->tgid, fh->fd, run->vp9.frame);
> - trace_v4l2_ctrl_vp9_compressed_hdr(fh->tgid, fh->fd, run->vp9.probs);
> - trace_v4l2_ctrl_vp9_compressed_coeff(fh->tgid, fh->fd, run->vp9.probs);
> - trace_v4l2_vp9_mv_probs(fh->tgid, fh->fd, &run->vp9.probs->mv);
> - break;
> - case VISL_CODEC_H264:
> - trace_v4l2_ctrl_h264_sps(fh->tgid, fh->fd, run->h264.sps);
> - trace_v4l2_ctrl_h264_pps(fh->tgid, fh->fd, run->h264.pps);
> - trace_v4l2_ctrl_h264_scaling_matrix(fh->tgid, fh->fd, run->h264.sm);
> - trace_v4l2_ctrl_h264_slice_params(fh->tgid, fh->fd, run->h264.spram);
> -
> - for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
> - trace_v4l2_h264_ref_pic_list0(fh->tgid, fh->fd,
> - &run->h264.spram->ref_pic_list0[i], i);
> - for (i = 0; i < ARRAY_SIZE(run->h264.spram->ref_pic_list0); i++)
> - trace_v4l2_h264_ref_pic_list1(fh->tgid, fh->fd,
> - &run->h264.spram->ref_pic_list1[i], i);
> -
> - trace_v4l2_ctrl_h264_decode_params(fh->tgid, fh->fd, run->h264.dpram);
> -
> - for (i = 0; i < ARRAY_SIZE(run->h264.dpram->dpb); i++)
> - trace_v4l2_h264_dpb_entry(fh->tgid, fh->fd, &run->h264.dpram->dpb[i], i);
> -
> - trace_v4l2_ctrl_h264_pred_weights(fh->tgid, fh->fd, run->h264.pwht);
> - break;
> - case VISL_CODEC_HEVC:
> - trace_v4l2_ctrl_hevc_sps(fh->tgid, fh->fd, run->hevc.sps);
> - trace_v4l2_ctrl_hevc_pps(fh->tgid, fh->fd, run->hevc.pps);
> - trace_v4l2_ctrl_hevc_slice_params(fh->tgid, fh->fd, run->hevc.spram);
> - trace_v4l2_ctrl_hevc_scaling_matrix(fh->tgid, fh->fd, run->hevc.sm);
> - trace_v4l2_ctrl_hevc_decode_params(fh->tgid, fh->fd, run->hevc.dpram);
> -
> - for (i = 0; i < ARRAY_SIZE(run->hevc.dpram->dpb); i++)
> - trace_v4l2_hevc_dpb_entry(fh->tgid, fh->fd, &run->hevc.dpram->dpb[i]);
> -
> -
> - trace_v4l2_hevc_pred_weight_table(fh->tgid, fh->fd,
> - &run->hevc.spram->pred_weight_table);
> - trace_v4l2_ctrl_hevc_ext_sps_lt_rps(fh->tgid, fh->fd, run->hevc.rps_lt);
> - trace_v4l2_ctrl_hevc_ext_sps_st_rps(fh->tgid, fh->fd, run->hevc.rps_st);
> - break;
> - case VISL_CODEC_AV1:
> - trace_v4l2_ctrl_av1_sequence(fh->tgid, fh->fd, run->av1.seq);
> - trace_v4l2_ctrl_av1_frame(fh->tgid, fh->fd, run->av1.frame);
> - trace_v4l2_ctrl_av1_film_grain(fh->tgid, fh->fd, run->av1.grain);
> - trace_v4l2_ctrl_av1_tile_group_entry(fh->tgid, fh->fd, run->av1.tge);
> - break;
> - }
> -}
> -
> void visl_device_run(void *priv)
> {
> struct visl_ctx *ctx = priv;
> @@ -634,7 +561,6 @@ void visl_device_run(void *priv)
> run.dst->sequence, run.dst->vb2_buf.timestamp);
>
> visl_tpg_fill(ctx, &run);
> - visl_trace_ctrls(ctx, &run);
>
> if (bitstream_trace_frame_start > -1 &&
> run.dst->sequence >= bitstream_trace_frame_start &&
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c
> index 0078a04c5445..8a814eec7a30 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c
> @@ -524,6 +524,12 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
> }
> EXPORT_SYMBOL(v4l2_g_ext_ctrls);
>
> +static void trace_ext_ctrl(struct v4l2_fh *fh, const struct v4l2_ctrl *ctrl)
> +{
> + if (ctrl->type_ops->trace)
> + ctrl->type_ops->trace(fh, ctrl, ctrl->p_cur);
> +}
> +
> /* Validate a new control */
> static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
> {
> @@ -713,6 +719,10 @@ int try_set_ext_ctrls_common(struct v4l2_fh *fh,
> idx = helpers[idx].next;
> } while (!ret && idx);
> }
> +
> + if (set)
> + trace_ext_ctrl(fh, master);
> +
> v4l2_ctrl_unlock(master);
> }
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
> index 79a157975f70..6165e36d8879 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
> @@ -10,8 +10,11 @@
> #include <linux/slab.h>
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-event.h>
> +#include <media/v4l2-fh.h>
> #include <media/v4l2-fwnode.h>
>
> +#include <trace/events/v4l2_requests.h>
> +
> #include "v4l2-ctrls-priv.h"
>
> static const union v4l2_ctrl_ptr ptr_null;
> @@ -1462,12 +1465,123 @@ int v4l2_ctrl_type_op_validate(const struct v4l2_ctrl *ctrl,
> }
> EXPORT_SYMBOL(v4l2_ctrl_type_op_validate);
>
> +void v4l2_ctrl_type_op_trace(const struct v4l2_fh *fh,
> + const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr)
> +{
> + int i = 0;
> +
> + switch ((u32)ctrl->type) {
> + case V4L2_CTRL_TYPE_FWHT_PARAMS:
> + trace_v4l2_ctrl_fwht_params(fh->tgid, fh->fd, ptr.p_fwht_params);
> + break;
> + case V4L2_CTRL_TYPE_MPEG2_SEQUENCE:
> + trace_v4l2_ctrl_mpeg2_sequence(fh->tgid, fh->fd, ptr.p_mpeg2_sequence);
> + break;
> + case V4L2_CTRL_TYPE_MPEG2_PICTURE:
> + trace_v4l2_ctrl_mpeg2_picture(fh->tgid, fh->fd, ptr.p_mpeg2_picture);
> + break;
> + case V4L2_CTRL_TYPE_MPEG2_QUANTISATION:
> + trace_v4l2_ctrl_mpeg2_quantisation(fh->tgid, fh->fd, ptr.p_mpeg2_quantisation);
> + break;
> + case V4L2_CTRL_TYPE_VP8_FRAME:
> + trace_v4l2_ctrl_vp8_frame(fh->tgid, fh->fd, ptr.p_vp8_frame);
> + trace_v4l2_ctrl_vp8_entropy(fh->tgid, fh->fd, ptr.p_vp8_frame);
> + break;
> + case V4L2_CTRL_TYPE_VP9_FRAME:
> + trace_v4l2_ctrl_vp9_frame(fh->tgid, fh->fd, ptr.p_vp9_frame);
> + break;
> + case V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR:
> + trace_v4l2_ctrl_vp9_compressed_hdr(fh->tgid, fh->fd,
> + ptr.p_vp9_compressed_hdr_probs);
> + trace_v4l2_ctrl_vp9_compressed_coeff(fh->tgid, fh->fd,
> + ptr.p_vp9_compressed_hdr_probs);
> + trace_v4l2_vp9_mv_probs(fh->tgid, fh->fd, &ptr.p_vp9_compressed_hdr_probs->mv);
> + break;
> + case V4L2_CTRL_TYPE_H264_SPS:
> + trace_v4l2_ctrl_h264_sps(fh->tgid, fh->fd, ptr.p_h264_sps);
> + break;
> + case V4L2_CTRL_TYPE_H264_PPS:
> + trace_v4l2_ctrl_h264_pps(fh->tgid, fh->fd, ptr.p_h264_pps);
> + break;
> + case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
> + trace_v4l2_ctrl_h264_scaling_matrix(fh->tgid, fh->fd, ptr.p_h264_scaling_matrix);
> + break;
> + case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
> + {
> + struct v4l2_ctrl_h264_slice_params *sp = ptr.p_h264_slice_params;
> +
> + trace_v4l2_ctrl_h264_slice_params(fh->tgid, fh->fd, sp);
> +
> + for (i = 0; i < ARRAY_SIZE(sp->ref_pic_list0); i++)
> + trace_v4l2_h264_ref_pic_list0(fh->tgid, fh->fd, &sp->ref_pic_list0[i], i);
> + for (i = 0; i < ARRAY_SIZE(sp->ref_pic_list1); i++)
> + trace_v4l2_h264_ref_pic_list1(fh->tgid, fh->fd, &sp->ref_pic_list1[i], i);
> +
> + break;
> + }
> + case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
> + {
> + struct v4l2_ctrl_h264_decode_params *dp = ptr.p_h264_decode_params;
> +
> + trace_v4l2_ctrl_h264_decode_params(fh->tgid, fh->fd, dp);
> +
> + for (i = 0; i < ARRAY_SIZE(dp->dpb); i++)
> + trace_v4l2_h264_dpb_entry(fh->tgid, fh->fd, &dp->dpb[i], i);
> +
> + break;
> + }
> + case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
> + trace_v4l2_ctrl_h264_pred_weights(fh->tgid, fh->fd, ptr.p_h264_pred_weights);
> + break;
> + case V4L2_CTRL_TYPE_HEVC_SPS:
> + trace_v4l2_ctrl_hevc_sps(fh->tgid, fh->fd, ptr.p_hevc_sps);
> + break;
> + case V4L2_CTRL_TYPE_HEVC_PPS:
> + trace_v4l2_ctrl_hevc_pps(fh->tgid, fh->fd, ptr.p_hevc_pps);
> + break;
> + case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
> + trace_v4l2_ctrl_hevc_slice_params(fh->tgid, fh->fd, ptr.p_hevc_slice_params);
> + trace_v4l2_hevc_pred_weight_table(fh->tgid, fh->fd,
> + &ptr.p_hevc_slice_params->pred_weight_table);
> + break;
> + case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX:
> + trace_v4l2_ctrl_hevc_scaling_matrix(fh->tgid, fh->fd, ptr.p_hevc_scaling_matrix);
> + break;
> + case V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS:
> + {
> + struct v4l2_ctrl_hevc_decode_params *dp = ptr.p_hevc_decode_params;
> +
> + trace_v4l2_ctrl_hevc_decode_params(fh->tgid, fh->fd, dp);
> +
> + for (i = 0; i < ARRAY_SIZE(dp->dpb); i++)
> + trace_v4l2_hevc_dpb_entry(fh->tgid, fh->fd, &dp->dpb[i]);
> +
> + break;
> + }
> + case V4L2_CTRL_TYPE_AV1_SEQUENCE:
> + trace_v4l2_ctrl_av1_sequence(fh->tgid, fh->fd, ptr.p_av1_sequence);
> + break;
> + case V4L2_CTRL_TYPE_AV1_FRAME:
> + trace_v4l2_ctrl_av1_frame(fh->tgid, fh->fd, ptr.p_av1_frame);
> + break;
> + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN:
> + trace_v4l2_ctrl_av1_film_grain(fh->tgid, fh->fd, ptr.p_av1_film_grain);
> + break;
> + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY:
> + trace_v4l2_ctrl_av1_tile_group_entry(fh->tgid, fh->fd, ptr.p_av1_tile_group_entry);
> + break;
Some controls are pretty generic, so what about these, the non compound ?
Nicolas
> + }
> +
> +}
> +EXPORT_SYMBOL(v4l2_ctrl_type_op_trace);
> +
> static const struct v4l2_ctrl_type_ops std_type_ops = {
> .equal = v4l2_ctrl_type_op_equal,
> .init = v4l2_ctrl_type_op_init,
> .minimum = v4l2_ctrl_type_op_minimum,
> .maximum = v4l2_ctrl_type_op_maximum,
> .log = v4l2_ctrl_type_op_log,
> + .trace = v4l2_ctrl_type_op_trace,
> .validate = v4l2_ctrl_type_op_validate,
> };
>
> diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> index a2b4c96a9a6f..57c4bb999b7b 100644
> --- a/include/media/v4l2-ctrls.h
> +++ b/include/media/v4l2-ctrls.h
> @@ -140,6 +140,7 @@ struct v4l2_ctrl_ops {
> * @minimum: set the value to the minimum value of the control.
> * @maximum: set the value to the maximum value of the control.
> * @log: log the value.
> + * @trace: trace the value of the control with Ftrace.
> * @validate: validate the value for ctrl->new_elems array elements.
> * Return 0 on success and a negative value otherwise.
> */
> @@ -153,6 +154,8 @@ struct v4l2_ctrl_type_ops {
> void (*maximum)(const struct v4l2_ctrl *ctrl, u32 idx,
> union v4l2_ctrl_ptr ptr);
> void (*log)(const struct v4l2_ctrl *ctrl);
> + void (*trace)(const struct v4l2_fh *fh,
> + const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr);
> int (*validate)(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr);
> };
>
> @@ -1627,6 +1630,18 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
> */
> void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl);
>
> +/**
> + * v4l2_ctrl_type_op_trace - Default v4l2_ctrl_type_ops trace callback.
> + *
> + * @fh: The v4l2_fh of the current context.
> + * @ctrl: The v4l2_ctrl pointer.
> + * @ptr: The v4l2 control value.
> + *
> + * Return: void
> + */
> +void v4l2_ctrl_type_op_trace(const struct v4l2_fh *fh,
> + const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr);
> +
> /**
> * v4l2_ctrl_type_op_validate - Default v4l2_ctrl_type_ops validate callback.
> *
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 11/11] media: hantro: Add fdinfo callback
From: Nicolas Dufresne @ 2026-04-28 19:41 UTC (permalink / raw)
To: Detlev Casanova, linux-kernel
Cc: Benjamin Gaignard, Philipp Zabel, Mauro Carvalho Chehab,
Heiko Stuebner, Daniel Almeida, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Hans Verkuil, Laurent Pinchart,
Ricardo Ribalda, Yunke Cao, Sakari Ailus, Pavan Bobba,
James Cowgill, Ma Ke, Jacopo Mondi, Daniel Scally, linux-media,
linux-rockchip, linux-arm-kernel, linux-trace-kernel, kernel
In-Reply-To: <20260212162328.192217-12-detlev.casanova@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 4001 bytes --]
Le jeudi 12 février 2026 à 11:23 -0500, Detlev Casanova a écrit :
> The fdinfo shows the number of buffers in each queue and the total amount
> of video buffer memory.
>
> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
Notice that the FD info is not linked with all the ftrace work, and could have
been kept separate. I think overall that this fdinfo implementation is a bit
limited, and lack helpers or introducing of common statistics that would be
opted in by other drivers. I would hold on that until we have a bigger and
robust plan.
Nicolas
> ---
> drivers/media/platform/verisilicon/hantro.h | 1 +
> drivers/media/platform/verisilicon/hantro_drv.c | 15 +++++++++++++++
> drivers/media/platform/verisilicon/hantro_v4l2.c | 10 +++++++++-
> 3 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/verisilicon/hantro.h
> b/drivers/media/platform/verisilicon/hantro.h
> index d5cddc783688..9e9fc0658586 100644
> --- a/drivers/media/platform/verisilicon/hantro.h
> +++ b/drivers/media/platform/verisilicon/hantro.h
> @@ -268,6 +268,7 @@ struct hantro_ctx {
> const struct hantro_codec_ops *codec_ops;
> struct hantro_postproc_ctx postproc;
> bool need_postproc;
> + u64 stats_buf_memory;
>
> /* Specific for particular codec modes. */
> union {
> diff --git a/drivers/media/platform/verisilicon/hantro_drv.c
> b/drivers/media/platform/verisilicon/hantro_drv.c
> index 8dd26ca32459..86d316a8a3e8 100644
> --- a/drivers/media/platform/verisilicon/hantro_drv.c
> +++ b/drivers/media/platform/verisilicon/hantro_drv.c
> @@ -17,6 +17,7 @@
> #include <linux/platform_device.h>
> #include <linux/pm.h>
> #include <linux/pm_runtime.h>
> +#include <linux/seq_file.h>
> #include <linux/slab.h>
> #include <linux/videodev2.h>
> #include <linux/workqueue.h>
> @@ -711,6 +712,19 @@ static int hantro_release(struct file *filp)
> return 0;
> }
>
> +static void hantro_show_fdinfo(struct seq_file *m, struct file *filp)
> +{
> + struct hantro_ctx *ctx =
> + container_of(filp->private_data, struct hantro_ctx, fh);
> +
> + struct vb2_queue *src_q = v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx);
> + struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx);
> +
> + seq_printf(m, "src-queued-count: %04u\n", src_q->queued_count);
> + seq_printf(m, "dst-queued-count: %04u\n", dst_q->queued_count);
> + seq_printf(m, "buf-size: %llu\n", ctx->stats_buf_memory);
> +}
> +
> static const struct v4l2_file_operations hantro_fops = {
> .owner = THIS_MODULE,
> .open = hantro_open,
> @@ -718,6 +732,7 @@ static const struct v4l2_file_operations hantro_fops = {
> .poll = v4l2_m2m_fop_poll,
> .unlocked_ioctl = video_ioctl2,
> .mmap = v4l2_m2m_fop_mmap,
> + .show_fdinfo = hantro_show_fdinfo,
> };
>
> static const struct of_device_id of_hantro_match[] = {
> diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c
> b/drivers/media/platform/verisilicon/hantro_v4l2.c
> index fcf3bd9bcda2..6d129613ea3d 100644
> --- a/drivers/media/platform/verisilicon/hantro_v4l2.c
> +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c
> @@ -820,18 +820,26 @@ hantro_queue_setup(struct vb2_queue *vq, unsigned int
> *num_buffers,
> return -EINVAL;
> }
>
> + ctx->stats_buf_memory = 0;
> +
> if (*num_planes) {
> if (*num_planes != pixfmt->num_planes)
> return -EINVAL;
> - for (i = 0; i < pixfmt->num_planes; ++i)
> + for (i = 0; i < pixfmt->num_planes; ++i) {
> if (sizes[i] < pixfmt->plane_fmt[i].sizeimage)
> return -EINVAL;
> + ctx->stats_buf_memory += pixfmt-
> >plane_fmt[i].sizeimage;
> + }
> +
> + ctx->stats_buf_memory *= *num_buffers;
> +
> return 0;
> }
>
> *num_planes = pixfmt->num_planes;
> for (i = 0; i < pixfmt->num_planes; ++i)
> sizes[i] = pixfmt->plane_fmt[i].sizeimage;
> +
> return 0;
> }
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ 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