* [PATCH iwl-next v6 00/14] Introduce iXD driver
From: Larysa Zaremba @ 2026-03-23 17:40 UTC (permalink / raw)
To: intel-wired-lan, Tony Nguyen
Cc: aleksander.lobakin, sridhar.samudrala, Singhai, Anjali,
Michal Swiatkowski, Larysa Zaremba, Fijalkowski, Maciej,
Emil Tantilov, Madhu Chittim, Josh Hay, Keller, Jacob E,
jayaprakash.shanmugam, Jiri Pirko, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
Richard Cochran, Przemek Kitszel, Andrew Lunn, netdev, linux-doc,
linux-kernel
This patch series adds the iXD driver, which supports the Intel(R)
Control Plane PCI Function on Intel E2100 and later IPUs and FNICs.
It facilitates a centralized control over multiple IDPF PFs/VFs/SFs
exposed by the same card. The reason for the separation is to be able
to offload the control plane to the host different from where the data
plane is running.
This is the first phase in the release of this driver where we implement the
initialization of the core PCI driver. Subsequent phases will implement
advanced features like usage of idpf ethernet aux device, link management,
NVM update via devlink, switchdev port representors, data and exception path,
flow rule programming, etc.
The first phase entails the following aspects:
1. Additional libie functionalities:
Patches 1-5 introduce additional common library API for drivers to
communicate with the control plane through mailbox communication.
A control queue is a hardware interface which is used by the driver
to interact with other subsystems (like firmware). The library APIs
allow the driver to setup and configure the control queues to send and
receive virtchnl messages. The library has an internal bookkeeping
(XN API) mechanism to keep track of the send messages. It supports both
synchronous as well as asynchronous way of handling the messages. The
library also handles the timeout internally for synchronous messages
using events. This reduces the driver's overhead in handling the timeout
error cases.
The current patch series supports only APIs that are needed for device
initialization. These include APIs in the libie_pci module:
* Allocating/freeing the DMA memory and mapping the MMIO regions for
BAR0, read/write APIs for drivers to access the MMIO memory
and libie_cp module:
* Control queue initialization and configuration
* Transport initialization for bookkeeping
* Blocking and asynchronous mailbox transactions
Once the mailbox is initialized, the drivers can send and receive virtchnl
messages to/from the control plane.
The modules above are not supposed to be linked witn the main libie library,
but do share the folder with it.
2. idpf :
Patches 6-9 refactor the idpf driver to use the libie APIs for control
queue configuration, virtchnl transaction, device initialization and
reset and adjust related code accordingly.
3. ixd:
Patches 11-14 add the ixd driver and implement multiple pieces of the
initialization flow as follows:
* Add the ability to load
* A reset is issued to ensure a clean device state, followed by
initialization of the mailbox
* Device capabilities:
As part of initialization, the driver has to determine what the device is
capable of (ex. max queues, vports, etc). This information is obtained from
the firmware and stored by the driver.
* Enable initial support for the devlink interface
v5->v6:
* improved failure handling and input validation
* removed cp version from devlink in ixd
* patch 8 requires retest
v4->v5:
* rebase on top of queue resources refactor
* overwrite idpf's memory regions management that was merged in the meantime
* introduce libie_pci_unmap_fltr_regs()
* rebase on top on RDMA patchset - patches 8 & 9
* use pcim_* helpers in libie_pci (patch 3)
* fix issue with reset not being triggered (reported by Emil) - patch 8
* introduce idpf_send_mb_msg_kfree function to handle cases, where
idpf allocates buffers on different size for the same command - patch 8
v3->v4:
* non-trivial rebase affecting patch 1 (moving headers) and idpf refactoring
patches
v2->v3:
* non-trivial rebase affecting idpf refactoring patches
* add include/linux/intel under both Tony and NETWORKING DRIVERS
* due to rebase, in libie account for libeth_rx now using netmem instead
of plain pages
* make libie_ctlq_release_rx_buf() take only one argument, as the producing
queue is not actually needed to release a page pool buffer
* fix return value not being set in idpf_send_get_rx_ptype_msg()
* fix kdoc comments, so libie and ixd generate it cleanly
* separate idpf refactoring into 2 patches: pci+mmio and ctlq+xn
* suplement idpf refactoring commit message with information about module size
and resource usage changes
* reformat commit messages to reduce the number of wasted lines
v1->v2:
* rename libeth_cp and libeth_pci to libie_cp and libie_pci respectively,
move them into an appropriate folder
* rebase on top of recent PTP changes, this alters idpf refactor
* update maintainers after moving headers
* cast resource_size_t to unsigned long long when printing
* add ixd devlink documentation into index
* fix xn system kdoc problems
* fix indentation in libeth_ctlq_xn_deinit()
* fix extra kdoc member vcxn_mngr in idpf_adapter
Amritha Nambiar (1):
ixd: add devlink support
Larysa Zaremba (5):
idpf: make mbx_task queueing and cancelling more consistent
idpf: print a debug message and bail in case of non-event ctlq message
ixd: add basic driver framework for Intel(R) Control Plane Function
ixd: add reset checks and initialize the mailbox
ixd: add the core initialization
Pavan Kumar Linga (4):
libeth: allow to create fill queues without NAPI
idpf: remove 'vport_params_reqd' field
idpf: refactor idpf to use libie_pci APIs
idpf: refactor idpf to use libie control queues
Phani R Burra (3):
libie: add PCI device initialization helpers to libie
libie: add control queue support
libie: add bookkeeping support for control queue messages
Victor Raj (1):
virtchnl: create 'include/linux/intel' and move necessary header files
.../device_drivers/ethernet/index.rst | 1 +
.../device_drivers/ethernet/intel/ixd.rst | 39 +
Documentation/networking/devlink/index.rst | 1 +
Documentation/networking/devlink/ixd.rst | 30 +
MAINTAINERS | 6 +-
drivers/infiniband/hw/irdma/i40iw_if.c | 2 +-
drivers/infiniband/hw/irdma/icrdma_if.c | 2 +-
drivers/infiniband/hw/irdma/ig3rdma_if.c | 2 +-
drivers/infiniband/hw/irdma/main.c | 2 +-
drivers/infiniband/hw/irdma/main.h | 2 +-
drivers/net/ethernet/intel/Kconfig | 2 +
drivers/net/ethernet/intel/Makefile | 1 +
drivers/net/ethernet/intel/i40e/i40e.h | 4 +-
.../net/ethernet/intel/i40e/i40e_adminq_cmd.h | 2 +-
drivers/net/ethernet/intel/i40e/i40e_client.c | 2 +-
drivers/net/ethernet/intel/i40e/i40e_common.c | 2 +-
.../net/ethernet/intel/i40e/i40e_ethtool.c | 2 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +-
.../net/ethernet/intel/i40e/i40e_prototype.h | 2 +-
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 +-
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 +-
.../ethernet/intel/i40e/i40e_virtchnl_pf.h | 2 +-
drivers/net/ethernet/intel/iavf/iavf.h | 2 +-
.../net/ethernet/intel/iavf/iavf_adminq_cmd.h | 2 +-
drivers/net/ethernet/intel/iavf/iavf_common.c | 2 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 2 +-
.../net/ethernet/intel/iavf/iavf_prototype.h | 2 +-
drivers/net/ethernet/intel/iavf/iavf_txrx.c | 2 +-
drivers/net/ethernet/intel/iavf/iavf_txrx.h | 2 +-
drivers/net/ethernet/intel/iavf/iavf_types.h | 4 +-
.../net/ethernet/intel/iavf/iavf_virtchnl.c | 2 +-
drivers/net/ethernet/intel/ice/ice.h | 2 +-
.../net/ethernet/intel/ice/ice_adminq_cmd.h | 2 +-
drivers/net/ethernet/intel/ice/ice_base.c | 2 +-
drivers/net/ethernet/intel/ice/ice_common.h | 2 +-
drivers/net/ethernet/intel/ice/ice_flow.h | 2 +-
drivers/net/ethernet/intel/ice/ice_idc_int.h | 4 +-
drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +-
drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 2 +-
drivers/net/ethernet/intel/ice/ice_type.h | 2 +-
drivers/net/ethernet/intel/ice/ice_vf_lib.h | 2 +-
.../net/ethernet/intel/ice/virt/virtchnl.h | 2 +-
drivers/net/ethernet/intel/idpf/Kconfig | 1 +
drivers/net/ethernet/intel/idpf/Makefile | 2 -
drivers/net/ethernet/intel/idpf/idpf.h | 103 +-
.../net/ethernet/intel/idpf/idpf_controlq.c | 621 ------
.../net/ethernet/intel/idpf/idpf_controlq.h | 144 --
.../ethernet/intel/idpf/idpf_controlq_api.h | 177 --
.../ethernet/intel/idpf/idpf_controlq_setup.c | 169 --
drivers/net/ethernet/intel/idpf/idpf_dev.c | 101 +-
.../net/ethernet/intel/idpf/idpf_ethtool.c | 28 +-
drivers/net/ethernet/intel/idpf/idpf_idc.c | 38 +-
drivers/net/ethernet/intel/idpf/idpf_lib.c | 69 +-
drivers/net/ethernet/intel/idpf/idpf_main.c | 117 +-
drivers/net/ethernet/intel/idpf/idpf_mem.h | 20 -
drivers/net/ethernet/intel/idpf/idpf_txrx.h | 4 +-
drivers/net/ethernet/intel/idpf/idpf_vf_dev.c | 99 +-
.../net/ethernet/intel/idpf/idpf_virtchnl.c | 1820 +++++++----------
.../net/ethernet/intel/idpf/idpf_virtchnl.h | 95 +-
.../ethernet/intel/idpf/idpf_virtchnl_ptp.c | 304 ++-
drivers/net/ethernet/intel/ixd/Kconfig | 15 +
drivers/net/ethernet/intel/ixd/Makefile | 13 +
drivers/net/ethernet/intel/ixd/ixd.h | 58 +
drivers/net/ethernet/intel/ixd/ixd_ctlq.c | 149 ++
drivers/net/ethernet/intel/ixd/ixd_ctlq.h | 33 +
drivers/net/ethernet/intel/ixd/ixd_dev.c | 89 +
drivers/net/ethernet/intel/ixd/ixd_devlink.c | 97 +
drivers/net/ethernet/intel/ixd/ixd_devlink.h | 44 +
drivers/net/ethernet/intel/ixd/ixd_lan_regs.h | 68 +
drivers/net/ethernet/intel/ixd/ixd_lib.c | 166 ++
drivers/net/ethernet/intel/ixd/ixd_main.c | 147 ++
drivers/net/ethernet/intel/ixd/ixd_virtchnl.c | 178 ++
drivers/net/ethernet/intel/ixd/ixd_virtchnl.h | 12 +
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 +-
.../ethernet/intel/ixgbe/ixgbe_type_e610.h | 2 +-
drivers/net/ethernet/intel/libeth/rx.c | 12 +-
drivers/net/ethernet/intel/libie/Kconfig | 14 +
drivers/net/ethernet/intel/libie/Makefile | 8 +
drivers/net/ethernet/intel/libie/adminq.c | 2 +-
drivers/net/ethernet/intel/libie/controlq.c | 1195 +++++++++++
drivers/net/ethernet/intel/libie/fwlog.c | 2 +-
drivers/net/ethernet/intel/libie/pci.c | 208 ++
drivers/net/ethernet/intel/libie/rx.c | 2 +-
include/linux/{net => }/intel/i40e_client.h | 0
include/linux/{net => }/intel/iidc_rdma.h | 0
include/linux/{net => }/intel/iidc_rdma_ice.h | 0
.../linux/{net => }/intel/iidc_rdma_idpf.h | 0
include/linux/{net => }/intel/libie/adminq.h | 0
include/linux/intel/libie/controlq.h | 424 ++++
include/linux/{net => }/intel/libie/fwlog.h | 2 +-
include/linux/intel/libie/pci.h | 56 +
include/linux/{net => }/intel/libie/pctype.h | 0
include/linux/{net => }/intel/libie/rx.h | 0
include/linux/{avf => intel}/virtchnl.h | 0
.../idpf => include/linux/intel}/virtchnl2.h | 0
.../linux/intel}/virtchnl2_lan_desc.h | 0
include/net/libeth/rx.h | 4 +-
97 files changed, 4196 insertions(+), 2876 deletions(-)
create mode 100644 Documentation/networking/device_drivers/ethernet/intel/ixd.rst
create mode 100644 Documentation/networking/devlink/ixd.rst
delete mode 100644 drivers/net/ethernet/intel/idpf/idpf_controlq.c
delete mode 100644 drivers/net/ethernet/intel/idpf/idpf_controlq.h
delete mode 100644 drivers/net/ethernet/intel/idpf/idpf_controlq_api.h
delete mode 100644 drivers/net/ethernet/intel/idpf/idpf_controlq_setup.c
delete mode 100644 drivers/net/ethernet/intel/idpf/idpf_mem.h
create mode 100644 drivers/net/ethernet/intel/ixd/Kconfig
create mode 100644 drivers/net/ethernet/intel/ixd/Makefile
create mode 100644 drivers/net/ethernet/intel/ixd/ixd.h
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_ctlq.c
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_ctlq.h
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_dev.c
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_devlink.c
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_devlink.h
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_lan_regs.h
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_lib.c
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_main.c
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_virtchnl.c
create mode 100644 drivers/net/ethernet/intel/ixd/ixd_virtchnl.h
create mode 100644 drivers/net/ethernet/intel/libie/controlq.c
create mode 100644 drivers/net/ethernet/intel/libie/pci.c
rename include/linux/{net => }/intel/i40e_client.h (100%)
rename include/linux/{net => }/intel/iidc_rdma.h (100%)
rename include/linux/{net => }/intel/iidc_rdma_ice.h (100%)
rename include/linux/{net => }/intel/iidc_rdma_idpf.h (100%)
rename include/linux/{net => }/intel/libie/adminq.h (100%)
create mode 100644 include/linux/intel/libie/controlq.h
rename include/linux/{net => }/intel/libie/fwlog.h (98%)
create mode 100644 include/linux/intel/libie/pci.h
rename include/linux/{net => }/intel/libie/pctype.h (100%)
rename include/linux/{net => }/intel/libie/rx.h (100%)
rename include/linux/{avf => intel}/virtchnl.h (100%)
rename {drivers/net/ethernet/intel/idpf => include/linux/intel}/virtchnl2.h (100%)
rename {drivers/net/ethernet/intel/idpf => include/linux/intel}/virtchnl2_lan_desc.h (100%)
--
2.47.0
^ permalink raw reply
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
From: Francesco Lavra @ 2026-03-23 17:37 UTC (permalink / raw)
To: Andy Shevchenko
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
In-Reply-To: <acFvHgTo-3cxH_UP@ashevche-desk.local>
On Mon, 2026-03-23 at 18:49 +0200, Andy Shevchenko wrote:
> On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> > On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > > On 3/17/26 10:04 AM, Francesco Lavra wrote:
>
> ...
>
> > > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
>
> > > We could make this proper kernel doc format with one comment per
> > > macro.
> >
> > Actually, a set of related #defines can be documented with a single
> > comment. I see a few examples doing that in include/linux/gfp_types.h
> > and
> > include/linux/fpga/fpga-mgr.h
> >
> > > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
>
> ...or use enum
>
> /**
> * ...kernel-doc for enum...
> */
> enum {
> IIO_SCAN_FORMAT_SIGNED_INT = 's',
> IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
> };
There is no standard kernel-doc format for anonymous enums.
^ permalink raw reply
* Re: [PATCH v2 5/5] doc: watchdog: Document buddy detector
From: Petr Mladek @ 2026-03-23 17:26 UTC (permalink / raw)
To: mrungta
Cc: Jinchao Wang, Yunhui Cui, Stephane Eranian, Ian Rogers, Li Huafei,
Feng Tang, Max Kellermann, Jonathan Corbet, Douglas Anderson,
Andrew Morton, Florian Delizy, Shuah Khan, linux-kernel,
linux-doc
In-Reply-To: <20260312-hardlockup-watchdog-fixes-v2-5-45bd8a0cc7ed@google.com>
On Thu 2026-03-12 16:22:06, Mayank Rungta via B4 Relay wrote:
> From: Mayank Rungta <mrungta@google.com>
>
> The current documentation generalizes the hardlockup detector as primarily
> NMI-perf-based and lacks details on the SMP "Buddy" detector.
>
> Update the documentation to add a detailed description of the Buddy
> detector, and also restructure the "Implementation" section to explicitly
> separate "Softlockup Detector", "Hardlockup Detector (NMI/Perf)", and
> "Hardlockup Detector (Buddy)".
>
> Clarify that the softlockup hrtimer acts as the heartbeat generator for
> both hardlockup mechanisms and centralize the configuration details in a
> "Frequency and Heartbeats" section.
This is a great step forward. See few nits below:
> --- a/Documentation/admin-guide/lockup-watchdogs.rst
> +++ b/Documentation/admin-guide/lockup-watchdogs.rst
> @@ -30,22 +30,23 @@ timeout is set through the confusingly named "kernel.panic" sysctl),
> to cause the system to reboot automatically after a specified amount
> of time.
>
> +Configuration
> +=============
> +
> +A kernel knob is provided that allows administrators to configure
> +this period. The "watchdog_thresh" parameter (default 10 seconds)
> +controls the threshold. The right value for a particular environment
> +is a trade-off between fast response to lockups and detection overhead.
> +
> Implementation
> ==============
>
> -The soft and hard lockup detectors are built on top of the hrtimer and
> -perf subsystems, respectively. A direct consequence of this is that,
> -in principle, they should work in any architecture where these
> -subsystems are present.
> +The soft lockup detector is built on top of the hrtimer subsystem.
> +The hard lockup detector is built on top of the perf subsystem
> +(on architectures that support it) or uses an SMP "buddy" system.
This looks like a too big simplification. In fact, the hrtimer is
the core of all these detectors. The buddy detector uses only
the hrtimer. Also it would be nice to mention the scheduled
job used by softlockup detector.
See below for a proposal.
> -A periodic hrtimer runs to generate interrupts and kick the watchdog
> -job. An NMI perf event is generated every "watchdog_thresh"
> -(compile-time initialized to 10 and configurable through sysctl of the
> -same name) seconds to check for hardlockups. If any CPU in the system
> -does not receive any hrtimer interrupt during that time the
> -'hardlockup detector' (the handler for the NMI perf event) will
> -generate a kernel warning or call panic, depending on the
> -configuration.
> +Softlockup Detector
> +-------------------
>
> The watchdog job runs in a stop scheduling thread that updates a
> timestamp every time it is scheduled. If that timestamp is not updated
> @@ -55,53 +56,105 @@ will dump useful debug information to the system log, after which it
> will call panic if it was instructed to do so or resume execution of
> other kernel code.
>
> -The period of the hrtimer is 2*watchdog_thresh/5, which means it has
> -two or three chances to generate an interrupt before the hardlockup
> -detector kicks in.
> +Frequency and Heartbeats
> +------------------------
> +
> +The hrtimer used by the softlockup detector serves a dual purpose:
> +it detects softlockups, and it also generates the interrupts
> +(heartbeats) that the hardlockup detectors use to verify CPU liveness.
> +
> +The period of this hrtimer is 2*watchdog_thresh/5. This means the
> +hrtimer has two or three chances to generate an interrupt before the
> +NMI hardlockup detector kicks in.
As I said, the hrtimer is the core of all detectors. I would explain
this first.
I propose the following changes on top of this one:
From f1cfdc330cfbc68568dfe6bf2513bde9373c89d7 Mon Sep 17 00:00:00 2001
From: Petr Mladek <pmladek@suse.com>
Date: Mon, 23 Mar 2026 18:21:38 +0100
Subject: [PATCH] doc: watchdog: Futher improvements
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
.../admin-guide/lockup-watchdogs.rst | 44 ++++++++++---------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/Documentation/admin-guide/lockup-watchdogs.rst b/Documentation/admin-guide/lockup-watchdogs.rst
index 7ae7ce3abd2c..d0773edf3396 100644
--- a/Documentation/admin-guide/lockup-watchdogs.rst
+++ b/Documentation/admin-guide/lockup-watchdogs.rst
@@ -41,31 +41,35 @@ is a trade-off between fast response to lockups and detection overhead.
Implementation
==============
-The soft lockup detector is built on top of the hrtimer subsystem.
-The hard lockup detector is built on top of the perf subsystem
-(on architectures that support it) or uses an SMP "buddy" system.
-
-Softlockup Detector
--------------------
-
-The watchdog job runs in a stop scheduling thread that updates a
-timestamp every time it is scheduled. If that timestamp is not updated
-for 2*watchdog_thresh seconds (the softlockup threshold) the
-'softlockup detector' (coded inside the hrtimer callback function)
-will dump useful debug information to the system log, after which it
-will call panic if it was instructed to do so or resume execution of
-other kernel code.
+The soft and hard lockup detectors are built around a hrtimer.
+In addition, the softlockup detector regularly schedules a job, and
+the hard lockup detector might use Perf/NMI events on architectures
+that support it.
Frequency and Heartbeats
------------------------
-The hrtimer used by the softlockup detector serves a dual purpose:
-it detects softlockups, and it also generates the interrupts
-(heartbeats) that the hardlockup detectors use to verify CPU liveness.
+The core of the detectors in a hrtimer. It servers multiple purpose:
-The period of this hrtimer is 2*watchdog_thresh/5. This means the
-hrtimer has two or three chances to generate an interrupt before the
-NMI hardlockup detector kicks in.
+- schedules watchdog job for the softlockup detector
+- bumps the interrupt counter for hardlockup detectors (heartbeat)
+- detects softlockups
+- detects hardlockups in Buddy mode
+
+The period of this hrtimer is 2*watchdog_thresh/5, which is 4 seconds
+by default. The hrtimer has two or three chances to generate an interrupt
+(heartbeat) before the hardlockup detector kicks in.
+
+Softlockup Detector
+-------------------
+
+The watchdog job is scheduled by the hrtimer and runs in a stop scheduling
+thread. It updates a timestamp every time it is scheduled. If that timestamp
+is not updated for 2*watchdog_thresh seconds (the softlockup threshold) the
+'softlockup detector' (coded inside the hrtimer callback function)
+will dump useful debug information to the system log, after which it
+will call panic if it was instructed to do so or resume execution of
+other kernel code.
Hardlockup Detector (NMI/Perf)
------------------------------
--
2.53.0
Best Regards,
Petr
^ permalink raw reply related
* Re: [PATCH V8 3/8] dax: add fsdev.c driver for fs-dax on character dax
From: John Groves @ 2026-03-23 17:21 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Miklos Szeredi, Dan Williams, Bernd Schubert, Alison Schofield,
John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
David Hildenbrand, Christian Brauner, Darrick J . Wong,
Randy Dunlap, Jeff Layton, Amir Goldstein, Stefan Hajnoczi,
Joanne Koong, Josef Bacik, Bagas Sanjaya, Chen Linxuan,
James Morse, Fuad Tabba, Sean Christopherson, Shivank Garg,
Ackerley Tng, Gregory Price, Aravind Ramesh, Ajay Joshi,
venkataravis, linux-doc, linux-kernel, nvdimm, linux-cxl,
linux-fsdevel
In-Reply-To: <20260323121250.00004402@huawei.com>
On 26/03/23 12:12PM, Jonathan Cameron wrote:
>
> > > > diff --git a/drivers/dax/Makefile b/drivers/dax/Makefile
> > > > index 5ed5c39857c8..3bae252fd1bf 100644
> > > > --- a/drivers/dax/Makefile
> > > > +++ b/drivers/dax/Makefile
> > > > @@ -5,10 +5,16 @@ obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
> > > > obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
> > > > obj-$(CONFIG_DEV_DAX_CXL) += dax_cxl.o
> > > >
> > > > +# fsdev_dax: fs-dax compatible devdax driver (needs DEV_DAX and FS_DAX)
> > > > +ifeq ($(CONFIG_FS_DAX),y)
> > > > +obj-$(CONFIG_DEV_DAX) += fsdev_dax.o
> > > > +endif
> > >
> > > Why not throw in a new CONFIG_FSDAX_DEV and handle the dependencies
> > > in Kconfig?
> >
> > At one point I had another config parameter, but I'm trying not to
> > gratuitously add them. The fsdev driver is pretty small, and including it
> > whenever FS_DAX is enabled felt reasonable to me. I'm willing to change it
> > if there's a consensus that way.
>
> You can make the build do exactly the same thing with a separate Kconfig
> option. Just moves where the dependency tracking is. I'd prefer Kconfig
> because that's generally where I'd look for something like this.
>
>
> Jonathan
OK, will do. It will be CONFIG_DEV_DAX_FSDEV for naming consistency.
V9 coming within 24 hours...
John
^ permalink raw reply
* [PATCH 2/2] docs: pt_BR: Add translation for KVM x86 maintainer guide
From: Daniel Pereira @ 2026-03-23 17:11 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260323171133.88074-1-danielmaraboo@gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 24485 bytes --]
Translate the KVM x86 maintainer guidelines (maintainer-kvm-x86.rst)
into Portuguese (pt_BR). This document covers the specific
workflow, coding style, and testing requirements for the
KVM x86 subsystem.
Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
Documentation/translations/pt_BR/index.rst | 1 +
.../pt_BR/process/maintainer-kvm-x86.rst | 435 ++++++++++++++++++
2 files changed, 436 insertions(+)
create mode 100644 Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst
diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst
index efe6a4a3f..4a094d8b7 100644
--- a/Documentation/translations/pt_BR/index.rst
+++ b/Documentation/translations/pt_BR/index.rst
@@ -74,3 +74,4 @@ kernel e sobre como ver seu trabalho integrado.
Processo do subsistema de rede (netdev) <process/maintainer-netdev>
Processo do subsistema SoC <process/maintainer-soc>
Conformidade de DTS para SoC <process/maintainer-soc-clean-dts>
+ Processo do subsistema KVM x86 <process/maintainer-kvm-x86>
diff --git a/Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst b/Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst
new file mode 100644
index 000000000..6480ff08b
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst
@@ -0,0 +1,435 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+KVM x86
+=======
+
+Prefácio
+--------
+
+O KVM se esforça para ser uma comunidade acolhedora; as contribuições de
+recém-chegados são valorizadas e incentivadas. Por favor, não se sinta
+desanimado ou intimidado pela extensão deste documento e pelas muitas
+regras/diretrizes que ele contém. Todo mundo comete erros e todo mundo já foi um
+novato em algum momento. Desde que você faça um esforço honesto para seguir as
+diretrizes do KVM x86, seja receptivo ao feedback e aprenda com os erros que
+cometer, você será recebido de braços abertos, não com tochas e forquilhas.
+
+(TL;DR)
+--------
+Testes são obrigatórios. Seja consistente com os estilos e padrões estabelecidos.
+
+Árvores
+-------
+O KVM x86 está atualmente em um período de transição: deixando de fazer parte da
+árvore principal do KVM para se tornar "apenas mais uma arquitetura KVM". Como tal,
+o KVM x86 está dividido entre a árvore principal do KVM,
+``git.kernel.org/pub/scm/virt/kvm/kvm.git``, e uma árvore específica para KVM x86,
+``github.com/kvm-x86/linux.git``.
+
+De modo geral, as correções (fixes) para o ciclo atual são aplicadas diretamente
+na árvore principal do KVM, enquanto todo o desenvolvimento para o próximo ciclo
+é roteado através da árvore do KVM x86. No caso improvável de uma correção para o
+ciclo atual ser roteada através da árvore do KVM x86, ela será aplicada à branch
+``fixes`` antes de seguir para a árvore principal do KVM.
+
+Note que espera-se que este período de transição dure bastante tempo, ou seja,
+será o status quo em um futuro próximo.
+
+Branches
+~~~~~~~~
+A árvore do KVM x86 é organizada em múltiplas branches de tópicos (topic
+branches). O objetivo de usar branches de tópicos mais granulares é facilitar o
+acompanhamento de uma área específica de desenvolvimento e limitar os danos
+colaterais de erros humanos e/ou commits com bugs; por exemplo, descartar o
+commit HEAD de uma branch de tópico não tem impacto nos hashes SHA1 de outros
+commits em andamento, e a necessidade de rejeitar um pull request devido a bugs
+atrasa apenas aquela branch de tópico específica.
+
+Todas as branches de tópicos, exceto a ``next`` e a ``fixes``, são incorporadas
+na ``next`` via um "Cthulhu merge" conforme a necessidade, ou seja, sempre que
+uma branch de tópico é atualizada. Como resultado, force pushes para a branch
+``next`` são comuns.
+
+Ciclo de Vida
+~~~~~~~~~~~~~
+As correções (fixes) destinadas ao lançamento atual, também conhecido como
+mainline, são normalmente aplicadas diretamente na árvore principal do KVM, ou
+seja, não passam pela árvore do KVM x86.
+
+As mudanças destinadas ao próximo lançamento são roteadas através da árvore do
+KVM x86. Pull requests (do KVM x86 para o KVM principal) são enviados para cada
+branch de tópico do KVM x86, normalmente na semana anterior à abertura da janela
+de merge por Linus, por exemplo, na semana seguinte ao rc7 para lançamentos
+"normais". Se tudo correr bem, as branches de tópicos são incorporadas ao pull
+request principal do KVM enviado durante a janela de merge de Linus.
+
+A árvore do KVM x86 não possui sua própria janela de merge oficial, mas há um
+"soft close" (fechamento flexível) por volta do rc5 para novos recursos, e um
+"soft close" por volta do rc6 para correções (para o próximo lançamento; veja
+acima para correções destinadas ao lançamento atual).
+
+Cronograma
+----------
+As submissões são normalmente revisadas e aplicadas em ordem FIFO (primeiro a
+entrar, primeiro a sair), com alguma margem de manobra para o tamanho de uma
+série, patches que estão "cache hot", etc. Correções (fixes), especialmente para
+o lançamento atual e/ou árvores estáveis (stable trees), têm prioridade na fila.
+Patches que serão aceitos através de uma árvore não-KVM (mais frequentemente
+através da árvore "tip") e/ou que possuam outros "acks"/revisões também ganham
+certa prioridade.
+
+Note que a grande maioria das revisões é feita entre o rc1 e o rc6,
+aproximadamente. O período entre o rc6 e o próximo rc1 é usado para colocar
+outras tarefas em dia, ou seja, o "silêncio de rádio" durante este período não é
+incomum.
+
+Pings para obter uma atualização de status são bem-vindos, mas tenha em mente o
+tempo do ciclo de lançamento atual e tenha expectativas realistas. Se você está
+dando um ping para aceitação — ou seja, não apenas para feedback ou uma
+atualização — por favor, faça tudo o que puder, dentro do razoável, para garantir
+que seus patches estejam prontos para o merge! Pings em séries que quebram o
+build ou falham em testes resultam em mantenedores infelizes!
+
+Desenvolvimento
+---------------
+
+Árvore/Branch Base
+~~~~~~~~~~~~~~~~~~
+Correções destinadas ao lançamento atual, também conhecido como mainline, devem
+ser baseadas em ``git://git.kernel.org/pub/scm/virt/kvm/kvm.git master``. Note
+que as correções não garantem inclusão automática no lançamento atual. Não
+existe uma regra única, mas tipicamente apenas correções para bugs que sejam
+urgentes, críticos e/ou que tenham sido introduzidos no lançamento atual devem
+ser destinadas ao lançamento atual.
+
+Todo o restante deve ser baseado em ``kvm-x86/next``, ou seja, não há
+necessidade de selecionar uma branch de tópico específica como base. Se houver
+conflitos e/ou dependências entre as branches de tópicos, é trabalho do
+mantenedor resolvê-los.
+
+A única exceção ao uso da ``kvm-x86/next`` como base é se um patch/série for uma
+série multi-arquitetura (multi-arch), ou seja, possuir modificações não triviais
+no código comum do KVM e/ou possuir mudanças mais do que superficiais no código
+de outras arquiteturas. Patches/séries multi-arquitetura devem, em vez disso,
+ser baseados em um ponto comum e estável no histórico do KVM, por exemplo, o
+release candidate no qual a ``kvm-x86 next`` se baseia. Se você não tiver
+certeza se um patch/série é verdadeiramente multi-arquitetura, erre pelo lado da
+cautela e trate-o como tal, ou seja, use uma base comum.
+
+Estilo de Codificação
+~~~~~~~~~~~~~~~~~~~~~
+Quando se trata de estilo, nomenclatura, padrões, etc., a consistência é a
+prioridade número um no KVM x86. Se tudo mais falhar, siga o que já existe.
+
+Com algumas ressalvas listadas abaixo, siga o estilo de codificação preferido
+dos mantenedores da árvore "tip" (:ref:`maintainer-tip-coding-style`), já que
+patches/séries frequentemente tocam tanto arquivos do KVM quanto arquivos x86
+não-KVM, ou seja, atraem a atenção de mantenedores do KVM *e* da árvore "tip".
+
+O uso de "reverse fir tree" (árvore de abeto invertida), também conhecido como
+"árvore de Natal invertida", para declarações de variáveis não é estritamente
+obrigatório, embora ainda seja preferido.
+
+Exceto por alguns casos excepcionais, não use comentários kernel-doc para
+funções. A grande maioria das funções "públicas" do KVM não são verdadeiramente
+públicas, pois se destinam apenas ao consumo interno do KVM (há planos para
+privatizar os headers e exports do KVM para reforçar isso).
+
+Comentários
+~~~~~~~~~~~
+Escreva comentários usando o modo imperativo e evite pronomes. Use comentários
+para fornecer uma visão geral de alto nível do código e/ou para explicar por
+que o código faz o que faz. Não reitere o que o código faz literalmente; deixe
+o código falar por si mesmo. Se o código em si for inescrutável, comentários
+não ajudarão.
+
+Referências ao SDM e ao APM
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Grande parte da base de código do KVM está diretamente ligada ao comportamento
+arquitetural definido no Manual de Desenvolvimento de Software (SDM) da Intel e
+no Manual do Programador de Arquitetura (APM) da AMD. O uso de "Intel SDM" e
+"AMD APM", ou até mesmo apenas "SDM" ou "APM", sem contexto adicional, é
+perfeitamente aceitável.
+
+Não faça referência a seções, tabelas, figuras, etc., por número, especialmente
+em comentários. Em vez disso, se necessário (veja abaixo), copie e cole o trecho
+relevante e referencie seções/tabelas/figuras pelo nome. Os layouts do SDM e do
+APM mudam constantemente e, portanto, os números/rótulos não são estáveis.
+
+De modo geral, não faça referência explícita nem copie e cole do SDM ou do APM
+em comentários. Com poucas exceções, o KVM *deve* respeitar o comportamento
+arquitetural; portanto, subentende-se que o comportamento do KVM está emulando o
+comportamento do SDM e/ou do APM. Note que fazer referência ao SDM/APM em
+changelogs para justificar a mudança e fornecer contexto é perfeitamente
+aceitável e incentivado.
+
+Shortlog
+~~~~~~~~
+O formato de prefixo preferencial é ``KVM: <topic>:``, onde ``<topic>`` é um dos
+seguintes::
+
+ - x86
+ - x86/mmu
+ - x86/pmu
+ - x86/xen
+ - selftests
+ - SVM
+ - nSVM
+ - VMX
+ - nVMX
+
+**NÃO use x86/kvm!** ``x86/kvm`` é usado exclusivamente para mudanças no Linux
+como convidado (guest) de um KVM, ou seja, para ``arch/x86/kernel/kvm.c``. Não
+use nomes de arquivos ou caminhos completos de arquivos como prefixo do
+assunto/shortlog.
+
+Note que estes não se alinham com as branches de tópicos (as branches de tópicos
+se preocupam muito mais com conflitos de código).
+
+Todos os nomes são sensíveis a maiúsculas e minúsculas! ``KVM: x86:`` é bom,
+``kvm: vmx:`` não é.
+
+Comece com letra maiúscula a primeira palavra da descrição condensada do patch,
+mas omita a pontuação final. Ex.::
+
+ KVM: x86: Fix a null pointer dereference in function_xyz()
+
+e não::
+
+ kvm: x86: fix a null pointer dereference in function_xyz.
+
+Se um patch tocar em múltiplos tópicos, suba na árvore conceitual para encontrar
+o primeiro pai comum (que geralmente é apenas ``x86``). Em caso de dúvida,
+``git log caminho/do/arquivo`` deve fornecer uma dica razoável.
+
+Novos tópicos surgem ocasionalmente, mas, por favor, inicie uma discussão na
+lista se desejar propor a introdução de um novo tópico; ou seja, não aja por
+conta própria.
+
+Veja :ref:`the_canonical_patch_format` para mais informações, com uma ressalva:
+não trate o limite de 70-75 caracteres como um limite absoluto e rígido. Em
+vez disso, use 75 caracteres como um limite firme, mas não rígido, e use 80
+caracteres como um limite intransponível. Ou seja, permita que o shortlog
+ultrapasse alguns caracteres do limite padrão se você tiver um bom motivo para
+fazê-lo.
+
+Changelog
+~~~~~~~~~
+O mais importante: escreva os changelogs usando o modo imperativo e evite o uso
+de pronomes.
+
+Veja :ref:`describe_changes` para mais informações, com uma ressalva: comece com
+uma breve descrição das mudanças reais e, em seguida, apresente o contexto e o
+histórico. Note! Esta ordem entra em conflito direto com a abordagem preferida
+da árvore "tip"! Por favor, siga o estilo preferido da árvore "tip" ao enviar
+patches que visam primariamente o código de arch/x86 que _NÃO_ seja código KVM.
+
+Declarar o que um patch faz antes de mergulhar nos detalhes é preferido pelo KVM
+x86 por vários motivos. Primeiro e mais importante, qual código está sendo
+realmente alterado é, reconhecidamente, a informação mais importante e,
+portanto, essa informação deve ser fácil de encontrar. Changelogs que escondem
+"o que está mudando de fato" em uma única linha após 3 ou mais parágrafos de
+histórico tornam muito difícil encontrar essa informação.
+
+Para uma revisão inicial, pode-se argumentar que "o que está quebrado" é mais
+importante, mas para uma leitura rápida de logs e arqueologia do git, os
+detalhes minuciosos importam cada vez menos. Por exemplo, ao fazer uma série de
+"git blame", os detalhes de cada mudança ao longo do caminho são inúteis; os
+detalhes só importam para o culpado. Fornecer "o que mudou" facilita determinar
+rapidamente se um commit pode ou não ser de interesse.
+
+Outro benefício de declarar "o que está mudando" primeiro é que quase sempre é
+possível declarar "o que está mudando" em uma única frase. Por outro lado,
+exceto pelos bugs mais simples, todos exigem várias frases ou parágrafos para
+descrever totalmente o problema. Se tanto "o que está mudando" quanto "qual é o
+bug" forem super curtos, a ordem não importa. Mas se um for mais curto (quase
+sempre o "o que está mudando"), então cobrir o mais curto primeiro é vantajoso
+porque é menos inconveniente para leitores/revisores que têm uma preferência de
+ordenação estrita. Ex: ter que pular uma frase para chegar ao contexto é menos
+doloroso do que ter que pular três parágrafos para chegar ao "o que está
+mudando".
+
+Correções (Fixes)
+~~~~~~~~~~~~~~~~~
+Se uma mudança corrige um bug do KVM/kernel, adicione uma tag Fixes:, mesmo que
+a mudança não precise ser portada (backported) para kernels estáveis, e mesmo
+que a mudança corrija um bug em uma versão mais antiga.
+
+Por outro lado, se uma correção realmente precisar de backport, marque
+explicitamente o patch com "Cc: stable@vger.kernel.org" (embora o e-mail em si
+não precise enviar cópia para a lista stable); o KVM x86 opta por não realizar
+o backport automático de tags Fixes: por padrão. Alguns patches selecionados
+automaticamente são portados, mas exigem aprovação explícita do mantenedor
+(pesquise por MANUALSEL).
+
+Referências a Funções
+~~~~~~~~~~~~~~~~~~~~~
+Quando uma função for mencionada em um comentário, changelog ou shortlog (ou em
+qualquer outro lugar, aliás), use o formato ``nome_da_funcao()``. Os parênteses
+fornecem contexto e removem a ambiguidade da referência.
+
+Testes
+------
+No mínimo, *todos* os patches de uma série devem compilar sem erros para
+KVM_INTEL=m, KVM_AMD=m e KVM_WERROR=y. Compilar cada combinação possível de
+Kconfigs não é viável, mas quanto mais, melhor. KVM_SMM, KVM_XEN, PROVE_LOCKING
+e X86_64 são opções (knobs) particularmente interessantes para se testar.
+
+A execução de KVM selftests e KVM-unit-tests também é obrigatória (e, para
+afirmar o óbvio, os testes precisam passar). A única exceção é para mudanças
+que tenham probabilidade insignificante de afetar o comportamento em tempo de
+execução, por exemplo, patches que apenas modificam comentários. Sempre que
+possível e relevante, o teste tanto em Intel quanto em AMD é fortemente
+preferido. A inicialização de uma VM real é incentivada, mas não obrigatória.
+
+Para mudanças que tocam o código de shadow paging do KVM, executar com o TDP
+(EPT/NPT) desabilitado é obrigatório. Para mudanças que afetam o código comum da
+MMU do KVM, a execução com o TDP desabilitado é fortemente incentivada. Para
+todas as outras mudanças, se o código sendo modificado depender de e/ou
+interagir com um parâmetro de módulo (module param), o teste com as
+configurações relevantes é obrigatório.
+
+Note que o KVM selftests e o KVM-unit-tests possuem falhas conhecidas. Se você
+suspeitar que uma falha não se deve às suas alterações, verifique se a *exata
+mesma* falha ocorre com e sem as suas mudanças.
+
+Mudanças que tocam a documentação em reStructuredText, ou seja, arquivos .rst,
+devem compilar o htmldocs de forma limpa, ou seja, sem novos avisos (warnings)
+ou erros.
+
+Se você não puder testar totalmente uma mudança, por exemplo, devido à falta de
+hardware, declare claramente qual nível de teste você foi capaz de realizar,
+por exemplo, na cover letter (carta de apresentação).
+
+Novos Recursos
+~~~~~~~~~~~~~~
+Com uma exceção, novos recursos *devem* vir acompanhados de cobertura de testes.
+Testes específicos do KVM não são estritamente obrigatórios, por exemplo, se a
+cobertura for fornecida ao executar uma VM convidada (guest) suficientemente
+habilitada, ou ao executar um selftest de kernel relacionado em uma VM, mas
+testes dedicados do KVM são preferidos em todos os casos. Casos de teste
+negativos, em particular, são obrigatórios para a habilitação de novos recursos
+de hardware, já que fluxos de erro e exceção raramente são exercitados
+simplesmente ao executar uma VM.
+
+A única exceção a esta regra é se o KVM estiver simplesmente anunciando suporte
+para um recurso via KVM_GET_SUPPORTED_CPUID, ou seja, para instruções/recursos
+que o KVM não pode impedir um convidado de usar e para os quais não há uma
+habilitação real.
+
+Note que "novos recursos" não significa apenas "novos recursos de hardware"!
+Novos recursos que não podem ser bem validados usando os KVM selftests e/ou
+KVM-unit-tests existentes devem vir acompanhados de testes.
+
+Enviar o desenvolvimento de novos recursos sem testes para obter feedback
+antecipado é mais do que bem-vindo, mas tais submissões devem ser marcadas como
+RFC, e a carta de apresentação (cover letter) deve declarar claramente que tipo
+de feedback é solicitado/esperado. Não abuse do processo de RFC; as RFCs
+normalmente não receberão uma revisão profunda.
+
+Correções de Bugs
+~~~~~~~~~~~~~~~~~
+Exceto por bugs "óbvios" encontrados por inspeção, as correções devem vir
+acompanhadas de um reprodutor (reproducer) para o bug que está sendo corrigido.
+Em muitos casos, o reprodutor é implícito, por exemplo, para erros de build e
+falhas de teste, mas ainda assim deve estar claro para os leitores o que está
+quebrado e como verificar a correção. Alguma margem de manobra é dada para
+bugs encontrados através de cargas de trabalho ou testes não públicos, mas a
+disponibilização de testes de regressão para tais bugs é fortemente preferida.
+
+Em geral, testes de regressão são preferidos para qualquer bug que não seja
+trivial de ser atingido. Por exemplo, mesmo que o bug tenha sido originalmente
+encontrado por um fuzzer como o syzkaller, um teste de regressão direcionado
+pode ser justificável se o bug exigir que se atinja uma condição de corrida do
+tipo "uma em um milhão".
+
+Note que os bugs do KVM raramente são urgentes *e* não triviais de reproduzir.
+Pergunte a si mesmo se um bug é realmente o fim do mundo antes de enviar uma
+correção sem um reprodutor.
+
+Postagem
+--------
+
+Links
+~~~~~
+Não faça referência explícita a relatórios de bugs, versões anteriores de um
+patch/série, etc., através de cabeçalhos ``In-Reply-To:``. O uso de
+``In-Reply-To:`` torna-se uma bagunça infernal para grandes séries e/ou quando
+o número de versões aumenta, e o ``In-Reply-To:`` é inútil para qualquer
+pessoa que não tenha a mensagem original, por exemplo, se alguém não estava
+em cópia (Cc) no relatório do bug ou se a lista de destinatários mudar entre
+as versões.
+
+Para vincular a um relatório de bug, versão anterior ou qualquer coisa de
+interesse, use links do lore. Para referenciar versão(ões) anterior(es), de modo
+geral, não inclua um Link: no changelog, pois não há necessidade de registrar o
+histórico no git; ou seja, coloque o link na carta de apresentação (cover
+letter) ou na seção que o git ignora. Forneça um Link: formal para relatórios
+de bugs e/ou discussões que levaram ao patch. O contexto de por que uma mudança
+foi feita é altamente valioso para futuros leitores.
+
+Base do Git (Git Base)
+~~~~~~~~~~~~~~~~~~~~~~
+Se você estiver usando o git versão 2.9.0 ou posterior (Googlers, isso inclui
+todos vocês!), use ``git format-patch`` com a flag ``--base`` para incluir
+automaticamente as informações da árvore base nos patches gerados.
+
+Note que ``--base=auto`` funciona conforme o esperado se, e somente se, o
+upstream de uma branch estiver definido para a branch de tópico base; por
+exemplo, ele fará a coisa errada se o seu upstream estiver definido para o seu
+repositório pessoal para fins de backup. Uma solução "auto" alternativa é
+derivar os nomes das suas branches de desenvolvimento com base no seu tópico
+KVM x86 e alimentar isso no ``--base``. Por exemplo,
+``x86/pmu/minha_branch`` e, em seguida, escrever um pequeno wrapper para
+extrair ``pmu`` do nome da branch atual para resultar em ``--base=x/pmu``, onde
+``x`` é o nome que seu repositório usa para rastrear o remoto do KVM x86.
+
+Postagem Conjunta de Testes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+KVM selftests que estão associados a mudanças no KVM, por exemplo, testes de
+regressão para correções de bugs, devem ser postados junto com as mudanças do
+KVM como uma única série. As regras padrão do kernel para bissecção (bisection)
+se aplicam, ou seja, mudanças no KVM que resultem em falhas de teste devem ser
+ordenadas após as atualizações dos selftests e, vice-versa, novos testes que
+falhem devido a bugs do KVM devem ser ordenados após as correções do KVM.
+
+KVM-unit-tests devem *sempre* ser postados separadamente. Ferramentas, como o
+b4 am, não sabem que o KVM-unit-tests é um repositório separado e ficam
+confusas quando os patches de uma série se aplicam a árvores diferentes. Para
+vincular os patches do KVM-unit-tests aos patches do KVM, poste primeiro as
+mudanças do KVM e, em seguida, forneça um link do lore para o patch/série do
+KVM no(s) patch(es) do KVM-unit-tests.
+
+Notificações
+------------
+Quando um patch/série é oficialmente aceito, um e-mail de notificação será
+enviado em resposta à postagem original (carta de apresentação para séries de
+múltiplos patches). A notificação incluirá a árvore e a branch de tópico,
+juntamente com os SHA1s dos commits dos patches aplicados.
+
+Se um subconjunto de patches for aplicado, isso será claramente declarado na
+notificação. A menos que seja dito o contrário, subentende-se que quaisquer
+patches na série que não foram aceitos precisam de mais trabalho e devem ser
+enviados em uma nova versão.
+
+Se, por algum motivo, um patch for descartado após ter sido oficialmente
+aceito, uma resposta será enviada ao e-mail de notificação explicando o porquê
+do descarte, bem como os próximos passos.
+
+Estabilidade de SHA1
+~~~~~~~~~~~~~~~~~~~~
+Os SHA1s não têm garantia de serem 100% estáveis até que cheguem na árvore do
+Linus! Um SHA1 é *geralmente* estável uma vez que a notificação tenha sido
+enviada, mas imprevistos acontecem. Na maioria dos casos, uma atualização no
+e-mail de notificação será fornecida se o SHA1 de um patch aplicado mudar. No
+entanto, em alguns cenários, por exemplo, se todas as branches do KVM x86
+precisarem de rebase, as notificações individuais não serão enviadas.
+
+Vulnerabilidades
+----------------
+Bugs que podem ser explorados pelo convidado (guest) para atacar o hospedeiro
+(host) (kernel ou espaço do usuário), ou que podem ser explorados por uma VM
+aninhada (nested) contra o *seu* próprio hospedeiro (L2 atacando L1), são de
+interesse particular para o KVM. Por favor, siga o protocolo em
+:ref:`securitybugs` se você suspeitar que um bug possa levar a um escape,
+vazamento de dados, etc.
--
2.47.3
^ permalink raw reply related
* [PATCH 1/2] docs: pt_BR: Add translation for process/conclave.rst
From: Daniel Pereira @ 2026-03-23 17:11 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-doc, Daniel Pereira
In-Reply-To: <20260323171133.88074-1-danielmaraboo@gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 3608 bytes --]
Translate the Linux kernel project continuity documentation (conclave.rst)
into Portuguese (pt_BR). Also, update the main pt_BR index to include
the link to the new translation.
Signed-off-by: Daniel Pereira <danielmaraboo@gmail.com>
---
Documentation/translations/pt_BR/index.rst | 1 +
.../translations/pt_BR/process/conclave.rst | 40 +++++++++++++++++++
2 files changed, 41 insertions(+)
create mode 100644 Documentation/translations/pt_BR/process/conclave.rst
diff --git a/Documentation/translations/pt_BR/index.rst b/Documentation/translations/pt_BR/index.rst
index a89837aef..efe6a4a3f 100644
--- a/Documentation/translations/pt_BR/index.rst
+++ b/Documentation/translations/pt_BR/index.rst
@@ -69,6 +69,7 @@ kernel e sobre como ver seu trabalho integrado.
Introdução <process/1.Intro>
Como começar <process/howto>
Requisitos mínimos <process/changes>
+ Conclave (Continuidade do projeto) <process/conclave>
Manuais dos mantenedores <process/maintainer-handbooks>
Processo do subsistema de rede (netdev) <process/maintainer-netdev>
Processo do subsistema SoC <process/maintainer-soc>
diff --git a/Documentation/translations/pt_BR/process/conclave.rst b/Documentation/translations/pt_BR/process/conclave.rst
new file mode 100644
index 000000000..9071b5a39
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/conclave.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Continuidade do projeto do kernel Linux
+=======================================
+
+O projeto de desenvolvimento do kernel Linux é amplamente distribuído, com mais de
+100 mantenedores, cada um trabalhando para manter as mudanças fluindo através de
+seus próprios repositórios. A etapa final, no entanto, é centralizada, onde as
+mudanças são puxadas para o repositório mainline. Isso é normalmente feito por
+Linus Torvalds mas, como foi demonstrado pelo lançamento da versão 4.19 em 2018,
+existem outros que podem realizar esse trabalho quando surge a necessidade.
+
+Caso os mantenedores desse repositório se tornem indispostos ou incapazes de
+realizar esse trabalho daqui em diante (incluindo a facilitação de uma transição),
+o projeto precisará encontrar um ou mais substitutos sem demora. O processo pelo
+qual isso será feito está listado abaixo. O $ORGANIZER é o último organizador do
+Maintainer Summit ou o atual presidente do Conselho Consultivo Técnico (TAB) da
+Linux Foundation (LF) como reserva.
+
+- Em até 72 horas, o $ORGANIZER abrirá uma discussão com os convidados do
+ Maintainer Summit concluído mais recentemente. Uma reunião desses convidados e
+ do TAB, seja online ou presencial, será agendada o mais rápido possível de uma
+ forma que maximize o número de pessoas que possam participar.
+
+- Se não houver ocorrido um Maintainer Summit nos últimos 15 meses, o conjunto de
+ convidados para esta reunião será determinado pelo TAB.
+
+- Os convidados para esta reunião podem trazer outros mantenedores conforme
+ necessário.
+
+- Esta reunião, presidida pelo $ORGANIZER, considerará opções para a gestão
+ contínua do repositório de nível superior do kernel, de forma consistente com
+ a expectativa de maximizar a saúde a longo prazo do projeto e de sua comunidade.
+
+- Em até duas semanas, um representante deste grupo comunicará à comunidade em
+ geral, utilizando a lista de discussão ksummit@lists.linux.dev, quais serão os
+ próximos passos.
+
+A Linux Foundation, conforme orientada pelo TAB, tomará as medidas necessárias
+para apoiar e implementar este plano.
--
2.47.3
^ permalink raw reply related
* [PATCH 0/2] docs: pt_BR: Add translations for KVM x86 and Conclave
From: Daniel Pereira @ 2026-03-23 17:11 UTC (permalink / raw)
To: Jonathan Corbet; +Cc: linux-doc, Daniel Pereira
This series adds Portuguese (pt_BR) translations for two documents in
the process and subsystem-specific documentation.
The first patch translates the KVM x86 maintainer guidelines, and the
second one adds the translation for the conclave documentation, which
covers project continuity.
Both files were validated with sphinx-build and checkpatch.pl.
Daniel Pereira (2):
docs: pt_BR: Add translation for process/conclave.rst
docs: pt_BR: Add translation for KVM x86 maintainer guide
Documentation/translations/pt_BR/index.rst | 2 +
Documentation/translations/pt_BR/process/conclave.rst | (linhas)
Documentation/translations/pt_BR/process/maintainer-kvm-x86.rst | (linhas)
^ permalink raw reply
* Re: [PATCH v7 03/10] x86/bhi: Rename clear_bhb_loop() to clear_bhb_loop_nofence()
From: Pawan Gupta @ 2026-03-23 17:07 UTC (permalink / raw)
To: Nikolay Borisov
Cc: x86, H. Peter Anvin, Josh Poimboeuf, David Kaplan,
Sean Christopherson, Borislav Petkov, Dave Hansen, Peter Zijlstra,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, KP Singh,
Jiri Olsa, David S. Miller, David Laight, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, David Ahern, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
Stanislav Fomichev, Hao Luo, Paolo Bonzini, Jonathan Corbet,
linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <6c315cb3-b3a0-478e-b8ec-36d82684d310@suse.com>
On Mon, Mar 23, 2026 at 04:44:24PM +0200, Nikolay Borisov wrote:
>
>
> On 19.03.26 г. 17:40 ч., Pawan Gupta wrote:
> > To reflect the recent change that moved LFENCE to the caller side.
> >
> > Suggested-by: Borislav Petkov <bp@alien8.de>
> > Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
>
>
> Nit: I think having the _nofence in the function name is leaking an
> implementation detail into the name/interface. I.e things change and we
> decide that the implementation of a particular function must change so we
> just do the change and substantiate it in the commit message or in a
> comment. Especially that we don't have a "with an lfence" version.
The explicit "_nofence" is because the series changes the implementation of
clear_bhb_loop() from lfence. If new call sites miss to add an lfence when
it is required could lead to a security issue. Having the "_nofence" in the
name helps avoid it.
Apart from the name, the commit message of patch 1/10 and the comment in
clear_bhb_loop() implementation covers this.
> What's more I'd consider this a "private" function, that's called via the
> CLEAR_BRANCH_HISTORY macros, the only place it's called directly is in the
> bpf jit code, but that's more of an exception.
Another place where the explicit "_nofence" in the name could help is while
applying the mitigation in vmscape_apply_mitigation(), which sets the
static call:
vmscape_apply_mitigation()
{
...
if (vmscape_mitigation == VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER)
static_call_update(vmscape_predictor_flush, write_ibpb);
else if (vmscape_mitigation == VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER)
static_call_update(vmscape_predictor_flush, clear_bhb_loop_nofence);
> Still,
>
> Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Thank you.
^ permalink raw reply
* Re: [PATCH v9 0/5] arm64/riscv: Add support for crashkernel CMA reservation
From: Andrew Morton @ 2026-03-23 16:55 UTC (permalink / raw)
To: Jinjie Ruan
Cc: corbet, skhan, catalin.marinas, will, chenhuacai, kernel, maddy,
mpe, npiggin, chleroy, pjw, palmer, aou, alex, tglx, mingo, bp,
dave.hansen, hpa, robh, saravanak, bhe, vgoyal, dyoung, rdunlap,
peterz, feng.tang, pawan.kumar.gupta, dapeng1.mi, kees, elver,
paulmck, lirongqing, safinaskar, rppt, ardb, leitao, jbohac,
cfsworks, osandov, tangyouling, sourabhjain, ritesh.list, eajames,
songshuaishuai, kevin.brodsky, samuel.holland, vishal.moola,
junhui.liu, coxu, liaoyuanhong, fuqiang.wang, x86, linux-doc,
linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
linux-riscv, devicetree, kexec
In-Reply-To: <20260323072745.2481719-1-ruanjinjie@huawei.com>
On Mon, 23 Mar 2026 15:27:40 +0800 Jinjie Ruan <ruanjinjie@huawei.com> wrote:
> The crash memory allocation, and the exclude of crashk_res, crashk_low_res
> and crashk_cma memory are almost identical across different architectures,
> This patch set handle them in crash core in a general way, which eliminate
> a lot of duplication code.
>
> And add support for crashkernel CMA reservation for arm64 and riscv.
Thanks. AI review has completed and it asks questions:
https://sashiko.dev/#/patchset/20260323072745.2481719-1-ruanjinjie@huawei.com
^ permalink raw reply
* Re: [PATCH 2/2] Documentation: document panic_on_unrecoverable_memory_failure sysctl
From: Randy Dunlap @ 2026-03-23 16:51 UTC (permalink / raw)
To: Breno Leitao, Miaohe Lin, Naoya Horiguchi, Andrew Morton,
Jonathan Corbet, Shuah Khan
Cc: linux-mm, linux-kernel, linux-doc, kernel-team
In-Reply-To: <20260323-ecc_panic-v1-2-72a1921726c5@debian.org>
On 3/23/26 8:29 AM, Breno Leitao wrote:
> Document the new vm.panic_on_unrecoverable_memory_failure sysctl in the
> admin guide, following the same format as panic_on_unrecovered_nmi.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> Documentation/admin-guide/sysctl/vm.rst | 27 +++++++++++++++++++++++++++
> 1 file changed, 27 insertions(+)
>
> diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst
> index 97e12359775c9..3310fb8272fb9 100644
> --- a/Documentation/admin-guide/sysctl/vm.rst
> +++ b/Documentation/admin-guide/sysctl/vm.rst
> +
> += ===================================================================
> +0 Try to continue operation (default).
> +1 Panic immediately. If the ``panic`` sysctl is also non-zero then the
> + machine will be rebooted.
> += ===================================================================
The table begin and end lines must be at least as long as the text (may be
longer). Please extend the =========== lines by a few characters.
--
~Randy
^ permalink raw reply
* Re: [PATCH] Documentation: PCI: Document decoding of TLP Header in AER messages
From: Bjorn Helgaas @ 2026-03-23 16:50 UTC (permalink / raw)
To: Lukas Wunner
Cc: Jonathan Corbet, linux-pci, linux-doc, Mika Westerberg,
Ilpo Jarvinen, Maciej Grochowski, Kai-Heng Feng
In-Reply-To: <bf826c41b4c1d255c7dcb16e266b52f774d944ed.1774246067.git.lukas@wunner.de>
On Mon, Mar 23, 2026 at 07:52:39AM +0100, Lukas Wunner wrote:
> The prefix/header of the TLP that caused an error is recorded by the Root
> Complex and emitted to the kernel log in raw hex format. Document the
> existence and usage of tlp-tool, which allows decoding the TLP Header
> into human-readable form.
>
> The TLP Header hints at the root cause of an error, yet is often ignored
> because of its seeming opaqueness. Instead, PCIe errors are frequently
> worked around by a change in the kernel without fully understanding the
> actual source of the problem. With more documentation on available tools
> we'll hopefully come up with better solutions.
>
> There are also wireshark dissectors for TLPs, but it seems they expect a
> complete TLP, not just the header, and they cannot grok the hex format
> emitted by the kernel directly. tlp-tool appears to be the most cut and
> dried solution out there.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> Cc: Maciej Grochowski <mx2pg@pm.me>
Applied to pci/for-linus for v7.0, thanks!
I tweaked the commit log to note that the Header Log is in the AER
Capability, which may be in any PCIe function.
> ---
> We could also go one step further and point users to this tool
> in a printk_once() message when the first error occurs.
> For now, just amending the documentation is probably sufficient.
>
> Documentation/PCI/pcieaer-howto.rst | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/Documentation/PCI/pcieaer-howto.rst b/Documentation/PCI/pcieaer-howto.rst
> index 3210c47..90fdfdd 100644
> --- a/Documentation/PCI/pcieaer-howto.rst
> +++ b/Documentation/PCI/pcieaer-howto.rst
> @@ -85,6 +85,16 @@ In the example, 'Requester ID' means the ID of the device that sent
> the error message to the Root Port. Please refer to PCIe specs for other
> fields.
>
> +The 'TLP Header' is the prefix/header of the TLP that caused the error
> +in raw hex format. To decode the TLP Header into human-readable form
> +one may use tlp-tool:
> +
> +https://github.com/mmpg-x86/tlp-tool
> +
> +Example usage::
> +
> + curl -L https://git.kernel.org/linus/2ca1c94ce0b6 | rtlp-tool --aer
> +
> AER Ratelimits
> --------------
>
> --
> 2.51.0
>
^ permalink raw reply
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
From: Andy Shevchenko @ 2026-03-23 16:49 UTC (permalink / raw)
To: Francesco Lavra
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
In-Reply-To: <af2128c68d2a14e1eb664ce9dc075ed02b640407.camel@baylibre.com>
On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > On 3/17/26 10:04 AM, Francesco Lavra wrote:
...
> > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> > We could make this proper kernel doc format with one comment per macro.
>
> Actually, a set of related #defines can be documented with a single
> comment. I see a few examples doing that in include/linux/gfp_types.h and
> include/linux/fpga/fpga-mgr.h
>
> > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
...or use enum
/**
* ...kernel-doc for enum...
*/
enum {
IIO_SCAN_FORMAT_SIGNED_INT = 's',
IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
};
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH 2/2] kallsyms: add BTF-based deep parameter rendering in oops dumps
From: Sasha Levin @ 2026-03-23 16:48 UTC (permalink / raw)
To: Andrew Morton, Masahiro Yamada, Nathan Chancellor, Nicolas Schier
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Peter Zijlstra, Josh Poimboeuf, Petr Mladek,
Alexei Starovoitov, Jonathan Corbet, David Gow, Kees Cook,
Greg KH, Luis Chamberlain, Steven Rostedt, Helge Deller,
Randy Dunlap, Geert Uytterhoeven, Juergen Gross, James Bottomley,
Alexey Dobriyan, Vlastimil Babka, Laurent Pinchart, Petr Pavlu,
x86, linux-kernel, linux-kbuild, linux-doc, linux-modules, bpf,
Sasha Levin
In-Reply-To: <20260323164858.1939248-1-sashal@kernel.org>
When CONFIG_KALLSYMS_PARAMINFO_BTF is enabled and a function parameter
is a pointer to a kernel struct, use BTF type information to safely
dereference the pointer and display struct member values in oops/WARN
dumps.
The rendering uses btf_type_snprintf_show() which internally uses
copy_from_kernel_nofault() for safe memory access, making it safe to
call in oops/panic context. Struct members are printed in a compact
two-column layout for readability.
Example output:
Function parameters (paraminfo_demo_crash):
file (struct file *) = 0xffff8bc043cb36c0
.f_mode = (fmode_t)67993630 .f_flags = (unsigned int)32769
.f_mapping = (struct address_space *)0x.. .f_inode = (struct inode *)0x..
.f_cred = (struct cred *)0x... .prev_pos = (loff_t)-1
Gated behind CONFIG_KALLSYMS_PARAMINFO_BTF which depends on both
CONFIG_KALLSYMS_PARAMINFO and CONFIG_DEBUG_INFO_BTF. No additional
kernel image size beyond BTF itself.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
init/Kconfig | 19 +++
kernel/Makefile | 1 +
kernel/kallsyms.c | 47 ++++--
kernel/kallsyms_paraminfo_btf.c | 267 ++++++++++++++++++++++++++++++++
lib/tests/paraminfo_kunit.c | 13 +-
scripts/gen_paraminfo.c | 80 ++++++++--
6 files changed, 384 insertions(+), 43 deletions(-)
create mode 100644 kernel/kallsyms_paraminfo_btf.c
diff --git a/init/Kconfig b/init/Kconfig
index 76d0c2da7d612..602594c86bf7e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2106,6 +2106,25 @@ config KALLSYMS_PARAMINFO
If unsure, say N.
+config KALLSYMS_PARAMINFO_BTF
+ bool "Render struct contents for pointer parameters in oops dumps"
+ depends on KALLSYMS_PARAMINFO && DEBUG_INFO_BTF
+ help
+ When a function parameter is a pointer to a kernel struct and BTF
+ type information is available, dereference the pointer and display
+ key struct members (1 level deep) in oops/WARN dumps.
+
+ When enabled, oops dumps may include additional indented lines
+ showing struct member values in a two-column layout:
+
+ file (struct file *) = 0xffff888123456000
+ .f_flags = (unsigned int)32769 .f_mode = (fmode_t)29
+
+ Requires CONFIG_DEBUG_INFO_BTF.
+ No additional kernel image size beyond BTF itself.
+
+ If unsure, say N.
+
# end of the "standard kernel features (expert users)" menu
config ARCH_HAS_MEMBARRIER_CALLBACKS
diff --git a/kernel/Makefile b/kernel/Makefile
index 6785982013dce..e47d911340cad 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_KALLSYMS_SELFTEST) += kallsyms_selftest.o
+obj-$(CONFIG_KALLSYMS_PARAMINFO_BTF) += kallsyms_paraminfo_btf.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_VMCORE_INFO) += vmcore_info.o elfcorehdr.o
obj-$(CONFIG_CRASH_RESERVE) += crash_reserve.o
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index af8de3d8e3ba3..362cfa80b2c08 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -510,16 +510,19 @@ bool kallsyms_lookup_lineinfo(unsigned long addr,
#define MAX_PARAMINFO_PARAMS 6
+#ifdef CONFIG_KALLSYMS_PARAMINFO_BTF
+void paraminfo_btf_show_ptr(unsigned long ptr_val, const char *type_str);
+#else
+static inline void paraminfo_btf_show_ptr(unsigned long ptr_val,
+ const char *type_str) {}
+#endif
+
/*
* x86-64 calling convention: arguments are passed in registers
* RDI, RSI, RDX, RCX, R8, R9 (in that order).
*/
#ifdef CONFIG_X86_64
-static const char * const paraminfo_reg_names[] = {
- "RDI", "RSI", "RDX", "RCX", "R8", "R9"
-};
-
static unsigned long paraminfo_get_reg(const struct pt_regs *regs,
unsigned int idx)
{
@@ -534,9 +537,6 @@ static unsigned long paraminfo_get_reg(const struct pt_regs *regs,
}
}
#else
-/* Stub for non-x86-64 architectures */
-static const char * const paraminfo_reg_names[] = {};
-
static unsigned long paraminfo_get_reg(const struct pt_regs *regs,
unsigned int idx)
{
@@ -586,13 +586,13 @@ void kallsyms_show_paraminfo(struct pt_regs *regs)
const u8 *data;
unsigned int num_params, i;
unsigned long ip, fault_addr;
- char sym_name[KSYM_NAME_LEN];
+ char sym_name[128];
unsigned long sym_size, sym_offset;
if (!regs || !paraminfo_num_funcs)
return;
- ip = regs->ip;
+ ip = instruction_pointer(regs);
/* Only handle kernel-mode faults */
if (user_mode(regs))
@@ -611,14 +611,23 @@ void kallsyms_show_paraminfo(struct pt_regs *regs)
return;
/*
- * Verify the IP is within a reasonable range of the function
- * start. paraminfo_func_addrs[] contains function start offsets;
- * check that we're not too far past the start. Use kallsyms to
- * verify we're in the right function.
+ * Verify the paraminfo entry actually matches the function
+ * containing the IP. Without this, if the faulting function
+ * has no paraminfo, the binary search silently returns the
+ * preceding function's entry — showing wrong parameter info.
*/
if (!kallsyms_lookup_size_offset(ip, &sym_size, &sym_offset))
return;
+ {
+ unsigned int func_start_offset;
+
+ func_start_offset = (unsigned int)(ip - sym_offset -
+ (unsigned long)_text);
+ if (paraminfo_func_addrs[func_idx] != func_start_offset)
+ return;
+ }
+
/* Decode the function's parameter data */
data = paraminfo_func_data + paraminfo_func_offsets[func_idx];
num_params = *data++;
@@ -631,9 +640,9 @@ void kallsyms_show_paraminfo(struct pt_regs *regs)
return;
/*
- * Read the fault address for highlighting. On x86, CR2 holds
- * the page fault linear address. On other architectures this
- * would need a different mechanism.
+ * Read CR2 for fault address highlighting. CR2 is only meaningful
+ * for page faults; for GPF, BUG, WARN, etc. it may hold a stale
+ * value. This is best-effort — a false match is harmless.
*/
#ifdef CONFIG_X86
fault_addr = read_cr2();
@@ -660,9 +669,13 @@ void kallsyms_show_paraminfo(struct pt_regs *regs)
is_fault_addr = fault_addr && (val == fault_addr);
- printk(KERN_DEFAULT " %-8s (%-20s) = 0x%016lx%s\n",
+ printk(KERN_DEFAULT " %-8s (%-20s) = 0x%016lx%s\n",
pname, ptype, val,
is_fault_addr ? " <-- fault address" : "");
+
+ /* If this is a pointer to a struct, try BTF deep rendering */
+ if (val && strstr(ptype, "*"))
+ paraminfo_btf_show_ptr(val, ptype);
}
}
EXPORT_SYMBOL_GPL(kallsyms_show_paraminfo);
diff --git a/kernel/kallsyms_paraminfo_btf.c b/kernel/kallsyms_paraminfo_btf.c
new file mode 100644
index 0000000000000..28ce1dd45f7a8
--- /dev/null
+++ b/kernel/kallsyms_paraminfo_btf.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * kallsyms_paraminfo_btf.c - BTF-based deep rendering for paraminfo
+ *
+ * Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+ *
+ * When CONFIG_KALLSYMS_PARAMINFO_BTF is enabled and a function parameter
+ * is a pointer to a kernel struct, this module uses BTF type information
+ * to safely dereference the pointer and display key struct members in
+ * oops/WARN dumps.
+ */
+
+#include <linux/btf.h>
+#include <linux/bpf.h>
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+
+/* Declared in kernel/kallsyms.c under CONFIG_KALLSYMS_PARAMINFO_BTF */
+void paraminfo_btf_show_ptr(unsigned long ptr_val, const char *type_str);
+
+extern struct btf *btf_vmlinux;
+
+/*
+ * Maximum output buffer for BTF rendering. Large structs (e.g.,
+ * struct dentry) need substantial space. This is declared static
+ * rather than on the stack because 4096 bytes would exceed the
+ * frame size limit. Oops context is effectively single-threaded
+ * (other CPUs are stopped or spinning), so a static buffer is safe.
+ */
+#define BTF_SHOW_BUF_LEN 4096
+
+/*
+ * Parse a type string like "struct file *" to extract the struct name.
+ * Writes into caller-provided @name_buf of size @bufsz.
+ * Returns @name_buf on success, or NULL if not a struct/union pointer type.
+ */
+static const char *extract_struct_name(const char *type_str, bool *is_union,
+ char *name_buf, size_t bufsz)
+{
+ const char *p, *end;
+
+ *is_union = false;
+
+ /* Must end with " *" to be a pointer */
+ end = type_str + strlen(type_str);
+ if (end - type_str < 3 || end[-1] != '*' || end[-2] != ' ')
+ return NULL;
+
+ if (!strncmp(type_str, "struct ", 7)) {
+ p = type_str + 7;
+ } else if (!strncmp(type_str, "union ", 6)) {
+ p = type_str + 6;
+ *is_union = true;
+ } else {
+ return NULL;
+ }
+
+ /* Copy name up to the " *" */
+ {
+ size_t len = (end - 2) - p;
+
+ if (len == 0 || len >= bufsz)
+ return NULL;
+ memcpy(name_buf, p, len);
+ name_buf[len] = '\0';
+ }
+
+ return name_buf;
+}
+
+/*
+ * Show BTF-rendered struct contents for a pointer parameter.
+ * Called from kallsyms_show_paraminfo() when the parameter is a
+ * struct/union pointer.
+ *
+ * Uses btf_type_snprintf_show() which internally uses
+ * copy_from_kernel_nofault() for safe memory access, making it
+ * safe to call in oops/panic context.
+ */
+void paraminfo_btf_show_ptr(unsigned long ptr_val, const char *type_str)
+{
+ static char buf[BTF_SHOW_BUF_LEN];
+ char sname[64];
+ const char *name;
+ bool is_union;
+ s32 type_id;
+ int ret;
+
+ if (!btf_vmlinux || !ptr_val)
+ return;
+
+ /* Only handle kernel pointers */
+ if (ptr_val < PAGE_OFFSET)
+ return;
+
+ name = extract_struct_name(type_str, &is_union, sname, sizeof(sname));
+ if (!name)
+ return;
+
+ type_id = btf_find_by_name_kind(btf_vmlinux, name,
+ is_union ? BTF_KIND_UNION
+ : BTF_KIND_STRUCT);
+ if (type_id < 0)
+ return;
+
+ /*
+ * Render without BTF_SHOW_COMPACT so each member gets its own
+ * line with proper indentation from BTF. Use BTF_SHOW_PTR_RAW
+ * to print real kernel addresses instead of hashed pointers —
+ * this is oops context where address visibility is critical.
+ */
+ ret = btf_type_snprintf_show(btf_vmlinux, type_id, (void *)ptr_val,
+ buf, sizeof(buf), BTF_SHOW_PTR_RAW);
+ if (ret < 0)
+ return;
+
+ buf[sizeof(buf) - 1] = '\0';
+
+ /*
+ * Filter the multi-line BTF output: skip lines that contain
+ * only braces/brackets/whitespace (structural noise), collect
+ * meaningful member lines, and print them two per row.
+ */
+ {
+ /*
+ * Collect filtered lines as pointers into buf[] (which
+ * we NUL-terminate in place). Stack budget: ~64 pointers.
+ */
+#define MAX_BTF_LINES 64
+#define BTF_COL_WIDTH 40
+ char *lines[MAX_BTF_LINES];
+ int nlines = 0;
+ char *line, *next;
+
+ for (line = buf; line && *line; line = next) {
+ char *s, *c;
+ bool has_content = false;
+
+ next = strchr(line, '\n');
+ if (next)
+ *next++ = '\0';
+
+ s = line;
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ /* Skip structural-only lines: {}[](), */
+ for (c = s; *c; c++) {
+ if (*c != '{' && *c != '}' &&
+ *c != '(' && *c != ')' &&
+ *c != '[' && *c != ']' &&
+ *c != ',' && *c != ' ' &&
+ *c != '\t') {
+ has_content = true;
+ break;
+ }
+ }
+ if (!has_content)
+ continue;
+
+ /* Skip type-only prefix lines */
+ if (*s == '(' && !strchr(s, '=') && !strchr(s, '['))
+ continue;
+
+ /* Trim trailing commas/spaces */
+ {
+ size_t len = strlen(s);
+
+ while (len > 0 && (s[len - 1] == ','
+ || s[len - 1] == ' '))
+ s[--len] = '\0';
+ }
+
+ if (*s && nlines < MAX_BTF_LINES)
+ lines[nlines++] = s;
+ }
+
+ /*
+ * Coalesce char array elements into strings.
+ *
+ * BTF renders char[] as individual elements:
+ * .sysname = (char[])[
+ * 'L'
+ * 'i'
+ * 'n' ...
+ *
+ * Detect lines containing "= (char[])[" or
+ * "= (unsigned char[])[" and collect following
+ * single-quoted-char lines into a readable string
+ * like: .sysname = "Linux"
+ */
+#define MAX_COALESCED 8
+ {
+ static char coalesced[MAX_COALESCED][128];
+ int ci = 0, i;
+
+ for (i = 0; i < nlines && ci < MAX_COALESCED; i++) {
+ char *eq;
+ int spos, j, pfxlen;
+
+ eq = strstr(lines[i], "(char[])[");
+ if (!eq)
+ eq = strstr(lines[i], "(unsigned char[])[");
+ if (!eq)
+ continue;
+
+ /* Extract prefix up to and including '=' */
+ eq = strstr(lines[i], "= ");
+ if (!eq)
+ continue;
+ pfxlen = eq - lines[i] + 2;
+ if (pfxlen > 60)
+ pfxlen = 60;
+
+ memcpy(coalesced[ci], lines[i], pfxlen);
+ coalesced[ci][pfxlen] = '"';
+ spos = pfxlen + 1;
+
+ /* Gather chars from subsequent lines */
+ for (j = i + 1; j < nlines &&
+ spos < (int)sizeof(coalesced[0]) - 2; j++) {
+ char *s = lines[j];
+
+ if (s[0] == '\'' && s[2] == '\'' &&
+ (s[3] == '\0' || s[3] == ',')) {
+ coalesced[ci][spos++] = s[1];
+ lines[j] = "";
+ } else {
+ break;
+ }
+ }
+ coalesced[ci][spos++] = '"';
+ coalesced[ci][spos] = '\0';
+ lines[i] = coalesced[ci];
+ ci++;
+ }
+ }
+#undef MAX_COALESCED
+
+ /* Print in two columns, skipping empty (consumed) lines */
+ {
+ int i, col = 0;
+ char *pending = NULL;
+
+ for (i = 0; i < nlines; i++) {
+ if (!lines[i][0])
+ continue;
+ if (col == 0) {
+ pending = lines[i];
+ col = 1;
+ } else {
+ printk(KERN_DEFAULT " %-*s %s\n",
+ BTF_COL_WIDTH, pending,
+ lines[i]);
+ col = 0;
+ }
+ }
+ if (col == 1)
+ printk(KERN_DEFAULT " %s\n", pending);
+ }
+#undef MAX_BTF_LINES
+#undef BTF_COL_WIDTH
+ }
+}
diff --git a/lib/tests/paraminfo_kunit.c b/lib/tests/paraminfo_kunit.c
index e09efc4ddeb0e..74a4436163a98 100644
--- a/lib/tests/paraminfo_kunit.c
+++ b/lib/tests/paraminfo_kunit.c
@@ -7,7 +7,8 @@
* Verifies that the paraminfo tables correctly map function addresses
* to their parameter names and types.
*
- * Build with: CONFIG_PARAMINFO_KUNIT_TEST=m (or =y)
+ * Build with: CONFIG_PARAMINFO_KUNIT_TEST=y (must be built-in; paraminfo
+ * tables are vmlinux-only, so module test functions won't be found)
*/
#include <kunit/test.h>
@@ -45,15 +46,7 @@ static noinline void paraminfo_test_no_args(void)
/* ---- Helpers to query paraminfo tables directly ---- */
-/*
- * These access the raw paraminfo tables to verify correctness.
- * The tables are defined in kernel/kallsyms_internal.h.
- */
-extern const u32 paraminfo_num_funcs;
-extern const u32 paraminfo_func_addrs[];
-extern const u32 paraminfo_func_offsets[];
-extern const u8 paraminfo_func_data[];
-extern const char paraminfo_strings[];
+#include "../../kernel/kallsyms_internal.h"
struct param_result {
unsigned int num_params;
diff --git a/scripts/gen_paraminfo.c b/scripts/gen_paraminfo.c
index ea1d23f3ddd9a..b64dd1232c77c 100644
--- a/scripts/gen_paraminfo.c
+++ b/scripts/gen_paraminfo.c
@@ -58,7 +58,7 @@ static unsigned int num_strings;
static unsigned int strtab_capacity;
static unsigned int strtab_total_size;
-#define STR_HASH_BITS 14
+#define STR_HASH_BITS 18
#define STR_HASH_SIZE (1 << STR_HASH_BITS)
struct str_hash_entry {
@@ -87,6 +87,13 @@ static unsigned int find_or_add_string(const char *s)
h = (h + 1) & (STR_HASH_SIZE - 1);
}
+ if (num_strings >= STR_HASH_SIZE * 3 / 4) {
+ fprintf(stderr,
+ "gen_paraminfo: string hash table overflow (%u entries)\n",
+ num_strings);
+ exit(1);
+ }
+
if (num_strings >= strtab_capacity) {
strtab_capacity = strtab_capacity ? strtab_capacity * 2 : 8192;
strtab = realloc(strtab, strtab_capacity * sizeof(*strtab));
@@ -97,6 +104,10 @@ static unsigned int find_or_add_string(const char *s)
}
strtab[num_strings].str = strdup(s);
+ if (!strtab[num_strings].str) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
strtab[num_strings].offset = strtab_total_size;
strtab_total_size += strlen(s) + 1;
@@ -120,20 +131,32 @@ static void add_func(struct func_entry *f)
funcs[num_funcs++] = *f;
}
+/* Max recursion depth to prevent stack overflow on pathological DWARF */
+#define MAX_TYPE_DEPTH 16
+
+static void __build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz,
+ int depth);
+
/*
* Build a human-readable type name string from a DWARF type DIE.
* Follows the type chain (pointers, const, etc.) to produce strings like:
* "struct file *", "const char *", "unsigned long", "void *"
*/
static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
+{
+ __build_type_name(type_die, buf, bufsz, 0);
+}
+
+static void __build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz,
+ int depth)
{
Dwarf_Die child;
Dwarf_Attribute attr;
const char *name;
int tag;
- if (!type_die) {
- snprintf(buf, bufsz, "void");
+ if (!type_die || depth > MAX_TYPE_DEPTH) {
+ snprintf(buf, bufsz, depth > MAX_TYPE_DEPTH ? "..." : "void");
return;
}
@@ -148,7 +171,7 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
case DW_TAG_pointer_type:
if (dwarf_attr(type_die, DW_AT_type, &attr) &&
dwarf_formref_die(&attr, &child)) {
- build_type_name(&child, buf, bufsz);
+ __build_type_name(&child, buf, bufsz, depth + 1);
if (strlen(buf) + 3 < bufsz)
strcat(buf, " *");
} else {
@@ -161,7 +184,7 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
dwarf_formref_die(&attr, &child)) {
char tmp[MAX_TYPE_LEN - 10];
- build_type_name(&child, tmp, sizeof(tmp));
+ __build_type_name(&child, tmp, sizeof(tmp), depth + 1);
snprintf(buf, bufsz, "const %s", tmp);
} else {
snprintf(buf, bufsz, "const void");
@@ -173,7 +196,7 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
dwarf_formref_die(&attr, &child)) {
char tmp[MAX_TYPE_LEN - 10];
- build_type_name(&child, tmp, sizeof(tmp));
+ __build_type_name(&child, tmp, sizeof(tmp), depth + 1);
snprintf(buf, bufsz, "volatile %s", tmp);
} else {
snprintf(buf, bufsz, "volatile void");
@@ -183,7 +206,7 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
case DW_TAG_restrict_type:
if (dwarf_attr(type_die, DW_AT_type, &attr) &&
dwarf_formref_die(&attr, &child)) {
- build_type_name(&child, buf, bufsz);
+ __build_type_name(&child, buf, bufsz, depth + 1);
} else {
snprintf(buf, bufsz, "void");
}
@@ -195,7 +218,7 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
snprintf(buf, bufsz, "%s", name);
} else if (dwarf_attr(type_die, DW_AT_type, &attr) &&
dwarf_formref_die(&attr, &child)) {
- build_type_name(&child, buf, bufsz);
+ __build_type_name(&child, buf, bufsz, depth + 1);
} else {
snprintf(buf, bufsz, "?");
}
@@ -219,7 +242,7 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
case DW_TAG_array_type:
if (dwarf_attr(type_die, DW_AT_type, &attr) &&
dwarf_formref_die(&attr, &child)) {
- build_type_name(&child, buf, bufsz);
+ __build_type_name(&child, buf, bufsz, depth + 1);
if (strlen(buf) + 3 < bufsz)
strcat(buf, "[]");
} else {
@@ -231,8 +254,23 @@ static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
snprintf(buf, bufsz, "func_ptr");
break;
+ case DW_TAG_unspecified_type:
+ name = dwarf_diename(type_die);
+ snprintf(buf, bufsz, "%s", name ? name : "void");
+ break;
+
default:
- snprintf(buf, bufsz, "?");
+ /*
+ * Unknown tag — try to follow DW_AT_type if present
+ * (handles DW_TAG_atomic_type and others).
+ */
+ if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ __build_type_name(&child, buf, bufsz, depth + 1);
+ } else {
+ name = dwarf_diename(type_die);
+ snprintf(buf, bufsz, "%s", name ? name : "?");
+ }
break;
}
}
@@ -311,10 +349,15 @@ static void process_dwarf(Dwarf *dwarf, unsigned long long text_addr)
continue;
/* Skip declarations (no body) */
- if (dwarf_attr(&child, DW_AT_declaration, &attr))
+ if (dwarf_attr_integrate(&child, DW_AT_declaration, &attr))
continue;
- /* Get function start address */
+ /*
+ * Get function start address.
+ * dwarf_lowpc handles DW_AT_low_pc directly, but
+ * for concrete inlined instances the address may be
+ * in a ranges table.
+ */
if (dwarf_lowpc(&child, &low_pc) != 0)
continue;
@@ -341,6 +384,12 @@ static void process_dwarf(Dwarf *dwarf, unsigned long long text_addr)
if (func.num_params >= MAX_PARAMS)
break;
+ /*
+ * Use dwarf_attr_integrate to follow
+ * DW_AT_abstract_origin chains — inlined
+ * or outlined functions may store param
+ * names/types in an abstract instance.
+ */
pname = dwarf_diename(¶m);
if (!pname)
pname = "?";
@@ -349,8 +398,8 @@ static void process_dwarf(Dwarf *dwarf, unsigned long long text_addr)
sizeof(func.params[0].name),
"%s", pname);
- /* Resolve type */
- if (dwarf_attr(¶m, DW_AT_type, &attr) &&
+ /* Resolve type (follow abstract origin) */
+ if (dwarf_attr_integrate(¶m, DW_AT_type, &attr) &&
dwarf_formref_die(&attr, &type_die)) {
build_type_name(&type_die,
func.params[func.num_params].type,
@@ -530,8 +579,7 @@ int main(int argc, char *argv[])
process_dwarf(dwarf, text_addr);
deduplicate();
- fprintf(stderr, "paraminfo: %u functions, %u strings\n",
- num_funcs, num_strings);
+ fprintf(stderr, "paraminfo: %u functions\n", num_funcs);
output_assembly();
--
2.51.0
^ permalink raw reply related
* [PATCH 1/2] kallsyms: show function parameter info in oops/WARN dumps
From: Sasha Levin @ 2026-03-23 16:48 UTC (permalink / raw)
To: Andrew Morton, Masahiro Yamada, Nathan Chancellor, Nicolas Schier
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Peter Zijlstra, Josh Poimboeuf, Petr Mladek,
Alexei Starovoitov, Jonathan Corbet, David Gow, Kees Cook,
Greg KH, Luis Chamberlain, Steven Rostedt, Helge Deller,
Randy Dunlap, Geert Uytterhoeven, Juergen Gross, James Bottomley,
Alexey Dobriyan, Vlastimil Babka, Laurent Pinchart, Petr Pavlu,
x86, linux-kernel, linux-kbuild, linux-doc, linux-modules, bpf,
Sasha Levin
In-Reply-To: <20260323164858.1939248-1-sashal@kernel.org>
Embed DWARF-derived function parameter name and type information in the
kernel image so that oops and WARN dumps display the crashing function's
register-passed arguments with their names, types, and values.
A new build-time tool (scripts/gen_paraminfo.c) parses DW_TAG_subprogram
and DW_TAG_formal_parameter entries from DWARF .debug_info, extracting
parameter names and human-readable type strings. The resulting tables are
stored in .rodata using the same two-phase link approach as lineinfo.
At runtime, kallsyms_show_paraminfo() performs a binary search on the
paraminfo tables, maps parameters to x86-64 calling convention registers
(RDI, RSI, RDX, RCX, R8, R9), and prints each parameter's name, type,
and value from pt_regs. If a parameter value matches the page fault
address (CR2), it is highlighted with "<-- fault address".
Integration at show_regs() means this works for both oops and WARN()
automatically, since both paths provide full pt_regs at the exception
point.
Example output:
Function parameters (ext4_readdir):
file (struct file *) = 0xffff888123456000
ctx (struct dir_context *) = 0x0000000000001234 <-- fault address
Gated behind CONFIG_KALLSYMS_PARAMINFO (depends on CONFIG_KALLSYMS_LINEINFO).
Adds approximately 1-2 MB to the kernel image for ~58K functions.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../admin-guide/kallsyms-lineinfo.rst | 31 +
arch/x86/kernel/dumpstack.c | 6 +-
include/linux/kallsyms.h | 9 +
init/Kconfig | 21 +
kernel/kallsyms.c | 168 ++++++
kernel/kallsyms_internal.h | 6 +
lib/Kconfig.debug | 11 +
lib/tests/Makefile | 3 +
lib/tests/paraminfo_kunit.c | 256 ++++++++
scripts/Makefile | 3 +
scripts/empty_paraminfo.S | 18 +
scripts/gen_paraminfo.c | 549 ++++++++++++++++++
scripts/link-vmlinux.sh | 44 +-
13 files changed, 1119 insertions(+), 6 deletions(-)
create mode 100644 lib/tests/paraminfo_kunit.c
create mode 100644 scripts/empty_paraminfo.S
create mode 100644 scripts/gen_paraminfo.c
diff --git a/Documentation/admin-guide/kallsyms-lineinfo.rst b/Documentation/admin-guide/kallsyms-lineinfo.rst
index dd264830c8d5b..26921bb3f7f81 100644
--- a/Documentation/admin-guide/kallsyms-lineinfo.rst
+++ b/Documentation/admin-guide/kallsyms-lineinfo.rst
@@ -83,6 +83,37 @@ compression).
Per-module lineinfo adds approximately 2-3 bytes per DWARF line entry to each
``.ko`` file.
+Function Parameter Info
+======================
+
+``CONFIG_KALLSYMS_PARAMINFO`` extends the debugging information by embedding
+function parameter names and types in the kernel image. When an oops or WARN
+occurs, the faulting function's register-passed arguments are displayed with
+their names, types, and values from the saved registers.
+
+Enable in addition to the lineinfo options::
+
+ CONFIG_KALLSYMS_PARAMINFO=y
+
+Example oops output with paraminfo::
+
+ RIP: 0010:ext4_readdir+0x1a3/0x5b0 (fs/ext4/dir.c:421)
+ ...
+ Function parameters (ext4_readdir):
+ file (struct file *) = 0xffff888123456000
+ ctx (struct dir_context *) = 0x0000000000001234 <-- fault address
+
+The ``<-- fault address`` annotation appears when a parameter value matches
+the page fault address (CR2 on x86), helping quickly identify which argument
+caused the crash.
+
+This feature works for both oops and WARN() on x86-64. Only register-passed
+parameters (up to 6 on x86-64: RDI, RSI, RDX, RCX, R8, R9) are displayed.
+The parameter info is only shown for the faulting/warning frame where full
+register state is available.
+
+The paraminfo tables add approximately 1-2 MiB to the kernel image.
+
Known Limitations
=================
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b10684dedc589..4e9b5fd58fd1b 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -483,8 +483,10 @@ void show_regs(struct pt_regs *regs)
__show_regs(regs, print_kernel_regs, KERN_DEFAULT);
/*
- * When in-kernel, we also print out the stack at the time of the fault..
+ * When in-kernel, show function parameter info and stack trace.
*/
- if (!user_mode(regs))
+ if (!user_mode(regs)) {
+ kallsyms_show_paraminfo(regs);
show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
+ }
}
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 7d4c9dca06c87..17c9df520b2b0 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -104,6 +104,13 @@ int lookup_symbol_name(unsigned long addr, char *symname);
bool kallsyms_lookup_lineinfo(unsigned long addr,
const char **file, unsigned int *line);
+#ifdef CONFIG_KALLSYMS_PARAMINFO
+struct pt_regs;
+void kallsyms_show_paraminfo(struct pt_regs *regs);
+#else
+static inline void kallsyms_show_paraminfo(struct pt_regs *regs) {}
+#endif
+
#else /* !CONFIG_KALLSYMS */
static inline unsigned long kallsyms_lookup_name(const char *name)
@@ -179,6 +186,8 @@ static inline bool kallsyms_lookup_lineinfo(unsigned long addr,
{
return false;
}
+
+static inline void kallsyms_show_paraminfo(struct pt_regs *regs) {}
#endif /*CONFIG_KALLSYMS*/
static inline void print_ip_sym(const char *loglvl, unsigned long ip)
diff --git a/init/Kconfig b/init/Kconfig
index 6e3795b3dbd62..76d0c2da7d612 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2085,6 +2085,27 @@ config KALLSYMS_LINEINFO_MODULES
If unsure, say N.
+config KALLSYMS_PARAMINFO
+ bool "Show function parameter info in oops/WARN dumps"
+ depends on KALLSYMS_LINEINFO
+ help
+ Embeds function parameter name and type information in the kernel
+ image, extracted from DWARF debug info at build time. When an
+ oops or WARN occurs, the crashing/warning function's register-
+ passed arguments are displayed with their names, types, and
+ values from pt_regs.
+
+ When enabled, oops/WARN dumps include lines like:
+
+ Function parameters (ext4_readdir):
+ file (struct file *) = 0xffff888123456000
+ ctx (struct dir_context *) = 0x0000000000001234
+
+ Requires elfutils (libdw-dev/elfutils-devel) on the build host.
+ Adds approximately 1-2 MB to the kernel image.
+
+ If unsure, say N.
+
# end of the "standard kernel features (expert users)" menu
config ARCH_HAS_MEMBARRIER_CALLBACKS
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index e6f796d43dd70..af8de3d8e3ba3 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -501,6 +501,174 @@ bool kallsyms_lookup_lineinfo(unsigned long addr,
return lineinfo_search(&tbl, (unsigned int)raw_offset, file, line);
}
+#ifdef CONFIG_KALLSYMS_PARAMINFO
+
+#include <linux/ptrace.h>
+#ifdef CONFIG_X86
+#include <asm/special_insns.h>
+#endif
+
+#define MAX_PARAMINFO_PARAMS 6
+
+/*
+ * x86-64 calling convention: arguments are passed in registers
+ * RDI, RSI, RDX, RCX, R8, R9 (in that order).
+ */
+#ifdef CONFIG_X86_64
+
+static const char * const paraminfo_reg_names[] = {
+ "RDI", "RSI", "RDX", "RCX", "R8", "R9"
+};
+
+static unsigned long paraminfo_get_reg(const struct pt_regs *regs,
+ unsigned int idx)
+{
+ switch (idx) {
+ case 0: return regs->di;
+ case 1: return regs->si;
+ case 2: return regs->dx;
+ case 3: return regs->cx;
+ case 4: return regs->r8;
+ case 5: return regs->r9;
+ default: return 0;
+ }
+}
+#else
+/* Stub for non-x86-64 architectures */
+static const char * const paraminfo_reg_names[] = {};
+
+static unsigned long paraminfo_get_reg(const struct pt_regs *regs,
+ unsigned int idx)
+{
+ return 0;
+}
+#endif /* CONFIG_X86_64 */
+
+/*
+ * Binary search for the function containing the given offset in
+ * paraminfo_func_addrs[]. Returns the index of the function whose
+ * start address is <= offset, or -1 if not found.
+ */
+static int paraminfo_find_func(unsigned int offset)
+{
+ int lo = 0, hi = paraminfo_num_funcs - 1;
+ int result = -1;
+
+ if (!paraminfo_num_funcs)
+ return -1;
+
+ while (lo <= hi) {
+ int mid = lo + (hi - lo) / 2;
+
+ if (paraminfo_func_addrs[mid] <= offset) {
+ result = mid;
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Show function parameter info for the faulting/warning instruction.
+ *
+ * Called from show_regs() on x86 when CONFIG_KALLSYMS_PARAMINFO is
+ * enabled. Works for both oops (page fault, GPF, etc.) and WARN(),
+ * since both paths provide full pt_regs at the exception point.
+ */
+void kallsyms_show_paraminfo(struct pt_regs *regs)
+{
+ unsigned long long raw_offset;
+ unsigned int offset;
+ int func_idx;
+ const u8 *data;
+ unsigned int num_params, i;
+ unsigned long ip, fault_addr;
+ char sym_name[KSYM_NAME_LEN];
+ unsigned long sym_size, sym_offset;
+
+ if (!regs || !paraminfo_num_funcs)
+ return;
+
+ ip = regs->ip;
+
+ /* Only handle kernel-mode faults */
+ if (user_mode(regs))
+ return;
+
+ if (ip < (unsigned long)_text)
+ return;
+
+ raw_offset = ip - (unsigned long)_text;
+ if (raw_offset > UINT_MAX)
+ return;
+ offset = (unsigned int)raw_offset;
+
+ func_idx = paraminfo_find_func(offset);
+ if (func_idx < 0)
+ return;
+
+ /*
+ * Verify the IP is within a reasonable range of the function
+ * start. paraminfo_func_addrs[] contains function start offsets;
+ * check that we're not too far past the start. Use kallsyms to
+ * verify we're in the right function.
+ */
+ if (!kallsyms_lookup_size_offset(ip, &sym_size, &sym_offset))
+ return;
+
+ /* Decode the function's parameter data */
+ data = paraminfo_func_data + paraminfo_func_offsets[func_idx];
+ num_params = *data++;
+
+ if (num_params == 0 || num_params > MAX_PARAMINFO_PARAMS)
+ return;
+
+ /* Look up function name for the header */
+ if (lookup_symbol_name(ip - sym_offset, sym_name))
+ return;
+
+ /*
+ * Read the fault address for highlighting. On x86, CR2 holds
+ * the page fault linear address. On other architectures this
+ * would need a different mechanism.
+ */
+#ifdef CONFIG_X86
+ fault_addr = read_cr2();
+#else
+ fault_addr = 0;
+#endif
+
+ printk(KERN_DEFAULT "Function parameters (%s):\n", sym_name);
+
+ for (i = 0; i < num_params; i++) {
+ u32 name_off, type_off;
+ const char *pname, *ptype;
+ unsigned long val;
+ bool is_fault_addr;
+
+ memcpy(&name_off, data, sizeof(u32));
+ data += sizeof(u32);
+ memcpy(&type_off, data, sizeof(u32));
+ data += sizeof(u32);
+
+ pname = paraminfo_strings + name_off;
+ ptype = paraminfo_strings + type_off;
+ val = paraminfo_get_reg(regs, i);
+
+ is_fault_addr = fault_addr && (val == fault_addr);
+
+ printk(KERN_DEFAULT " %-8s (%-20s) = 0x%016lx%s\n",
+ pname, ptype, val,
+ is_fault_addr ? " <-- fault address" : "");
+ }
+}
+EXPORT_SYMBOL_GPL(kallsyms_show_paraminfo);
+
+#endif /* CONFIG_KALLSYMS_PARAMINFO */
+
/* Look up a kernel symbol and return it in a text buffer. */
static int __sprint_symbol(char *buffer, unsigned long address,
int symbol_offset, int add_offset, int add_buildid)
diff --git a/kernel/kallsyms_internal.h b/kernel/kallsyms_internal.h
index ffe4c658067ec..7287ee0859515 100644
--- a/kernel/kallsyms_internal.h
+++ b/kernel/kallsyms_internal.h
@@ -26,4 +26,10 @@ extern const u32 lineinfo_file_offsets[];
extern const u32 lineinfo_filenames_size;
extern const char lineinfo_filenames[];
+extern const u32 paraminfo_num_funcs;
+extern const u32 paraminfo_func_addrs[];
+extern const u32 paraminfo_func_offsets[];
+extern const u8 paraminfo_func_data[];
+extern const char paraminfo_strings[];
+
#endif // LINUX_KALLSYMS_INTERNAL_H_
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 688bbcb3eaa62..be8cee0985fbd 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3058,6 +3058,17 @@ config LINEINFO_KUNIT_TEST
If unsure, say N.
+config PARAMINFO_KUNIT_TEST
+ tristate "KUnit tests for kallsyms paraminfo" if !KUNIT_ALL_TESTS
+ depends on KUNIT && KALLSYMS_PARAMINFO
+ default KUNIT_ALL_TESTS
+ help
+ KUnit tests for the kallsyms function parameter info feature.
+ Verifies that paraminfo tables correctly map functions to their
+ parameter names and types.
+
+ If unsure, say N.
+
config HW_BREAKPOINT_KUNIT_TEST
bool "Test hw_breakpoint constraints accounting" if !KUNIT_ALL_TESTS
depends on HAVE_HW_BREAKPOINT
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index c6add3b04bbd5..70452942baf45 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -39,6 +39,9 @@ obj-$(CONFIG_LONGEST_SYM_KUNIT_TEST) += longest_symbol_kunit.o
CFLAGS_lineinfo_kunit.o += $(call cc-option,-fno-inline-functions-called-once)
obj-$(CONFIG_LINEINFO_KUNIT_TEST) += lineinfo_kunit.o
+CFLAGS_paraminfo_kunit.o += $(call cc-option,-fno-inline-functions-called-once)
+obj-$(CONFIG_PARAMINFO_KUNIT_TEST) += paraminfo_kunit.o
+
obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_kunit.o
CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
diff --git a/lib/tests/paraminfo_kunit.c b/lib/tests/paraminfo_kunit.c
new file mode 100644
index 0000000000000..e09efc4ddeb0e
--- /dev/null
+++ b/lib/tests/paraminfo_kunit.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit tests for kallsyms paraminfo (CONFIG_KALLSYMS_PARAMINFO).
+ *
+ * Copyright (c) 2026 Sasha Levin <sashal@kernel.org>
+ *
+ * Verifies that the paraminfo tables correctly map function addresses
+ * to their parameter names and types.
+ *
+ * Build with: CONFIG_PARAMINFO_KUNIT_TEST=m (or =y)
+ */
+
+#include <kunit/test.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* ---- Test target functions with known signatures ---- */
+
+static noinline int paraminfo_test_two_args(struct kunit *test, int value)
+{
+ /* Prevent optimization */
+ return test ? value + 1 : 0;
+}
+
+static noinline void *paraminfo_test_ptr_arg(void *ptr, unsigned long size)
+{
+ if (ptr && size > 0)
+ return ptr;
+ return NULL;
+}
+
+static noinline long paraminfo_test_many_args(int a, int b, int c,
+ int d, int e, int f)
+{
+ return (long)a + b + c + d + e + f;
+}
+
+static noinline void paraminfo_test_no_args(void)
+{
+ /* Function with no parameters */
+ barrier();
+}
+
+/* ---- Helpers to query paraminfo tables directly ---- */
+
+/*
+ * These access the raw paraminfo tables to verify correctness.
+ * The tables are defined in kernel/kallsyms_internal.h.
+ */
+extern const u32 paraminfo_num_funcs;
+extern const u32 paraminfo_func_addrs[];
+extern const u32 paraminfo_func_offsets[];
+extern const u8 paraminfo_func_data[];
+extern const char paraminfo_strings[];
+
+struct param_result {
+ unsigned int num_params;
+ const char *names[6];
+ const char *types[6];
+};
+
+/*
+ * Look up paraminfo for a given kernel address.
+ * Returns true if found, filling in @result.
+ */
+static bool lookup_paraminfo(unsigned long addr, struct param_result *result)
+{
+ unsigned long long raw_offset;
+ unsigned int offset;
+ int lo, hi, func_idx;
+ const u8 *data;
+ unsigned int i;
+
+ if (!paraminfo_num_funcs)
+ return false;
+
+ if (addr < (unsigned long)_text)
+ return false;
+
+ raw_offset = addr - (unsigned long)_text;
+ if (raw_offset > UINT_MAX)
+ return false;
+ offset = (unsigned int)raw_offset;
+
+ /* Binary search for the function */
+ lo = 0;
+ hi = paraminfo_num_funcs - 1;
+ func_idx = -1;
+ while (lo <= hi) {
+ int mid = lo + (hi - lo) / 2;
+
+ if (paraminfo_func_addrs[mid] <= offset) {
+ func_idx = mid;
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ if (func_idx < 0)
+ return false;
+
+ /* Verify we're not too far from the function start */
+ if (offset - paraminfo_func_addrs[func_idx] > 0x10000)
+ return false;
+
+ data = paraminfo_func_data + paraminfo_func_offsets[func_idx];
+ result->num_params = *data++;
+
+ if (result->num_params > 6)
+ return false;
+
+ for (i = 0; i < result->num_params; i++) {
+ u32 name_off, type_off;
+
+ memcpy(&name_off, data, sizeof(u32));
+ data += sizeof(u32);
+ memcpy(&type_off, data, sizeof(u32));
+ data += sizeof(u32);
+
+ result->names[i] = paraminfo_strings + name_off;
+ result->types[i] = paraminfo_strings + type_off;
+ }
+
+ return true;
+}
+
+/* ---- Test cases ---- */
+
+static void test_paraminfo_two_args(struct kunit *test)
+{
+ struct param_result res;
+ bool found;
+
+ found = lookup_paraminfo((unsigned long)paraminfo_test_two_args, &res);
+
+ if (!IS_ENABLED(CONFIG_KALLSYMS_PARAMINFO)) {
+ KUNIT_EXPECT_FALSE(test, found);
+ return;
+ }
+
+ KUNIT_ASSERT_TRUE(test, found);
+ KUNIT_EXPECT_EQ(test, res.num_params, 2U);
+ KUNIT_EXPECT_STREQ(test, res.names[0], "test");
+ KUNIT_EXPECT_STREQ(test, res.names[1], "value");
+ KUNIT_EXPECT_TRUE(test, strstr(res.types[1], "int") != NULL);
+}
+
+static void test_paraminfo_ptr_arg(struct kunit *test)
+{
+ struct param_result res;
+ bool found;
+
+ found = lookup_paraminfo((unsigned long)paraminfo_test_ptr_arg, &res);
+
+ if (!IS_ENABLED(CONFIG_KALLSYMS_PARAMINFO)) {
+ KUNIT_EXPECT_FALSE(test, found);
+ return;
+ }
+
+ KUNIT_ASSERT_TRUE(test, found);
+ KUNIT_EXPECT_EQ(test, res.num_params, 2U);
+ KUNIT_EXPECT_STREQ(test, res.names[0], "ptr");
+ KUNIT_EXPECT_STREQ(test, res.names[1], "size");
+ /* First param should be a pointer type */
+ KUNIT_EXPECT_TRUE(test, strstr(res.types[0], "*") != NULL);
+}
+
+static void test_paraminfo_many_args(struct kunit *test)
+{
+ struct param_result res;
+ bool found;
+
+ found = lookup_paraminfo((unsigned long)paraminfo_test_many_args, &res);
+
+ if (!IS_ENABLED(CONFIG_KALLSYMS_PARAMINFO)) {
+ KUNIT_EXPECT_FALSE(test, found);
+ return;
+ }
+
+ KUNIT_ASSERT_TRUE(test, found);
+ KUNIT_EXPECT_EQ(test, res.num_params, 6U);
+ KUNIT_EXPECT_STREQ(test, res.names[0], "a");
+ KUNIT_EXPECT_STREQ(test, res.names[1], "b");
+ KUNIT_EXPECT_STREQ(test, res.names[2], "c");
+ KUNIT_EXPECT_STREQ(test, res.names[3], "d");
+ KUNIT_EXPECT_STREQ(test, res.names[4], "e");
+ KUNIT_EXPECT_STREQ(test, res.names[5], "f");
+}
+
+static void test_paraminfo_no_args(struct kunit *test)
+{
+ struct param_result res;
+ bool found;
+
+ /*
+ * Functions with no parameters should not have entries in the
+ * paraminfo table (they are filtered out at build time).
+ * The lookup may find a nearby function instead, but if it
+ * does find our function exactly, num_params should be 0.
+ */
+ found = lookup_paraminfo((unsigned long)paraminfo_test_no_args, &res);
+
+ if (found) {
+ /* If it matched our exact function, it should have 0 params.
+ * But it may have matched a preceding function instead.
+ */
+ kunit_info(test, "lookup found func with %u params\n",
+ res.num_params);
+ }
+}
+
+static void test_paraminfo_bogus_addr(struct kunit *test)
+{
+ struct param_result res;
+
+ /* Address 0 should not match anything */
+ KUNIT_EXPECT_FALSE(test, lookup_paraminfo(0, &res));
+
+ /* Address in userspace should not match */
+ KUNIT_EXPECT_FALSE(test, lookup_paraminfo(0x1000, &res));
+}
+
+static void test_paraminfo_tables_present(struct kunit *test)
+{
+ if (!IS_ENABLED(CONFIG_KALLSYMS_PARAMINFO)) {
+ kunit_skip(test, "CONFIG_KALLSYMS_PARAMINFO not enabled");
+ return;
+ }
+
+ KUNIT_EXPECT_GT(test, paraminfo_num_funcs, 0U);
+ kunit_info(test, "paraminfo: %u functions in table\n",
+ paraminfo_num_funcs);
+}
+
+static struct kunit_case paraminfo_test_cases[] = {
+ KUNIT_CASE(test_paraminfo_tables_present),
+ KUNIT_CASE(test_paraminfo_two_args),
+ KUNIT_CASE(test_paraminfo_ptr_arg),
+ KUNIT_CASE(test_paraminfo_many_args),
+ KUNIT_CASE(test_paraminfo_no_args),
+ KUNIT_CASE(test_paraminfo_bogus_addr),
+ {}
+};
+
+static struct kunit_suite paraminfo_test_suite = {
+ .name = "paraminfo",
+ .test_cases = paraminfo_test_cases,
+};
+
+kunit_test_suite(paraminfo_test_suite);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for kallsyms paraminfo");
diff --git a/scripts/Makefile b/scripts/Makefile
index ffe89875b3295..f681b94c6d9e7 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -5,6 +5,7 @@
hostprogs-always-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-always-$(CONFIG_KALLSYMS_LINEINFO) += gen_lineinfo
+hostprogs-always-$(CONFIG_KALLSYMS_PARAMINFO) += gen_paraminfo
hostprogs-always-$(BUILD_C_RECORDMCOUNT) += recordmcount
hostprogs-always-$(CONFIG_BUILDTIME_TABLE_SORT) += sorttable
hostprogs-always-$(CONFIG_ASN1) += asn1_compiler
@@ -39,6 +40,8 @@ HOSTCFLAGS_sign-file.o = $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/nu
HOSTLDLIBS_sign-file = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto)
HOSTCFLAGS_gen_lineinfo.o = $(shell $(HOSTPKG_CONFIG) --cflags libdw 2> /dev/null)
HOSTLDLIBS_gen_lineinfo = $(shell $(HOSTPKG_CONFIG) --libs libdw 2> /dev/null || echo -ldw -lelf -lz)
+HOSTCFLAGS_gen_paraminfo.o = $(shell $(HOSTPKG_CONFIG) --cflags libdw 2> /dev/null)
+HOSTLDLIBS_gen_paraminfo = $(shell $(HOSTPKG_CONFIG) --libs libdw 2> /dev/null || echo -ldw -lelf -lz)
ifdef CONFIG_UNWINDER_ORC
ifeq ($(ARCH),x86_64)
diff --git a/scripts/empty_paraminfo.S b/scripts/empty_paraminfo.S
new file mode 100644
index 0000000000000..a0e39dbfbd3cb
--- /dev/null
+++ b/scripts/empty_paraminfo.S
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Empty paraminfo stub for the initial vmlinux link.
+ * The real paraminfo is generated from .tmp_vmlinux1 by gen_paraminfo.
+ */
+ .section .rodata, "a"
+ .globl paraminfo_num_funcs
+ .balign 4
+paraminfo_num_funcs:
+ .long 0
+ .globl paraminfo_func_addrs
+paraminfo_func_addrs:
+ .globl paraminfo_func_offsets
+paraminfo_func_offsets:
+ .globl paraminfo_func_data
+paraminfo_func_data:
+ .globl paraminfo_strings
+paraminfo_strings:
diff --git a/scripts/gen_paraminfo.c b/scripts/gen_paraminfo.c
new file mode 100644
index 0000000000000..ea1d23f3ddd9a
--- /dev/null
+++ b/scripts/gen_paraminfo.c
@@ -0,0 +1,549 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * gen_paraminfo.c - Generate function parameter info tables from DWARF
+ *
+ * Copyright (C) 2026 Sasha Levin <sashal@kernel.org>
+ *
+ * Reads DWARF .debug_info from a vmlinux ELF file and outputs an assembly
+ * file containing function parameter name/type tables that the kernel uses
+ * to annotate oops/WARN dumps with typed parameter values.
+ *
+ * Requires libdw from elfutils.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elfutils/libdw.h>
+#include <dwarf.h>
+#include <elf.h>
+#include <gelf.h>
+#include <limits.h>
+
+/* Maximum register-passed parameters on x86-64 */
+#define MAX_PARAMS 6
+
+/* Maximum length for a type name string */
+#define MAX_TYPE_LEN 64
+
+struct param_info {
+ char name[64];
+ char type[MAX_TYPE_LEN];
+};
+
+struct func_entry {
+ unsigned int offset; /* offset from _text */
+ unsigned int num_params;
+ struct param_info params[MAX_PARAMS];
+};
+
+static struct func_entry *funcs;
+static unsigned int num_funcs;
+static unsigned int funcs_capacity;
+
+/*
+ * String table for parameter names and type names.
+ * Deduplicated via a hash table.
+ */
+struct str_entry {
+ char *str;
+ unsigned int offset; /* byte offset in concatenated output */
+};
+
+static struct str_entry *strtab;
+static unsigned int num_strings;
+static unsigned int strtab_capacity;
+static unsigned int strtab_total_size;
+
+#define STR_HASH_BITS 14
+#define STR_HASH_SIZE (1 << STR_HASH_BITS)
+
+struct str_hash_entry {
+ const char *str;
+ unsigned int idx; /* index into strtab[] */
+};
+
+static struct str_hash_entry str_hash[STR_HASH_SIZE];
+
+static unsigned int hash_str(const char *s)
+{
+ unsigned int h = 5381;
+
+ for (; *s; s++)
+ h = h * 33 + (unsigned char)*s;
+ return h & (STR_HASH_SIZE - 1);
+}
+
+static unsigned int find_or_add_string(const char *s)
+{
+ unsigned int h = hash_str(s);
+
+ while (str_hash[h].str) {
+ if (!strcmp(str_hash[h].str, s))
+ return str_hash[h].idx;
+ h = (h + 1) & (STR_HASH_SIZE - 1);
+ }
+
+ if (num_strings >= strtab_capacity) {
+ strtab_capacity = strtab_capacity ? strtab_capacity * 2 : 8192;
+ strtab = realloc(strtab, strtab_capacity * sizeof(*strtab));
+ if (!strtab) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ }
+
+ strtab[num_strings].str = strdup(s);
+ strtab[num_strings].offset = strtab_total_size;
+ strtab_total_size += strlen(s) + 1;
+
+ str_hash[h].str = strtab[num_strings].str;
+ str_hash[h].idx = num_strings;
+
+ num_strings++;
+ return num_strings - 1;
+}
+
+static void add_func(struct func_entry *f)
+{
+ if (num_funcs >= funcs_capacity) {
+ funcs_capacity = funcs_capacity ? funcs_capacity * 2 : 16384;
+ funcs = realloc(funcs, funcs_capacity * sizeof(*funcs));
+ if (!funcs) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ }
+ funcs[num_funcs++] = *f;
+}
+
+/*
+ * Build a human-readable type name string from a DWARF type DIE.
+ * Follows the type chain (pointers, const, etc.) to produce strings like:
+ * "struct file *", "const char *", "unsigned long", "void *"
+ */
+static void build_type_name(Dwarf_Die *type_die, char *buf, size_t bufsz)
+{
+ Dwarf_Die child;
+ Dwarf_Attribute attr;
+ const char *name;
+ int tag;
+
+ if (!type_die) {
+ snprintf(buf, bufsz, "void");
+ return;
+ }
+
+ tag = dwarf_tag(type_die);
+
+ switch (tag) {
+ case DW_TAG_base_type:
+ name = dwarf_diename(type_die);
+ snprintf(buf, bufsz, "%s", name ? name : "?");
+ break;
+
+ case DW_TAG_pointer_type:
+ if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ build_type_name(&child, buf, bufsz);
+ if (strlen(buf) + 3 < bufsz)
+ strcat(buf, " *");
+ } else {
+ snprintf(buf, bufsz, "void *");
+ }
+ break;
+
+ case DW_TAG_const_type:
+ if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ char tmp[MAX_TYPE_LEN - 10];
+
+ build_type_name(&child, tmp, sizeof(tmp));
+ snprintf(buf, bufsz, "const %s", tmp);
+ } else {
+ snprintf(buf, bufsz, "const void");
+ }
+ break;
+
+ case DW_TAG_volatile_type:
+ if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ char tmp[MAX_TYPE_LEN - 10];
+
+ build_type_name(&child, tmp, sizeof(tmp));
+ snprintf(buf, bufsz, "volatile %s", tmp);
+ } else {
+ snprintf(buf, bufsz, "volatile void");
+ }
+ break;
+
+ case DW_TAG_restrict_type:
+ if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ build_type_name(&child, buf, bufsz);
+ } else {
+ snprintf(buf, bufsz, "void");
+ }
+ break;
+
+ case DW_TAG_typedef:
+ name = dwarf_diename(type_die);
+ if (name) {
+ snprintf(buf, bufsz, "%s", name);
+ } else if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ build_type_name(&child, buf, bufsz);
+ } else {
+ snprintf(buf, bufsz, "?");
+ }
+ break;
+
+ case DW_TAG_structure_type:
+ name = dwarf_diename(type_die);
+ snprintf(buf, bufsz, "struct %s", name ? name : "(anon)");
+ break;
+
+ case DW_TAG_union_type:
+ name = dwarf_diename(type_die);
+ snprintf(buf, bufsz, "union %s", name ? name : "(anon)");
+ break;
+
+ case DW_TAG_enumeration_type:
+ name = dwarf_diename(type_die);
+ snprintf(buf, bufsz, "enum %s", name ? name : "(anon)");
+ break;
+
+ case DW_TAG_array_type:
+ if (dwarf_attr(type_die, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &child)) {
+ build_type_name(&child, buf, bufsz);
+ if (strlen(buf) + 3 < bufsz)
+ strcat(buf, "[]");
+ } else {
+ snprintf(buf, bufsz, "?[]");
+ }
+ break;
+
+ case DW_TAG_subroutine_type:
+ snprintf(buf, bufsz, "func_ptr");
+ break;
+
+ default:
+ snprintf(buf, bufsz, "?");
+ break;
+ }
+}
+
+static unsigned long long find_text_addr(Elf *elf)
+{
+ size_t nsyms, i;
+ Elf_Scn *scn = NULL;
+ GElf_Shdr shdr;
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ Elf_Data *data;
+
+ if (!gelf_getshdr(scn, &shdr))
+ continue;
+ if (shdr.sh_type != SHT_SYMTAB)
+ continue;
+
+ data = elf_getdata(scn, NULL);
+ if (!data)
+ continue;
+
+ nsyms = shdr.sh_size / shdr.sh_entsize;
+ for (i = 0; i < nsyms; i++) {
+ GElf_Sym sym;
+ const char *name;
+
+ if (!gelf_getsym(data, i, &sym))
+ continue;
+ name = elf_strptr(elf, shdr.sh_link, sym.st_name);
+ if (name && !strcmp(name, "_text"))
+ return sym.st_value;
+ }
+ }
+
+ fprintf(stderr, "Cannot find _text symbol\n");
+ exit(1);
+}
+
+static int compare_funcs(const void *a, const void *b)
+{
+ const struct func_entry *fa = a;
+ const struct func_entry *fb = b;
+
+ if (fa->offset < fb->offset)
+ return -1;
+ if (fa->offset > fb->offset)
+ return 1;
+ return 0;
+}
+
+static void process_dwarf(Dwarf *dwarf, unsigned long long text_addr)
+{
+ Dwarf_Off off = 0, next_off;
+ size_t hdr_size;
+
+ while (dwarf_nextcu(dwarf, off, &next_off, &hdr_size,
+ NULL, NULL, NULL) == 0) {
+ Dwarf_Die cudie, child;
+
+ if (!dwarf_offdie(dwarf, off + hdr_size, &cudie))
+ goto next;
+
+ if (dwarf_child(&cudie, &child) != 0)
+ goto next;
+
+ do {
+ Dwarf_Die param;
+ Dwarf_Attribute attr;
+ Dwarf_Addr low_pc;
+ struct func_entry func;
+ int tag;
+
+ tag = dwarf_tag(&child);
+ if (tag != DW_TAG_subprogram)
+ continue;
+
+ /* Skip declarations (no body) */
+ if (dwarf_attr(&child, DW_AT_declaration, &attr))
+ continue;
+
+ /* Get function start address */
+ if (dwarf_lowpc(&child, &low_pc) != 0)
+ continue;
+
+ if (low_pc < text_addr)
+ continue;
+
+ {
+ unsigned long long raw_offset = low_pc - text_addr;
+
+ if (raw_offset > UINT_MAX)
+ continue;
+ func.offset = (unsigned int)raw_offset;
+ }
+
+ /* Iterate formal parameters */
+ func.num_params = 0;
+ if (dwarf_child(&child, ¶m) == 0) {
+ do {
+ Dwarf_Die type_die;
+ const char *pname;
+
+ if (dwarf_tag(¶m) != DW_TAG_formal_parameter)
+ continue;
+ if (func.num_params >= MAX_PARAMS)
+ break;
+
+ pname = dwarf_diename(¶m);
+ if (!pname)
+ pname = "?";
+
+ snprintf(func.params[func.num_params].name,
+ sizeof(func.params[0].name),
+ "%s", pname);
+
+ /* Resolve type */
+ if (dwarf_attr(¶m, DW_AT_type, &attr) &&
+ dwarf_formref_die(&attr, &type_die)) {
+ build_type_name(&type_die,
+ func.params[func.num_params].type,
+ MAX_TYPE_LEN);
+ } else {
+ snprintf(func.params[func.num_params].type,
+ MAX_TYPE_LEN, "?");
+ }
+
+ func.num_params++;
+ } while (dwarf_siblingof(¶m, ¶m) == 0);
+ }
+
+ /* Skip functions with no parameters */
+ if (func.num_params == 0)
+ continue;
+
+ add_func(&func);
+ } while (dwarf_siblingof(&child, &child) == 0);
+next:
+ off = next_off;
+ }
+}
+
+static void deduplicate(void)
+{
+ unsigned int i, j;
+
+ if (num_funcs < 2)
+ return;
+
+ /* Sort by offset */
+ qsort(funcs, num_funcs, sizeof(*funcs), compare_funcs);
+
+ /* Remove duplicates (same offset — keep first) */
+ j = 0;
+ for (i = 1; i < num_funcs; i++) {
+ if (funcs[i].offset == funcs[j].offset)
+ continue;
+ j++;
+ if (j != i)
+ funcs[j] = funcs[i];
+ }
+ num_funcs = j + 1;
+}
+
+static void print_escaped_asciz(const char *s)
+{
+ printf("\t.asciz \"");
+ for (; *s; s++) {
+ if (*s == '"' || *s == '\\')
+ putchar('\\');
+ putchar(*s);
+ }
+ printf("\"\n");
+}
+
+static void output_assembly(void)
+{
+ unsigned int i, j;
+
+ printf("/* SPDX-License-Identifier: GPL-2.0 */\n");
+ printf("/*\n");
+ printf(" * Automatically generated by scripts/gen_paraminfo\n");
+ printf(" * Do not edit.\n");
+ printf(" */\n\n");
+
+ printf("\t.section .rodata, \"a\"\n\n");
+
+ /* Number of functions */
+ printf("\t.globl paraminfo_num_funcs\n");
+ printf("\t.balign 4\n");
+ printf("paraminfo_num_funcs:\n");
+ printf("\t.long %u\n\n", num_funcs);
+
+ /* Function address offsets (sorted, for binary search) */
+ printf("\t.globl paraminfo_func_addrs\n");
+ printf("\t.balign 4\n");
+ printf("paraminfo_func_addrs:\n");
+ for (i = 0; i < num_funcs; i++)
+ printf("\t.long 0x%x\n", funcs[i].offset);
+ printf("\n");
+
+ /*
+ * Function data offsets — byte offset into paraminfo_func_data
+ * for each function's parameter list.
+ */
+ printf("\t.globl paraminfo_func_offsets\n");
+ printf("\t.balign 4\n");
+ printf("paraminfo_func_offsets:\n");
+ for (i = 0; i < num_funcs; i++)
+ printf("\t.long .Lfunc_%u - paraminfo_func_data\n", i);
+ printf("\n");
+
+ /*
+ * Register strings in the string table and build the func data.
+ * Func data format per function:
+ * u8 num_params
+ * For each param:
+ * u32 name_str_offset
+ * u32 type_str_offset
+ */
+ /* First pass: register all strings */
+ for (i = 0; i < num_funcs; i++) {
+ for (j = 0; j < funcs[i].num_params; j++) {
+ find_or_add_string(funcs[i].params[j].name);
+ find_or_add_string(funcs[i].params[j].type);
+ }
+ }
+
+ /* Function parameter data */
+ printf("\t.globl paraminfo_func_data\n");
+ printf("paraminfo_func_data:\n");
+ for (i = 0; i < num_funcs; i++) {
+ printf(".Lfunc_%u:\n", i);
+ printf("\t.byte %u\n", funcs[i].num_params);
+ for (j = 0; j < funcs[i].num_params; j++) {
+ unsigned int name_idx = find_or_add_string(funcs[i].params[j].name);
+ unsigned int type_idx = find_or_add_string(funcs[i].params[j].type);
+
+ printf("\t.long %u, %u\n",
+ strtab[name_idx].offset,
+ strtab[type_idx].offset);
+ }
+ }
+ printf("\n");
+
+ /* String table */
+ printf("\t.globl paraminfo_strings\n");
+ printf("paraminfo_strings:\n");
+ for (i = 0; i < num_strings; i++)
+ print_escaped_asciz(strtab[i].str);
+ printf("\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ Elf *elf;
+ Dwarf *dwarf;
+ unsigned long long text_addr;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <vmlinux ELF>\n", argv[0]);
+ return 1;
+ }
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open %s: %s\n", argv[1],
+ strerror(errno));
+ return 1;
+ }
+
+ elf_version(EV_CURRENT);
+ elf = elf_begin(fd, ELF_C_READ, NULL);
+ if (!elf) {
+ fprintf(stderr, "elf_begin failed: %s\n",
+ elf_errmsg(elf_errno()));
+ close(fd);
+ return 1;
+ }
+
+ text_addr = find_text_addr(elf);
+
+ dwarf = dwarf_begin_elf(elf, DWARF_C_READ, NULL);
+ if (!dwarf) {
+ fprintf(stderr, "dwarf_begin_elf failed: %s\n",
+ dwarf_errmsg(dwarf_errno()));
+ fprintf(stderr, "Is %s built with CONFIG_DEBUG_INFO?\n",
+ argv[1]);
+ elf_end(elf);
+ close(fd);
+ return 1;
+ }
+
+ process_dwarf(dwarf, text_addr);
+ deduplicate();
+
+ fprintf(stderr, "paraminfo: %u functions, %u strings\n",
+ num_funcs, num_strings);
+
+ output_assembly();
+
+ dwarf_end(dwarf);
+ elf_end(elf);
+ close(fd);
+
+ /* Cleanup */
+ free(funcs);
+ for (unsigned int i = 0; i < num_strings; i++)
+ free(strtab[i].str);
+ free(strtab);
+
+ return 0;
+}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 39ca44fbb259b..d41b31dde4ef9 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -103,7 +103,7 @@ vmlinux_link()
${ld} ${ldflags} -o ${output} \
${wl}--whole-archive ${objs} ${wl}--no-whole-archive \
${wl}--start-group ${libs} ${wl}--end-group \
- ${kallsymso} ${lineinfo_o} ${btf_vmlinux_bin_o} ${arch_vmlinux_o} ${ldlibs}
+ ${kallsymso} ${lineinfo_o} ${paraminfo_o} ${btf_vmlinux_bin_o} ${arch_vmlinux_o} ${ldlibs}
}
# Create ${2}.o file with all symbols from the ${1} object file
@@ -149,6 +149,26 @@ gen_lineinfo()
lineinfo_o=.tmp_lineinfo.o
}
+# Generate paraminfo tables from DWARF debug info in a temporary vmlinux.
+# ${1} - temporary vmlinux with debug info
+# Output: sets paraminfo_o to the generated .o file
+gen_paraminfo()
+{
+ info PARAMINFO .tmp_paraminfo.S
+ if ! scripts/gen_paraminfo "${1}" > .tmp_paraminfo.S; then
+ echo >&2 "Failed to generate paraminfo from ${1}"
+ echo >&2 "Try to disable CONFIG_KALLSYMS_PARAMINFO"
+ exit 1
+ fi
+
+ info AS .tmp_paraminfo.o
+ ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \
+ ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
+ -c -o .tmp_paraminfo.o .tmp_paraminfo.S
+
+ paraminfo_o=.tmp_paraminfo.o
+}
+
# Perform kallsyms for the given temporary vmlinux.
sysmap_and_kallsyms()
{
@@ -176,6 +196,7 @@ cleanup()
{
rm -f .btf.*
rm -f .tmp_lineinfo.*
+ rm -f .tmp_paraminfo.*
rm -f .tmp_vmlinux.nm-sort
rm -f System.map
rm -f vmlinux
@@ -205,6 +226,7 @@ btf_vmlinux_bin_o=
btfids_vmlinux=
kallsymso=
lineinfo_o=
+paraminfo_o=
strip_debug=
generate_map=
@@ -229,12 +251,22 @@ if is_enabled CONFIG_KALLSYMS_LINEINFO; then
lineinfo_o=.tmp_lineinfo.o
fi
+if is_enabled CONFIG_KALLSYMS_PARAMINFO; then
+ # Assemble an empty paraminfo stub for the initial link.
+ # The real paraminfo is generated from .tmp_vmlinux1 by gen_paraminfo.
+ ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \
+ ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
+ -c -o .tmp_paraminfo.o "${srctree}/scripts/empty_paraminfo.S"
+ paraminfo_o=.tmp_paraminfo.o
+fi
+
if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DEBUG_INFO_BTF; then
- # The kallsyms linking does not need debug symbols, but BTF and
- # lineinfo generation do.
+ # The kallsyms linking does not need debug symbols, but BTF,
+ # lineinfo and paraminfo generation do.
if ! is_enabled CONFIG_DEBUG_INFO_BTF &&
- ! is_enabled CONFIG_KALLSYMS_LINEINFO; then
+ ! is_enabled CONFIG_KALLSYMS_LINEINFO &&
+ ! is_enabled CONFIG_KALLSYMS_PARAMINFO; then
strip_debug=1
fi
@@ -256,6 +288,10 @@ if is_enabled CONFIG_KALLSYMS_LINEINFO; then
gen_lineinfo .tmp_vmlinux1
fi
+if is_enabled CONFIG_KALLSYMS_PARAMINFO; then
+ gen_paraminfo .tmp_vmlinux1
+fi
+
if is_enabled CONFIG_KALLSYMS; then
# kallsyms support
--
2.51.0
^ permalink raw reply related
* [PATCH 0/2] kallsyms: show typed function parameters in oops/WARN dumps
From: Sasha Levin @ 2026-03-23 16:48 UTC (permalink / raw)
To: Andrew Morton, Masahiro Yamada, Nathan Chancellor, Nicolas Schier
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Peter Zijlstra, Josh Poimboeuf, Petr Mladek,
Alexei Starovoitov, Jonathan Corbet, David Gow, Kees Cook,
Greg KH, Luis Chamberlain, Steven Rostedt, Helge Deller,
Randy Dunlap, Geert Uytterhoeven, Juergen Gross, James Bottomley,
Alexey Dobriyan, Vlastimil Babka, Laurent Pinchart, Petr Pavlu,
x86, linux-kernel, linux-kbuild, linux-doc, linux-modules, bpf,
Sasha Levin
Building on the lineinfo series, this adds typed function parameter
display to oops and WARN dumps. A build-time tool extracts parameter
names and types from DWARF, and the kernel maps pt_regs to the calling
convention at crash time. When BTF is available, struct pointer
parameters are dereferenced and their members displayed.
Example output from a WARN in a function receiving struct new_utsname *
(kernel version info) and struct file * parameters:
------------[ cut here ]------------
WARNING: drivers/tty/sysrq.c:1209 at demo_crash+0xf/0x20 (drivers/tty/sysrq.c:1209)
CPU: 2 UID: 0 PID: 323 Comm: bash
RIP: 0010:demo_crash+0xf/0x20 (drivers/tty/sysrq.c:1209)
...
RDI: ffffffffb8ca8d00
RSI: ffffa0a3c250acc0
...
Function parameters (paraminfo_demo_crash):
uts (struct new_utsname *) = 0xffffffffb8ca8d00
.sysname = "Linux" .nodename = "localhost"
.release = "7.0.0-rc2-00006-g3190..." .version = "#45 SMP PRE"
file (struct file * ) = 0xffffa0a3c250acc0
.f_mode = (fmode_t)67993630 .f_op = (struct file_operations *)0xffffffffb7237620
.f_flags = (unsigned int)32769 .f_cred = (struct cred *)0xffffa0a3c2e06a80
.dentry = (struct dentry *)0xffffa0a3c0978cc0
.prev_pos = (loff_t)-1
Call Trace:
<TASK>
write_sysrq_trigger+0x96/0xb0 (drivers/tty/sysrq.c:1222)
proc_reg_write+0x54/0xa0 (fs/proc/inode.c:330)
vfs_write+0xc9/0x480 (fs/read_write.c:686)
ksys_write+0x6e/0xe0 (fs/read_write.c:738)
do_syscall_64+0xe2/0x570 (arch/x86/entry/syscall_64.c:62)
entry_SYSCALL_64_after_hwframe+0x77/0x7f (arch/x86/entry/entry_64.S:121)
Patch 1 adds the core paraminfo infrastructure (DWARF extraction,
kernel-side lookup, register-to-parameter mapping, ~1-2 MB overhead).
Patch 2 adds optional BTF-based struct rendering, gated behind
CONFIG_KALLSYMS_PARAMINFO_BTF.
Sasha Levin (2):
kallsyms: show function parameter info in oops/WARN dumps
kallsyms: add BTF-based deep parameter rendering in oops dumps
.../admin-guide/kallsyms-lineinfo.rst | 31 +
arch/x86/kernel/dumpstack.c | 6 +-
include/linux/kallsyms.h | 9 +
init/Kconfig | 40 ++
kernel/Makefile | 1 +
kernel/kallsyms.c | 182 ++++++
kernel/kallsyms_internal.h | 6 +
kernel/kallsyms_paraminfo_btf.c | 199 ++++++
lib/Kconfig.debug | 11 +
lib/tests/Makefile | 3 +
lib/tests/paraminfo_kunit.c | 249 ++++++++
scripts/Makefile | 3 +
scripts/empty_paraminfo.S | 18 +
scripts/gen_paraminfo.c | 597 ++++++++++++++++++
scripts/link-vmlinux.sh | 44 +-
15 files changed, 1393 insertions(+), 6 deletions(-)
create mode 100644 kernel/kallsyms_paraminfo_btf.c
create mode 100644 lib/tests/paraminfo_kunit.c
create mode 100644 scripts/empty_paraminfo.S
create mode 100644 scripts/gen_paraminfo.c
--
2.51.0
^ permalink raw reply
* Re: [PATCH v9 4/5] arm64: kexec: Add support for crashkernel CMA reservation
From: Breno Leitao @ 2026-03-23 16:42 UTC (permalink / raw)
To: Jinjie Ruan
Cc: corbet, skhan, catalin.marinas, will, chenhuacai, kernel, maddy,
mpe, npiggin, chleroy, pjw, palmer, aou, alex, tglx, mingo, bp,
dave.hansen, hpa, robh, saravanak, akpm, bhe, vgoyal, dyoung,
rdunlap, peterz, feng.tang, pawan.kumar.gupta, dapeng1.mi, kees,
elver, paulmck, lirongqing, safinaskar, rppt, ardb, jbohac,
cfsworks, osandov, tangyouling, sourabhjain, ritesh.list, eajames,
songshuaishuai, kevin.brodsky, samuel.holland, vishal.moola,
junhui.liu, coxu, liaoyuanhong, fuqiang.wang, x86, linux-doc,
linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
linux-riscv, devicetree, kexec
In-Reply-To: <a5694ee0-7a95-4c15-6775-990d70c8d77b@huawei.com>
On Mon, Mar 23, 2026 at 07:17:21PM +0800, Jinjie Ruan wrote:
>
>
> On 2026/3/23 18:20, Breno Leitao wrote:
> > On Mon, Mar 23, 2026 at 03:27:44PM +0800, Jinjie Ruan wrote:
> >> Commit 35c18f2933c5 ("Add a new optional ",cma" suffix to the
> >> crashkernel= command line option") and commit ab475510e042 ("kdump:
> >> implement reserve_crashkernel_cma") added CMA support for kdump
> >> crashkernel reservation.
> >>
> >> Crash kernel memory reservation wastes production resources if too
> >> large, risks kdump failure if too small, and faces allocation difficulties
> >> on fragmented systems due to contiguous block constraints. The new
> >> CMA-based crashkernel reservation scheme splits the "large fixed
> >> reservation" into a "small fixed region + large CMA dynamic region": the
> >> CMA memory is available to userspace during normal operation to avoid
> >> waste, and is reclaimed for kdump upon crash—saving memory while
> >> improving reliability.
> >>
> >> So extend crashkernel CMA reservation support to arm64. The following
> >> changes are made to enable CMA reservation:
> >>
> >> - Parse and obtain the CMA reservation size along with other crashkernel
> >> parameters.
> >> - Call reserve_crashkernel_cma() to allocate the CMA region for kdump.
> >> - Include the CMA-reserved ranges for kdump kernel to use.
> >> - Exclude the CMA-reserved ranges from the crash kernel memory to
> >> prevent them from being exported through /proc/vmcore, which is already
> >> done in the crash core.
> >>
> >> Update kernel-parameters.txt to document CMA support for crashkernel on
> >> arm64 architecture.
> >>
> >> Acked-by: Rob Herring (Arm) <robh@kernel.org>
> >> Acked-by: Baoquan He <bhe@redhat.com>
> >> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> >> Acked-by: Ard Biesheuvel <ardb@kernel.org>
> >> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> >> ---
> >> v7:
> >> - Correct the inclusion of CMA-reserved ranges for kdump
> >> kernel in of/kexec.
> >> v3:
> >> - Add Acked-by.
> >> v2:
> >> - Free cmem in prepare_elf_headers()
> >> - Add the mtivation.
> >> ---
> >> Documentation/admin-guide/kernel-parameters.txt | 2 +-
> >> arch/arm64/kernel/machine_kexec_file.c | 2 +-
> >> arch/arm64/mm/init.c | 5 +++--
> >> drivers/of/fdt.c | 9 +++++----
> >> drivers/of/kexec.c | 9 +++++++++
> >> 5 files changed, 19 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> >> index cb850e5290c2..afb3112510f7 100644
> >> --- a/Documentation/admin-guide/kernel-parameters.txt
> >> +++ b/Documentation/admin-guide/kernel-parameters.txt
> >> @@ -1121,7 +1121,7 @@ Kernel parameters
> >> It will be ignored when crashkernel=X,high is not used
> >> or memory reserved is below 4G.
> >> crashkernel=size[KMG],cma
> >> - [KNL, X86, ppc] Reserve additional crash kernel memory from
> >> + [KNL, X86, ARM64, PPC] Reserve additional crash kernel memory from
> >> CMA. This reservation is usable by the first system's
> >> userspace memory and kernel movable allocations (memory
> >> balloon, zswap). Pages allocated from this memory range
> >> diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
> >> index c338506a580b..cc577d77df00 100644
> >> --- a/arch/arm64/kernel/machine_kexec_file.c
> >> +++ b/arch/arm64/kernel/machine_kexec_file.c
> >> @@ -42,7 +42,7 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
> >> #ifdef CONFIG_CRASH_DUMP
> >> unsigned int arch_get_system_nr_ranges(void)
> >> {
> >> - unsigned int nr_ranges = 2; /* for exclusion of crashkernel region */
> >> + unsigned int nr_ranges = 2 + crashk_cma_cnt; /* for exclusion of crashkernel region */
> >
> > You update arch_get_system_nr_ranges() to account for CMA ranges, but
> > prepare_elf_headers() in the same file (line 51) still has the
> > hardcoded:
> >
> > nr_ranges = 2; /* for exclusion of crashkernel region */
>
> I don't see any logic related to prepare_elf_headers() or hardcoded
> nr_ranges = 2 in the arm64 implementation.
Just ignore me here, I've mis applied the patch, and then I got
arch_get_system_nr_ranges() and prepare_elf_headers(), but, they are the
same thing at in here.
> >
> > and does not exclude CMA ranges from cmem. If the generic crash core
> > handles CMA exclusion from vmcore, then shouldn't
> > arch_get_system_nr_ranges() also not need this change?
> >
^ permalink raw reply
* Re: [PATCH v5 00/21] Virtual Swap Space
From: Kairui Song @ 2026-03-23 16:40 UTC (permalink / raw)
To: Nhat Pham
Cc: Liam.Howlett, akpm, apopple, axelrasmussen, baohua, baolin.wang,
bhe, byungchul, cgroups, chengming.zhou, chrisl, corbet, david,
dev.jain, gourry, hannes, hughd, jannh, joshua.hahnjy, lance.yang,
lenb, linux-doc, linux-kernel, linux-mm, linux-pm,
lorenzo.stoakes, matthew.brost, mhocko, muchun.song, npache,
pavel, peterx, peterz, pfalcato, rafael, rakie.kim,
roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAKEwX=PBjMVfMvKkNfqbgiw7o10NFyZBSB62ODzsqogv-WDYKQ@mail.gmail.com>
On Mon, Mar 23, 2026 at 11:33 PM Nhat Pham <nphamcs@gmail.com> wrote:
>
> On Mon, Mar 23, 2026 at 6:09 AM Kairui Song <ryncsn@gmail.com> wrote:
> >
> > On Sat, Mar 21, 2026 at 3:29 AM Nhat Pham <nphamcs@gmail.com> wrote:
> > > This patch series is based on 6.19. There are a couple more
> > > swap-related changes in mainline that I would need to coordinate
> > > with, but I still want to send this out as an update for the
> > > regressions reported by Kairui Song in [15]. It's probably easier
> > > to just build this thing rather than dig through that series of
> > > emails to get the fix patch :)
> > >
> > > Changelog:
> > > * v4 -> v5:
> > > * Fix a deadlock in memcg1_swapout (reported by syzbot [16]).
> > > * Replace VM_WARN_ON(!spin_is_locked()) with lockdep_assert_held(),
> > > and use guard(rcu) in vswap_cpu_dead
> > > (reported by Peter Zijlstra [17]).
> > > * v3 -> v4:
> > > * Fix poor swap free batching behavior to alleviate a regression
> > > (reported by Kairui Song).
> >
>
> Hi Kairui! Thanks a lot for the testing big boss :) I will focus on
> the regression in this patch series - we can talk more about
> directions in another thread :)
Hi Nhat,
> Interesting. Normally "lots of zero-filled page" is a very beneficial
> case for vswap. You don't need a swapfile, or any zram/zswap metadata
> overhead - it's a native swap backend. If production workload has this
> many zero-filled pages, I think the numbers of vswap would be much
> less alarming - perhaps even matching memory overhead because you
> don't need to maintain a zram entry metadata (it's at least 2 words
> per zram entry right?), while there's no reverse map overhead induced
> (so it's 24 bytes on both side), and no need to do zram-side locking
> :)
>
> So I was surprised to see that it's not working out very well here. I
> checked the implementation of memhog - let me know if this is wrong
> place to look:
>
> https://man7.org/linux/man-pages/man8/memhog.8.html
> https://github.com/numactl/numactl/blob/master/memhog.c#L52
>
> I think this is what happened here: memhog was populating the memory
> 0xff, which triggers the full overhead of a swapfile-backed swap entry
> because even though it's "same-filled" it's not zero-filled! I was
> following Usama's observation - "less than 1% of the same-filled pages
> were non-zero" - and so I only handled the zero-filled case here:
>
> https://lore.kernel.org/all/20240530102126.357438-1-usamaarif642@gmail.com/
>
> This sounds a bit artificial IMHO - as Usama pointed out above, I
> think most samefilled pages are zero pages, in real production
> workloads. However, if you think there are real use cases with a lot
I vaguely remember some workloads like Java or some JS engine
initialize their heap with fixed value, same fill might not be that
common but not a rare thing, it strongly depends on the workload.
> of non-zero samefilled pages, please let me know I can fix this real
> quick. We can support this in vswap with zero extra metadata overhead
> - change the VSWAP_ZERO swap entry type to VSWAP_SAME_FILLED, then use
> the backend field to store that value. I can send you a patch if
> you're interested.
Actually I don't think that's the main problem. For example, I just
wrote a few lines C bench program to zerofill ~50G of memory
and swapout sequentially:
Before:
Swapout: 4415467us
Swapin: 49573297us
After:
Swapout: 4955874us
Swapin: 56223658us
And vmstat:
cat /proc/vmstat | grep zero
thp_zero_page_alloc 0
thp_zero_page_alloc_failed 0
swpin_zero 12239329
swpout_zero 21516634
There are all zero filled pages, but still slower. And what's more, a
more critical issue, I just found the cgroup and global swap usage
accounting are both somehow broken for zero page swap,
maybe because you skipped some allocation? Users can
no longer see how many pages are swapped out. I don't think you can
break that, that's one major reason why we use a zero entry instead of
mapping to a zero readonly page. If that is acceptable, we can have
a very nice optimization right away with current swap.
That's still just an example. bypassing the accounting and still
slower is not a good sign. We should focus on the generic
performance and design.
Yet this is just another new found issue, there are many other parts
like the folio swap allocation may still occur even if a lower device
can no longer accept more whole folios, which I'm currently
unsure how it will affect swap.
> 1. Regarding pmem backend - I'm not sure if I can get my hands on one
> of these, but if you think SSD has the same characteristics maybe I
> can give that a try? The problem with SSD is for some reason variance
> tends to be pretty high, between iterations yes, but especially across
> reboots. Or maybe zram?
Yeah, ZRAM has a very similar number for some cases, but storage is
getting faster and faster and swap occurs through high speed networks
too. We definitely shouldn't ignore that.
> 2. What about the other numbers below? Are they also on pmem? FTR I
> was running most of my benchmarks on zswap, except for one kernel
> build benchmark on SSD.
>
> 3. Any other backends and setup you're interested in?
>
> BTW, sounds like you have a great benchmark suite - is it open source
> somewhere? If not, can you share it with us :) Vswap aside, I think
> this would be a good suite to run all swap related changes for every
> swap contributor.
I can try to post that somewhere, really nothing fancy just some
wrapper to make use of systemd for reboot and auto test. But all test
steps I mentioned before are already posted and publically available.
^ permalink raw reply
* Re: [PATCH v2 4/5] watchdog/hardlockup: improve buddy system detection timeliness
From: Petr Mladek @ 2026-03-23 16:26 UTC (permalink / raw)
To: mrungta
Cc: Jinchao Wang, Yunhui Cui, Stephane Eranian, Ian Rogers, Li Huafei,
Feng Tang, Max Kellermann, Jonathan Corbet, Douglas Anderson,
Andrew Morton, Florian Delizy, Shuah Khan, linux-kernel,
linux-doc
In-Reply-To: <20260312-hardlockup-watchdog-fixes-v2-4-45bd8a0cc7ed@google.com>
On Thu 2026-03-12 16:22:05, Mayank Rungta via B4 Relay wrote:
> From: Mayank Rungta <mrungta@google.com>
>
> Currently, the buddy system only performs checks every 3rd sample. With
> a 4-second interval. If a check window is missed, the next check occurs
> 12 seconds later, potentially delaying hard lockup detection for up to
> 24 seconds.
>
> Modify the buddy system to perform checks at every interval (4s).
> Introduce a missed-interrupt threshold to maintain the existing grace
> period while reducing the detection window to 8-12 seconds.
>
> Best and worst case detection scenarios:
>
> Before (12s check window):
> - Best case: Lockup occurs after first check but just before heartbeat
> interval. Detected in ~8s (8s till next check).
> - Worst case: Lockup occurs just after a check.
> Detected in ~24s (missed check + 12s till next check + 12s logic).
>
> After (4s check window with threshold of 3):
> - Best case: Lockup occurs just before a check.
> Detected in ~8s (0s till 1st check + 4s till 2nd + 4s till 3rd).
> - Worst case: Lockup occurs just after a check.
> Detected in ~12s (4s till 1st check + 4s till 2nd + 4s till 3rd).
>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> Signed-off-by: Mayank Rungta <mrungta@google.com>
LGTM:
Reviewed-by: Petr Mladek <pmladek@suse.com>
Best Regards,
Petr
^ permalink raw reply
* [PATCH 3/3] hwmon: (tmp108) Add support for NXP P3T1084UK
From: Anshika Gupta @ 2026-03-23 16:22 UTC (permalink / raw)
To: linux, corbet, skhan, linux-hwmon, linux-doc, linux-kernel, robh,
krzk+dt, conor+dt, devicetree
Cc: lakshaypiplani77, Anshika Gupta
In-Reply-To: <20260323162252.15508-1-guptaanshika.ag@gmail.com>
The NXP P3T1084UK is a ±0.4°C accurate digital temperature sensor with
a 12-bit temperature register, configuration register, and alert
functionality over I²C/I3C. Its register interface matches the TMP108
programming model, so the existing tmp108 driver can bind it without
functional changes.
Add "nxp,p3t1084uk" to the OF match table and "p3t1084" to the I²C
device-id table so the driver probes the device via both devicetree and
board data.
Datasheet: https://www.nxp.com/part/P3T1084UK
https://www.nxp.com/docs/en/data-sheet/P3T1084UK.pdf
Signed-off-by: Lakshay Piplani <lakshaypiplani77@gmail.com>
Signed-off-by: Anshika Gupta <guptaanshika.ag@gmail.com>
---
drivers/hwmon/tmp108.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
index 3ea5f6485744..db46961a31d3 100644
--- a/drivers/hwmon/tmp108.c
+++ b/drivers/hwmon/tmp108.c
@@ -538,6 +538,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume
static const struct i2c_device_id tmp108_i2c_ids[] = {
{ "p3t1035", (unsigned long)&p3t1035_data },
+ { "p3t1084", (unsigned long)&tmp108_data },
{ "p3t1085", (unsigned long)&tmp108_data },
{ "tmp108", (unsigned long)&tmp108_data },
{}
@@ -546,6 +547,7 @@ MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids);
static const struct of_device_id tmp108_of_ids[] = {
{ .compatible = "nxp,p3t1035", .data = &p3t1035_data },
+ { .compatible = "nxp,p3t1084", .data = &tmp108_data },
{ .compatible = "nxp,p3t1085", .data = &tmp108_data },
{ .compatible = "ti,tmp108", .data = &tmp108_data },
{}
--
2.34.1
^ permalink raw reply related
* [PATCH 2/3] docs: hwmon: Update TMP108 documentation for NXP P3T1084UK support
From: Anshika Gupta @ 2026-03-23 16:22 UTC (permalink / raw)
To: linux, corbet, skhan, linux-hwmon, linux-doc, linux-kernel, robh,
krzk+dt, conor+dt, devicetree
Cc: lakshaypiplani77, Anshika Gupta
In-Reply-To: <20260323162252.15508-1-guptaanshika.ag@gmail.com>
Add references to the NXP P3T1084UK temperature sensor in the TMP108
hardware monitoring documentation. The P3T1084UK is compatible with
the TMP108 register interface and protocol, and the hwmon driver now
supports it. Update the .rst document accordingly to reflect the new
compatible device and its expected behavior.
Signed-off-by: Lakshay Piplani <lakshaypiplani77@gmail.com>
Signed-off-by: Anshika Gupta <guptaanshika.ag@gmail.com>
---
Documentation/hwmon/tmp108.rst | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/hwmon/tmp108.rst b/Documentation/hwmon/tmp108.rst
index c218ea333dd6..cda280032710 100644
--- a/Documentation/hwmon/tmp108.rst
+++ b/Documentation/hwmon/tmp108.rst
@@ -11,6 +11,13 @@ Supported chips:
Datasheet: https://www.nxp.com/docs/en/data-sheet/P3T1035XUK_P3T2030XUK.pdf
+ * NXP P3T1084
+
+ Prefix: 'p3t1045'
+
+ Addresses scanned: none
+
+ Datasheet: https://www.nxp.com/docs/en/data-sheet/P3T1084UK.pdf
* NXP P3T1085
--
2.34.1
^ permalink raw reply related
* [PATCH 1/3] dt-bindings: hwmon: Add support for NXP P3T1084UK temperature sensor
From: Anshika Gupta @ 2026-03-23 16:22 UTC (permalink / raw)
To: linux, corbet, skhan, linux-hwmon, linux-doc, linux-kernel, robh,
krzk+dt, conor+dt, devicetree
Cc: lakshaypiplani77, Anshika Gupta
The P3T1084UK is an NXP digital temperature sensor compatible with the
Texas Instruments TMP108 register and protocol specification. This patch
extends the existing DT binding for "ti,tmp108" to document the
compatible string for P3T1084UK so that the hwmon TMP108 driver can
bind to this device.
Signed-off-by: Lakshay Piplani <lakshaypiplani77@gmail.com>
Signed-off-by: Anshika Gupta <guptaanshika.ag@gmail.com>
---
Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
index 9f6c9f6fa561..47714df5aaff 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,tmp108.yaml
@@ -4,20 +4,21 @@
$id: http://devicetree.org/schemas/hwmon/ti,tmp108.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: TMP108/P3T1035/P3T1085/P3T2030 temperature sensor
+title: TMP108/P3T1035/P3T1084/P3T1085/P3T2030 temperature sensor
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
- The TMP108 or NXP P3T Family (P3T1035, P3T1085 and P3T2030) is a digital-
+ The TMP108 or NXP P3T Family (P3T1035, P3T1084, P3T1085 and P3T2030) is a digital-
output temperature sensor with a dynamically-programmable limit window,
and under- and over-temperature alert functions.
- NXP P3T Family (P3T1035, P3T1085 and P3T2030) supports I3C.
+ NXP P3T Family (P3T1035, P3T1084, P3T1085 and P3T2030) supports I3C.
Datasheets:
https://www.ti.com/product/TMP108
+ https://www.nxp.com/docs/en/data-sheet/P3T1084UK.pdf
https://www.nxp.com/docs/en/data-sheet/P3T1085UK.pdf
https://www.nxp.com/docs/en/data-sheet/P3T1035XUK_P3T2030XUK.pdf
@@ -28,6 +29,7 @@ properties:
- const: nxp,p3t2030
- const: nxp,p3t1035
- const: nxp,p3t1035
+ - const: nxp,p3t1084
- const: nxp,p3t1085
- const: ti,tmp108
--
2.34.1
^ permalink raw reply related
* [PATCH 6.1 229/481] time: add kernel-doc in time.c
From: Greg Kroah-Hartman @ 2026-03-23 13:43 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Randy Dunlap, John Stultz,
Thomas Gleixner, Stephen Boyd, Jonathan Corbet, linux-doc,
Sasha Levin
In-Reply-To: <20260323134525.256603107@linuxfoundation.org>
6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Randy Dunlap <rdunlap@infradead.org>
[ Upstream commit 67b3f564cb1e769ef8e45835129a4866152fcfdb ]
Add kernel-doc for all APIs that do not already have it.
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: John Stultz <jstultz@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org
Acked-by: John Stultz <jstultz@google.com>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/20230704052405.5089-3-rdunlap@infradead.org
Stable-dep-of: 755a648e78f1 ("time/jiffies: Mark jiffies_64_to_clock_t() notrace")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/time/time.c | 169 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 158 insertions(+), 11 deletions(-)
diff --git a/kernel/time/time.c b/kernel/time/time.c
index a92c7f3277ad6..be42ace51255c 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -365,11 +365,14 @@ SYSCALL_DEFINE1(adjtimex_time32, struct old_timex32 __user *, utp)
}
#endif
-/*
- * Convert jiffies to milliseconds and back.
+/**
+ * jiffies_to_msecs - Convert jiffies to milliseconds
+ * @j: jiffies value
*
* Avoid unnecessary multiplications/divisions in the
- * two most common HZ cases:
+ * two most common HZ cases.
+ *
+ * Return: milliseconds value
*/
unsigned int jiffies_to_msecs(const unsigned long j)
{
@@ -388,6 +391,12 @@ unsigned int jiffies_to_msecs(const unsigned long j)
}
EXPORT_SYMBOL(jiffies_to_msecs);
+/**
+ * jiffies_to_usecs - Convert jiffies to microseconds
+ * @j: jiffies value
+ *
+ * Return: microseconds value
+ */
unsigned int jiffies_to_usecs(const unsigned long j)
{
/*
@@ -408,8 +417,15 @@ unsigned int jiffies_to_usecs(const unsigned long j)
}
EXPORT_SYMBOL(jiffies_to_usecs);
-/*
+/**
* mktime64 - Converts date to seconds.
+ * @year0: year to convert
+ * @mon0: month to convert
+ * @day: day to convert
+ * @hour: hour to convert
+ * @min: minute to convert
+ * @sec: second to convert
+ *
* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -427,6 +443,8 @@ EXPORT_SYMBOL(jiffies_to_usecs);
*
* An encoding of midnight at the end of the day as 24:00:00 - ie. midnight
* tomorrow - (allowable under ISO 8601) is supported.
+ *
+ * Return: seconds since the epoch time for the given input date
*/
time64_t mktime64(const unsigned int year0, const unsigned int mon0,
const unsigned int day, const unsigned int hour,
@@ -471,8 +489,7 @@ EXPORT_SYMBOL(ns_to_kernel_old_timeval);
* Set seconds and nanoseconds field of a timespec variable and
* normalize to the timespec storage format
*
- * Note: The tv_nsec part is always in the range of
- * 0 <= tv_nsec < NSEC_PER_SEC
+ * Note: The tv_nsec part is always in the range of 0 <= tv_nsec < NSEC_PER_SEC.
* For negative values only the tv_sec field is negative !
*/
void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec)
@@ -501,7 +518,7 @@ EXPORT_SYMBOL(set_normalized_timespec64);
* ns_to_timespec64 - Convert nanoseconds to timespec64
* @nsec: the nanoseconds value to be converted
*
- * Returns the timespec64 representation of the nsec parameter.
+ * Return: the timespec64 representation of the nsec parameter.
*/
struct timespec64 ns_to_timespec64(s64 nsec)
{
@@ -548,6 +565,8 @@ EXPORT_SYMBOL(ns_to_timespec64);
* runtime.
* the _msecs_to_jiffies helpers are the HZ dependent conversion
* routines found in include/linux/jiffies.h
+ *
+ * Return: jiffies value
*/
unsigned long __msecs_to_jiffies(const unsigned int m)
{
@@ -560,6 +579,12 @@ unsigned long __msecs_to_jiffies(const unsigned int m)
}
EXPORT_SYMBOL(__msecs_to_jiffies);
+/**
+ * __usecs_to_jiffies: - convert microseconds to jiffies
+ * @u: time in milliseconds
+ *
+ * Return: jiffies value
+ */
unsigned long __usecs_to_jiffies(const unsigned int u)
{
if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
@@ -568,7 +593,10 @@ unsigned long __usecs_to_jiffies(const unsigned int u)
}
EXPORT_SYMBOL(__usecs_to_jiffies);
-/*
+/**
+ * timespec64_to_jiffies - convert a timespec64 value to jiffies
+ * @value: pointer to &struct timespec64
+ *
* The TICK_NSEC - 1 rounds up the value to the next resolution. Note
* that a remainder subtract here would not do the right thing as the
* resolution values don't fall on second boundaries. I.e. the line:
@@ -582,8 +610,9 @@ EXPORT_SYMBOL(__usecs_to_jiffies);
*
* The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
* value to a scaled second value.
+ *
+ * Return: jiffies value
*/
-
unsigned long
timespec64_to_jiffies(const struct timespec64 *value)
{
@@ -601,6 +630,11 @@ timespec64_to_jiffies(const struct timespec64 *value)
}
EXPORT_SYMBOL(timespec64_to_jiffies);
+/**
+ * jiffies_to_timespec64 - convert jiffies value to &struct timespec64
+ * @jiffies: jiffies value
+ * @value: pointer to &struct timespec64
+ */
void
jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value)
{
@@ -618,6 +652,13 @@ EXPORT_SYMBOL(jiffies_to_timespec64);
/*
* Convert jiffies/jiffies_64 to clock_t and back.
*/
+
+/**
+ * jiffies_to_clock_t - Convert jiffies to clock_t
+ * @x: jiffies value
+ *
+ * Return: jiffies converted to clock_t (CLOCKS_PER_SEC)
+ */
clock_t jiffies_to_clock_t(unsigned long x)
{
#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
@@ -632,6 +673,12 @@ clock_t jiffies_to_clock_t(unsigned long x)
}
EXPORT_SYMBOL(jiffies_to_clock_t);
+/**
+ * clock_t_to_jiffies - Convert clock_t to jiffies
+ * @x: clock_t value
+ *
+ * Return: clock_t value converted to jiffies
+ */
unsigned long clock_t_to_jiffies(unsigned long x)
{
#if (HZ % USER_HZ)==0
@@ -649,6 +696,12 @@ unsigned long clock_t_to_jiffies(unsigned long x)
}
EXPORT_SYMBOL(clock_t_to_jiffies);
+/**
+ * jiffies_64_to_clock_t - Convert jiffies_64 to clock_t
+ * @x: jiffies_64 value
+ *
+ * Return: jiffies_64 value converted to 64-bit "clock_t" (CLOCKS_PER_SEC)
+ */
u64 jiffies_64_to_clock_t(u64 x)
{
#if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
@@ -671,6 +724,12 @@ u64 jiffies_64_to_clock_t(u64 x)
}
EXPORT_SYMBOL(jiffies_64_to_clock_t);
+/**
+ * nsec_to_clock_t - Convert nsec value to clock_t
+ * @x: nsec value
+ *
+ * Return: nsec value converted to 64-bit "clock_t" (CLOCKS_PER_SEC)
+ */
u64 nsec_to_clock_t(u64 x)
{
#if (NSEC_PER_SEC % USER_HZ) == 0
@@ -687,6 +746,12 @@ u64 nsec_to_clock_t(u64 x)
#endif
}
+/**
+ * jiffies64_to_nsecs - Convert jiffies64 to nanoseconds
+ * @j: jiffies64 value
+ *
+ * Return: nanoseconds value
+ */
u64 jiffies64_to_nsecs(u64 j)
{
#if !(NSEC_PER_SEC % HZ)
@@ -697,6 +762,12 @@ u64 jiffies64_to_nsecs(u64 j)
}
EXPORT_SYMBOL(jiffies64_to_nsecs);
+/**
+ * jiffies64_to_msecs - Convert jiffies64 to milliseconds
+ * @j: jiffies64 value
+ *
+ * Return: milliseconds value
+ */
u64 jiffies64_to_msecs(const u64 j)
{
#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
@@ -719,6 +790,8 @@ EXPORT_SYMBOL(jiffies64_to_msecs);
* note:
* NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
* ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
+ *
+ * Return: nsecs converted to jiffies64 value
*/
u64 nsecs_to_jiffies64(u64 n)
{
@@ -750,6 +823,8 @@ EXPORT_SYMBOL(nsecs_to_jiffies64);
* note:
* NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
* ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
+ *
+ * Return: nsecs converted to jiffies value
*/
unsigned long nsecs_to_jiffies(u64 n)
{
@@ -757,10 +832,16 @@ unsigned long nsecs_to_jiffies(u64 n)
}
EXPORT_SYMBOL_GPL(nsecs_to_jiffies);
-/*
- * Add two timespec64 values and do a safety check for overflow.
+/**
+ * timespec64_add_safe - Add two timespec64 values and do a safety check
+ * for overflow.
+ * @lhs: first (left) timespec64 to add
+ * @rhs: second (right) timespec64 to add
+ *
* It's assumed that both values are valid (>= 0).
* And, each timespec64 is in normalized form.
+ *
+ * Return: sum of @lhs + @rhs
*/
struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
const struct timespec64 rhs)
@@ -778,6 +859,15 @@ struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
return res;
}
+/**
+ * get_timespec64 - get user's time value into kernel space
+ * @ts: destination &struct timespec64
+ * @uts: user's time value as &struct __kernel_timespec
+ *
+ * Handles compat or 32-bit modes.
+ *
+ * Return: %0 on success or negative errno on error
+ */
int get_timespec64(struct timespec64 *ts,
const struct __kernel_timespec __user *uts)
{
@@ -801,6 +891,14 @@ int get_timespec64(struct timespec64 *ts,
}
EXPORT_SYMBOL_GPL(get_timespec64);
+/**
+ * put_timespec64 - convert timespec64 value to __kernel_timespec format and
+ * copy the latter to userspace
+ * @ts: input &struct timespec64
+ * @uts: user's &struct __kernel_timespec
+ *
+ * Return: %0 on success or negative errno on error
+ */
int put_timespec64(const struct timespec64 *ts,
struct __kernel_timespec __user *uts)
{
@@ -839,6 +937,15 @@ static int __put_old_timespec32(const struct timespec64 *ts64,
return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0;
}
+/**
+ * get_old_timespec32 - get user's old-format time value into kernel space
+ * @ts: destination &struct timespec64
+ * @uts: user's old-format time value (&struct old_timespec32)
+ *
+ * Handles X86_X32_ABI compatibility conversion.
+ *
+ * Return: %0 on success or negative errno on error
+ */
int get_old_timespec32(struct timespec64 *ts, const void __user *uts)
{
if (COMPAT_USE_64BIT_TIME)
@@ -848,6 +955,16 @@ int get_old_timespec32(struct timespec64 *ts, const void __user *uts)
}
EXPORT_SYMBOL_GPL(get_old_timespec32);
+/**
+ * put_old_timespec32 - convert timespec64 value to &struct old_timespec32 and
+ * copy the latter to userspace
+ * @ts: input &struct timespec64
+ * @uts: user's &struct old_timespec32
+ *
+ * Handles X86_X32_ABI compatibility conversion.
+ *
+ * Return: %0 on success or negative errno on error
+ */
int put_old_timespec32(const struct timespec64 *ts, void __user *uts)
{
if (COMPAT_USE_64BIT_TIME)
@@ -857,6 +974,13 @@ int put_old_timespec32(const struct timespec64 *ts, void __user *uts)
}
EXPORT_SYMBOL_GPL(put_old_timespec32);
+/**
+ * get_itimerspec64 - get user's &struct __kernel_itimerspec into kernel space
+ * @it: destination &struct itimerspec64
+ * @uit: user's &struct __kernel_itimerspec
+ *
+ * Return: %0 on success or negative errno on error
+ */
int get_itimerspec64(struct itimerspec64 *it,
const struct __kernel_itimerspec __user *uit)
{
@@ -872,6 +996,14 @@ int get_itimerspec64(struct itimerspec64 *it,
}
EXPORT_SYMBOL_GPL(get_itimerspec64);
+/**
+ * put_itimerspec64 - convert &struct itimerspec64 to __kernel_itimerspec format
+ * and copy the latter to userspace
+ * @it: input &struct itimerspec64
+ * @uit: user's &struct __kernel_itimerspec
+ *
+ * Return: %0 on success or negative errno on error
+ */
int put_itimerspec64(const struct itimerspec64 *it,
struct __kernel_itimerspec __user *uit)
{
@@ -887,6 +1019,13 @@ int put_itimerspec64(const struct itimerspec64 *it,
}
EXPORT_SYMBOL_GPL(put_itimerspec64);
+/**
+ * get_old_itimerspec32 - get user's &struct old_itimerspec32 into kernel space
+ * @its: destination &struct itimerspec64
+ * @uits: user's &struct old_itimerspec32
+ *
+ * Return: %0 on success or negative errno on error
+ */
int get_old_itimerspec32(struct itimerspec64 *its,
const struct old_itimerspec32 __user *uits)
{
@@ -898,6 +1037,14 @@ int get_old_itimerspec32(struct itimerspec64 *its,
}
EXPORT_SYMBOL_GPL(get_old_itimerspec32);
+/**
+ * put_old_itimerspec32 - convert &struct itimerspec64 to &struct
+ * old_itimerspec32 and copy the latter to userspace
+ * @its: input &struct itimerspec64
+ * @uits: user's &struct old_itimerspec32
+ *
+ * Return: %0 on success or negative errno on error
+ */
int put_old_itimerspec32(const struct itimerspec64 *its,
struct old_itimerspec32 __user *uits)
{
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
From: David Lechner @ 2026-03-23 16:08 UTC (permalink / raw)
To: Francesco Lavra, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
In-Reply-To: <af2128c68d2a14e1eb664ce9dc075ed02b640407.camel@baylibre.com>
On 3/23/26 11:04 AM, Francesco Lavra wrote:
> On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
>> On 3/17/26 10:04 AM, Francesco Lavra wrote:
>>> This field is used to differentiate between signed and unsigned
>>> integers.
>>> A following commit will extend its use in order to add support for non-
>>> integer scan elements; therefore, replace it with a union that contains
>>> a
>>> more generic 'format' field. This union will be dropped when all
>>> drivers
>>> are changed to use the format field.
>>> Opportunistically replace character literals with symbolic constants
>>> that
>>> represent the set of allowed values for the format field.
>>>
>>> Signed-off-by: Francesco Lavra <flavra@baylibre.com>
>>> ---
>>> Documentation/driver-api/iio/buffers.rst | 4 ++--
>>> include/linux/iio/iio.h | 17 +++++++++++++++--
>>> 2 files changed, 17 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/Documentation/driver-api/iio/buffers.rst
>>> b/Documentation/driver-api/iio/buffers.rst
>>> index 63f364e862d1..e16abaf826fe 100644
>>> --- a/Documentation/driver-api/iio/buffers.rst
>>> +++ b/Documentation/driver-api/iio/buffers.rst
>>> @@ -78,7 +78,7 @@ fields in iio_chan_spec definition::
>>> /* other members */
>>> int scan_index
>>> struct {
>>> - char sign;
>>> + char format;
>>> u8 realbits;
>>> u8 storagebits;
>>> u8 shift;
>>> @@ -98,7 +98,7 @@ following channel definition::
>>> /* other stuff here */
>>> .scan_index = 0,
>>> .scan_type = {
>>> - .sign = 's',
>>> + .format = IIO_SCAN_FORMAT_SIGNED_INT,
>>> .realbits = 12,
>>> .storagebits = 16,
>>> .shift = 4,
>>> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
>>> index a9ecff191bd9..d48a0ab01b8d 100644
>>> --- a/include/linux/iio/iio.h
>>> +++ b/include/linux/iio/iio.h
>>> @@ -176,9 +176,19 @@ struct iio_event_spec {
>>> unsigned long mask_shared_by_all;
>>> };
>>>
>>> +/*
>>> + * Format values in scan type
>>> + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
>>> + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
>>> + */
>>
>> We could make this proper kernel doc format with one comment per macro.
>
> Actually, a set of related #defines can be documented with a single
> comment. I see a few examples doing that in include/linux/gfp_types.h and
> include/linux/fpga/fpga-mgr.h
Fancy. Although, IDEs tend to be able to handle doc comments better
if they are not combined (i.e. getting the docs when you hold the
mouse over an identifier).
>
>
>>> +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
>>> +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
>>> +
>
^ permalink raw reply
* Re: [PATCH v7 1/3] dt-bindings: hwmon: Document the LTC4283 Swap Controller
From: Nuno Sá @ 2026-03-23 16:07 UTC (permalink / raw)
To: Guenter Roeck, nuno.sa
Cc: linux-gpio, linux-hwmon, devicetree, linux-doc, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet, Shuah Khan,
Linus Walleij, Bartosz Golaszewski
In-Reply-To: <821aafb4-d1a8-4611-addc-5bff4f1e187e@roeck-us.net>
On Mon, 2026-03-23 at 08:27 -0700, Guenter Roeck wrote:
> On 3/23/26 08:17, Nuno Sá wrote:
> > On Mon, 2026-03-23 at 07:33 -0700, Guenter Roeck wrote:
> > > [ ...]
> > > > > > + adi,pgio1-func:
> > > > > > + description: Configures the function of the PGIO1 pin.
> > > > > > + $ref: /schemas/types.yaml#/definitions/string
> > > > > > + enum: [inverted_power_good, power_good, gpio]
> > > > > > + default: inverted_power_good
> > > > > > +
> > > > > > + adi,pgio2-func:
> > > > > > + description: Configures the function of the PGIO2 pin.
> > > > > > + $ref: /schemas/types.yaml#/definitions/string
> > > > > > + enum: [inverted_power_good, power_good, gpio, active_current_limiting]
> > > > > > + default: inverted_power_good
> > > > > > +
> > > > > > + adi,pgio3-func:
> > > > > > + description: Configures the function of the PGIO3 pin.
> > > > > > + $ref: /schemas/types.yaml#/definitions/string
> > > > > > + enum: [inverted_power_good_input, power_good_input, gpio]
> > > > > > + default: inverted_power_good_input
> > > > > > +
> > > > > > + adi,pgio4-func:
> > > > > > + description: Configures the function of the PGIO4 pin.
> > > > > > + $ref: /schemas/types.yaml#/definitions/string
> > > > > > + enum: [inverted_external_fault, external_fault, gpio]
> > > > > > + default: inverted_external_fault
> > > > > > +
> > > > > > + adi,gpio-on-adio1:
> > > > > > + description: If set, the ADIO1 pin is used as a GPIO.
> > > > > > + type: boolean
> > > > > > +
> > > > > > + adi,gpio-on-adio2:
> > > > > > + description: If set, the ADIO2 pin is used as a GPIO.
> > > > > > + type: boolean
> > > > > > +
> > > > > > + adi,gpio-on-adio3:
> > > > > > + description: If set, the ADIO3 pin is used as a GPIO.
> > > > > > + type: boolean
> > > > > > +
> > > > > > + adi,gpio-on-adio4:
> > > > > > + description: If set, the ADIO4 pin is used as a GPIO.
> > > > > > + type: boolean
> > > > >
> > > > > Does this dependency block force a redundant specification of adi,pgio4-func?
> > > > > The default for adi,pgio4-func is inverted_external_fault, which means the
> > > > > default hardware state already supports external fault features.
> > > > > If a device tree legitimately omits adi,pgio4-func to rely on that default,
> > > > > will it fail schema validation here since the dependencies keyword strictly
> > > > > checks for the literal presence of properties without injecting defaults?
> > > >
> > > > Fair point. I guess it will fail but the alternative is to not have any constrain at all so
> > > > maybe worth it to be explicit in here?
> > > >
> > >
> > > I don't claim to understand how to define devicetree properties, but
> > >
> > > adi,pgio4-func = <"gpio">
> > >
> > > and
> > >
> > > adi,gpio-on-adio4;
> > >
> > > seem to be equivalent to me, and omitting the first property (because
> >
> > Not exactly. ADIO4 and PGIO4 are different pins and can be both configured
> > as GPIOs. ADIO is a boolean because they are either monitored by the ADC (default)
> > or configured as GPIOs. PGIOs can have additional configurations and hence the
> > enum.
> >
>
> Ah, I didn't realize the small "A" vs. "G" difference (and apparently
> I don't understand what the AI is complaining about ;-). Sorry for the noise.
>
My understanding about the AI complain is the below dependencies:
+ adi,external-fault-retry-enable:
+ - adi,pgio4-func
+ adi,external-fault-fet-off-enable:
+ - adi,pgio4-func
The default value (omitting the property) is a valid case to use any of the above two
flags but with the above, omitting the property and adding the flag should result in
an error when validating the binding (because of the dependency). That is why I replied
with
"Fair point. I guess it will fail but the alternative is to not have any constrain at all so
maybe worth it to be explicit in here?"
- Nuno Sá
^ permalink raw reply
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
From: Francesco Lavra @ 2026-03-23 16:04 UTC (permalink / raw)
To: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
In-Reply-To: <4723284d-1e18-4a13-9ec1-878220af257e@baylibre.com>
On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> On 3/17/26 10:04 AM, Francesco Lavra wrote:
> > This field is used to differentiate between signed and unsigned
> > integers.
> > A following commit will extend its use in order to add support for non-
> > integer scan elements; therefore, replace it with a union that contains
> > a
> > more generic 'format' field. This union will be dropped when all
> > drivers
> > are changed to use the format field.
> > Opportunistically replace character literals with symbolic constants
> > that
> > represent the set of allowed values for the format field.
> >
> > Signed-off-by: Francesco Lavra <flavra@baylibre.com>
> > ---
> > Documentation/driver-api/iio/buffers.rst | 4 ++--
> > include/linux/iio/iio.h | 17 +++++++++++++++--
> > 2 files changed, 17 insertions(+), 4 deletions(-)
> >
> > diff --git a/Documentation/driver-api/iio/buffers.rst
> > b/Documentation/driver-api/iio/buffers.rst
> > index 63f364e862d1..e16abaf826fe 100644
> > --- a/Documentation/driver-api/iio/buffers.rst
> > +++ b/Documentation/driver-api/iio/buffers.rst
> > @@ -78,7 +78,7 @@ fields in iio_chan_spec definition::
> > /* other members */
> > int scan_index
> > struct {
> > - char sign;
> > + char format;
> > u8 realbits;
> > u8 storagebits;
> > u8 shift;
> > @@ -98,7 +98,7 @@ following channel definition::
> > /* other stuff here */
> > .scan_index = 0,
> > .scan_type = {
> > - .sign = 's',
> > + .format = IIO_SCAN_FORMAT_SIGNED_INT,
> > .realbits = 12,
> > .storagebits = 16,
> > .shift = 4,
> > diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> > index a9ecff191bd9..d48a0ab01b8d 100644
> > --- a/include/linux/iio/iio.h
> > +++ b/include/linux/iio/iio.h
> > @@ -176,9 +176,19 @@ struct iio_event_spec {
> > unsigned long mask_shared_by_all;
> > };
> >
> > +/*
> > + * Format values in scan type
> > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> > + */
>
> We could make this proper kernel doc format with one comment per macro.
Actually, a set of related #defines can be documented with a single
comment. I see a few examples doing that in include/linux/gfp_types.h and
include/linux/fpga/fpga-mgr.h
> > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
> > +
^ 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