From: Sasha Levin <sashal@kernel.org>
To: linux-api@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-kbuild@vger.kernel.org, linux-kselftest@vger.kernel.org,
workflows@vger.kernel.org, tools@kernel.org, x86@kernel.org,
Thomas Gleixner <tglx@kernel.org>,
"Paul E. McKenney" <paulmck@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jonathan Corbet <corbet@lwn.net>,
Dmitry Vyukov <dvyukov@google.com>,
Randy Dunlap <rdunlap@infradead.org>,
Cyril Hrubis <chrubis@suse.cz>, Kees Cook <kees@kernel.org>,
Jake Edge <jake@lwn.net>,
David Laight <david.laight.linux@gmail.com>,
Askar Safin <safinaskar@zohomail.com>,
Gabriele Paoloni <gpaoloni@redhat.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Christian Brauner <brauner@kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Andrew Morton <akpm@linux-foundation.org>,
Masahiro Yamada <masahiroy@kernel.org>,
Shuah Khan <skhan@linuxfoundation.org>,
Ingo Molnar <mingo@redhat.com>, Arnd Bergmann <arnd@arndb.de>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 3/9] kernel/api: add debugfs interface for kernel API specifications
Date: Fri, 13 Mar 2026 11:09:13 -0400 [thread overview]
Message-ID: <20260313150928.2637368-4-sashal@kernel.org> (raw)
In-Reply-To: <20260313150928.2637368-1-sashal@kernel.org>
Add a debugfs interface to expose kernel API specifications at runtime.
This allows tools and users to query the complete API specifications
through the debugfs filesystem.
The interface provides:
- /sys/kernel/debug/kapi/list - lists all available API specifications
- /sys/kernel/debug/kapi/specs/<name> - detailed info for each API
Each specification file includes:
- Function name, version, and descriptions
- Execution context requirements and flags
- Parameter details with types, flags, and constraints
- Return value specifications and success conditions
- Error codes with descriptions and conditions
- Locking requirements and constraints
- Signal handling specifications
- Examples, notes, and deprecation status
This enables runtime introspection of kernel APIs for documentation
tools, static analyzers, and debugging purposes.
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
Documentation/dev-tools/kernel-api-spec.rst | 88 ++--
kernel/api/kapi_debugfs.c | 503 ++++++++++++++++++++
2 files changed, 534 insertions(+), 57 deletions(-)
create mode 100644 kernel/api/kapi_debugfs.c
diff --git a/Documentation/dev-tools/kernel-api-spec.rst b/Documentation/dev-tools/kernel-api-spec.rst
index 7c0c1694f1f4a..6ec6e65a1902a 100644
--- a/Documentation/dev-tools/kernel-api-spec.rst
+++ b/Documentation/dev-tools/kernel-api-spec.rst
@@ -56,16 +56,10 @@ The framework consists of several key components:
2. **DebugFS Interface** (``kernel/api/kapi_debugfs.c``)
- Runtime introspection via ``/sys/kernel/debug/kapi/``
- - JSON and XML export formats
- - Per-API detailed information
+ - Per-API detailed specification output
+ - List of all registered API specifications
-3. **IOCTL Support** (``kernel/api/ioctl_validation.c``)
-
- - Extended framework for IOCTL specifications
- - Automatic validation wrappers
- - Structure field validation
-
-4. **Specification Macros** (``include/linux/kernel_api_spec.h``)
+3. **Specification Macros** (``include/linux/kernel_api_spec.h``)
- Declarative macros for API documentation
- Type-safe parameter specifications
@@ -186,8 +180,8 @@ Runtime validation is controlled by kernel configuration:
2. Enable ``CONFIG_KAPI_RUNTIME_CHECKS`` for runtime validation
3. Optionally enable ``CONFIG_KAPI_SPEC_DEBUGFS`` for debugfs interface
-Validation Modes
-----------------
+Validation Behavior
+-------------------
When ``CONFIG_KAPI_RUNTIME_CHECKS`` is enabled, all registered API specifications
are validated automatically at call time. The framework checks parameter constraints,
@@ -225,55 +219,39 @@ Directory Structure
::
/sys/kernel/debug/kapi/
- ├── apis/ # All registered APIs
- │ ├── kmalloc/
- │ │ ├── specification # Human-readable spec
- │ │ ├── json # JSON format
- │ │ └── xml # XML format
- │ └── open/
- │ └── ...
- ├── summary # Overview of all APIs
- ├── validation/ # Validation controls
- │ ├── enabled # Global enable/disable
- │ ├── level # Validation level
- │ └── stats # Validation statistics
- └── export/ # Bulk export options
- ├── all.json # All specs in JSON
- └── all.xml # All specs in XML
+ ├── list # Overview of all registered API specs
+ └── specs/ # Per-API specification files
+ ├── sys_open # Human-readable spec for sys_open
+ ├── sys_close # Human-readable spec for sys_close
+ ├── sys_read # Human-readable spec for sys_read
+ └── sys_write # Human-readable spec for sys_write
Usage Examples
--------------
-Query specific API::
-
- $ cat /sys/kernel/debug/kapi/apis/kmalloc/specification
- API: kmalloc
- Version: 3.0
- Description: Allocate kernel memory
+List all available API specifications::
- Parameters:
- [0] size (size_t, in): Number of bytes to allocate
- Range: 0 - 4194304
- [1] flags (flags, in): Allocation flags (GFP_*)
- Mask: 0x1ffffff
+ $ cat /sys/kernel/debug/kapi/list
+ Available Kernel API Specifications
+ ===================================
- Returns: pointer - Pointer to allocated memory or NULL
+ sys_open - Open or create a file
+ sys_close - Close a file descriptor
+ sys_read - Read data from a file descriptor
+ sys_write - Write data to a file descriptor
- Errors:
- ENOMEM: Out of memory
+ Total: 4 specifications
- Context: process, softirq, hardirq
-
- Side Effects:
- - Allocates memory from kernel heap
-
-Export all specifications::
-
- $ cat /sys/kernel/debug/kapi/export/all.json > kernel-apis.json
+Query specific API::
-Enable validation for specific API::
+ $ cat /sys/kernel/debug/kapi/specs/sys_open
+ Kernel API Specification
+ ========================
- $ echo 1 > /sys/kernel/debug/kapi/apis/kmalloc/validate
+ Name: sys_open
+ Version: 1
+ Description: Open or create a file
+ ...
Performance Considerations
==========================
@@ -304,11 +282,8 @@ Optimization Strategies
1. **Compile-time optimization**: When validation is disabled, all
validation code is optimized away by the compiler.
-2. **Selective validation**: Enable validation only for specific APIs
- or subsystems under test.
-
-3. **Caching**: The framework caches validation results for repeated
- calls with identical parameters.
+2. **Selective enablement**: Enable ``CONFIG_KAPI_RUNTIME_CHECKS``
+ only in development/testing kernels, not in production.
Documentation Generation
------------------------
@@ -414,10 +389,9 @@ Common Issues
Debug Options
-------------
-Enable verbose debugging::
+Enable verbose kernel logging to see KAPI validation messages::
echo 8 > /proc/sys/kernel/printk
- echo 1 > /sys/kernel/debug/kapi/debug/verbose
Future Directions
=================
diff --git a/kernel/api/kapi_debugfs.c b/kernel/api/kapi_debugfs.c
new file mode 100644
index 0000000000000..be187646ee768
--- /dev/null
+++ b/kernel/api/kapi_debugfs.c
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kernel API specification debugfs interface
+ *
+ * This provides a debugfs interface to expose kernel API specifications
+ * at runtime, allowing tools and users to query the complete API specs.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/kernel_api_spec.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+/* External symbols for kernel API spec section */
+extern struct kernel_api_spec __start_kapi_specs[];
+extern struct kernel_api_spec __stop_kapi_specs[];
+
+static struct dentry *kapi_debugfs_root;
+
+/* Helper function to print parameter type as string */
+static const char * const param_type_names[] = {
+ [KAPI_TYPE_VOID] = "void",
+ [KAPI_TYPE_INT] = "int",
+ [KAPI_TYPE_UINT] = "uint",
+ [KAPI_TYPE_PTR] = "ptr",
+ [KAPI_TYPE_STRUCT] = "struct",
+ [KAPI_TYPE_UNION] = "union",
+ [KAPI_TYPE_ARRAY] = "array",
+ [KAPI_TYPE_FD] = "fd",
+ [KAPI_TYPE_ENUM] = "enum",
+ [KAPI_TYPE_USER_PTR] = "user_ptr",
+ [KAPI_TYPE_PATH] = "path",
+ [KAPI_TYPE_FUNC_PTR] = "func_ptr",
+ [KAPI_TYPE_CUSTOM] = "custom",
+};
+
+static const char *param_type_str(enum kapi_param_type type)
+{
+ if (type < ARRAY_SIZE(param_type_names) && param_type_names[type])
+ return param_type_names[type];
+ return "unknown";
+}
+
+/* Helper to print parameter flags */
+static void print_param_flags(struct seq_file *m, u32 flags)
+{
+ seq_puts(m, " flags: ");
+ if ((flags & KAPI_PARAM_INOUT) == KAPI_PARAM_INOUT)
+ seq_puts(m, "INOUT ");
+ else if (flags & KAPI_PARAM_IN)
+ seq_puts(m, "IN ");
+ else if (flags & KAPI_PARAM_OUT)
+ seq_puts(m, "OUT ");
+ if (flags & KAPI_PARAM_OPTIONAL)
+ seq_puts(m, "OPTIONAL ");
+ if (flags & KAPI_PARAM_CONST)
+ seq_puts(m, "CONST ");
+ if (flags & KAPI_PARAM_USER)
+ seq_puts(m, "USER ");
+ if (flags & KAPI_PARAM_VOLATILE)
+ seq_puts(m, "VOLATILE ");
+ if (flags & KAPI_PARAM_DMA)
+ seq_puts(m, "DMA ");
+ if (flags & KAPI_PARAM_ALIGNED)
+ seq_puts(m, "ALIGNED ");
+ seq_puts(m, "\n");
+}
+
+/* Helper to print context flags */
+static void print_context_flags(struct seq_file *m, u32 flags)
+{
+ seq_puts(m, "Context flags: ");
+ if (flags & KAPI_CTX_PROCESS)
+ seq_puts(m, "PROCESS ");
+ if (flags & KAPI_CTX_HARDIRQ)
+ seq_puts(m, "HARDIRQ ");
+ if (flags & KAPI_CTX_SOFTIRQ)
+ seq_puts(m, "SOFTIRQ ");
+ if (flags & KAPI_CTX_NMI)
+ seq_puts(m, "NMI ");
+ if (flags & KAPI_CTX_SLEEPABLE)
+ seq_puts(m, "SLEEPABLE ");
+ if (flags & KAPI_CTX_ATOMIC)
+ seq_puts(m, "ATOMIC ");
+ if (flags & KAPI_CTX_PREEMPT_DISABLED)
+ seq_puts(m, "PREEMPT_DISABLED ");
+ if (flags & KAPI_CTX_IRQ_DISABLED)
+ seq_puts(m, "IRQ_DISABLED ");
+ seq_puts(m, "\n");
+}
+
+/* Show function for individual API spec */
+static int kapi_spec_show(struct seq_file *m, void *v)
+{
+ struct kernel_api_spec *spec = m->private;
+ int i;
+
+ seq_puts(m, "Kernel API Specification\n");
+ seq_puts(m, "========================\n\n");
+
+ /* Basic info */
+ seq_printf(m, "Name: %s\n", spec->name);
+ seq_printf(m, "Version: %u\n", spec->version);
+ seq_printf(m, "Description: %s\n", spec->description);
+ if (strnlen(spec->long_description, sizeof(spec->long_description)) > 0)
+ seq_printf(m, "Long description: %.*s\n",
+ (int)sizeof(spec->long_description), spec->long_description);
+
+ /* Context */
+ print_context_flags(m, spec->context_flags);
+ seq_puts(m, "\n");
+
+ /* Parameters */
+ if (spec->param_count > 0) {
+ seq_printf(m, "Parameters (%u):\n", spec->param_count);
+ for (i = 0; i < spec->param_count && i < KAPI_MAX_PARAMS; i++) {
+ struct kapi_param_spec *param = &spec->params[i];
+ seq_printf(m, " [%d] %s:\n", i, param->name);
+ seq_printf(m, " type: %s (%s)\n",
+ param_type_str(param->type), param->type_name);
+ print_param_flags(m, param->flags);
+ if (strnlen(param->description, sizeof(param->description)) > 0)
+ seq_printf(m, " description: %.*s\n",
+ (int)sizeof(param->description), param->description);
+ if (param->size > 0)
+ seq_printf(m, " size: %zu\n", param->size);
+ if (param->alignment > 0)
+ seq_printf(m, " alignment: %zu\n", param->alignment);
+
+ /* Print constraints if any */
+ if (param->constraint_type != KAPI_CONSTRAINT_NONE) {
+ seq_puts(m, " constraints:\n");
+ switch (param->constraint_type) {
+ case KAPI_CONSTRAINT_RANGE:
+ seq_puts(m, " type: range\n");
+ seq_printf(m, " min: %lld\n", param->min_value);
+ seq_printf(m, " max: %lld\n", param->max_value);
+ break;
+ case KAPI_CONSTRAINT_MASK:
+ seq_puts(m, " type: mask\n");
+ seq_printf(m, " valid_bits: 0x%llx\n", param->valid_mask);
+ break;
+ case KAPI_CONSTRAINT_ENUM:
+ seq_puts(m, " type: enum\n");
+ seq_printf(m, " count: %u\n", param->enum_count);
+ break;
+ case KAPI_CONSTRAINT_USER_STRING:
+ seq_puts(m, " type: user_string\n");
+ seq_printf(m, " min_len: %lld\n", param->min_value);
+ seq_printf(m, " max_len: %lld\n", param->max_value);
+ break;
+ case KAPI_CONSTRAINT_USER_PATH:
+ seq_puts(m, " type: user_path\n");
+ seq_puts(m, " max_len: PATH_MAX (4096)\n");
+ break;
+ case KAPI_CONSTRAINT_USER_PTR:
+ seq_puts(m, " type: user_ptr\n");
+ seq_printf(m, " size: %zu bytes\n", param->size);
+ break;
+ case KAPI_CONSTRAINT_ALIGNMENT:
+ seq_puts(m, " type: alignment\n");
+ seq_printf(m, " alignment: %zu\n", param->alignment);
+ break;
+ case KAPI_CONSTRAINT_POWER_OF_TWO:
+ seq_puts(m, " type: power_of_two\n");
+ break;
+ case KAPI_CONSTRAINT_PAGE_ALIGNED:
+ seq_puts(m, " type: page_aligned\n");
+ break;
+ case KAPI_CONSTRAINT_NONZERO:
+ seq_puts(m, " type: nonzero\n");
+ break;
+ case KAPI_CONSTRAINT_CUSTOM:
+ seq_puts(m, " type: custom\n");
+ if (strnlen(param->constraints, sizeof(param->constraints)) > 0)
+ seq_printf(m, " description: %.*s\n",
+ (int)sizeof(param->constraints),
+ param->constraints);
+ break;
+ default:
+ break;
+ }
+ }
+ seq_puts(m, "\n");
+ }
+ }
+
+ /* Return value */
+ seq_puts(m, "Return value:\n");
+ seq_printf(m, " type: %s\n", spec->return_spec.type_name);
+ if (strnlen(spec->return_spec.description, sizeof(spec->return_spec.description)) > 0)
+ seq_printf(m, " description: %.*s\n",
+ (int)sizeof(spec->return_spec.description),
+ spec->return_spec.description);
+
+ switch (spec->return_spec.check_type) {
+ case KAPI_RETURN_EXACT:
+ seq_printf(m, " success: == %lld\n", spec->return_spec.success_value);
+ break;
+ case KAPI_RETURN_RANGE:
+ seq_printf(m, " success: [%lld, %lld]\n",
+ spec->return_spec.success_min,
+ spec->return_spec.success_max);
+ break;
+ case KAPI_RETURN_FD:
+ seq_puts(m, " success: valid file descriptor (>= 0)\n");
+ break;
+ case KAPI_RETURN_ERROR_CHECK:
+ seq_puts(m, " success: error check\n");
+ break;
+ case KAPI_RETURN_CUSTOM:
+ seq_puts(m, " success: custom check\n");
+ break;
+ default:
+ break;
+ }
+ seq_puts(m, "\n");
+
+ /* Errors */
+ if (spec->error_count > 0) {
+ seq_printf(m, "Errors (%u):\n", spec->error_count);
+ for (i = 0; i < spec->error_count && i < KAPI_MAX_ERRORS; i++) {
+ struct kapi_error_spec *err = &spec->errors[i];
+ seq_printf(m, " %s (%d): %s\n",
+ err->name, err->error_code, err->description);
+ if (strnlen(err->condition, sizeof(err->condition)) > 0)
+ seq_printf(m, " condition: %s\n", err->condition);
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* Locks */
+ if (spec->lock_count > 0) {
+ seq_printf(m, "Locks (%u):\n", spec->lock_count);
+ for (i = 0; i < spec->lock_count && i < KAPI_MAX_CONSTRAINTS; i++) {
+ struct kapi_lock_spec *lock = &spec->locks[i];
+ const char *type_str, *scope_str;
+ switch (lock->lock_type) {
+ case KAPI_LOCK_MUTEX:
+ type_str = "mutex";
+ break;
+ case KAPI_LOCK_SPINLOCK:
+ type_str = "spinlock";
+ break;
+ case KAPI_LOCK_RWLOCK:
+ type_str = "rwlock";
+ break;
+ case KAPI_LOCK_SEMAPHORE:
+ type_str = "semaphore";
+ break;
+ case KAPI_LOCK_RCU:
+ type_str = "rcu";
+ break;
+ case KAPI_LOCK_SEQLOCK:
+ type_str = "seqlock";
+ break;
+ default:
+ type_str = "unknown";
+ break;
+ }
+ switch (lock->scope) {
+ case KAPI_LOCK_INTERNAL:
+ scope_str = "acquired and released";
+ break;
+ case KAPI_LOCK_ACQUIRES:
+ scope_str = "acquired (not released)";
+ break;
+ case KAPI_LOCK_RELEASES:
+ scope_str = "released (held on entry)";
+ break;
+ case KAPI_LOCK_CALLER_HELD:
+ scope_str = "held by caller";
+ break;
+ default:
+ scope_str = "unknown";
+ break;
+ }
+ seq_printf(m, " %s (%s): %s\n",
+ lock->lock_name, type_str, lock->description);
+ seq_printf(m, " scope: %s\n", scope_str);
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* Constraints */
+ if (spec->constraint_count > 0) {
+ seq_printf(m, "Additional constraints (%u):\n", spec->constraint_count);
+ for (i = 0; i < spec->constraint_count && i < KAPI_MAX_CONSTRAINTS; i++) {
+ struct kapi_constraint_spec *cons = &spec->constraints[i];
+
+ seq_printf(m, " - %s", cons->name);
+ if (cons->description[0])
+ seq_printf(m, ": %s", cons->description);
+ seq_puts(m, "\n");
+ if (cons->expression[0])
+ seq_printf(m, " expression: %s\n", cons->expression);
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* Signals */
+ if (spec->signal_count > 0) {
+ seq_printf(m, "Signal handling (%u):\n", spec->signal_count);
+ for (i = 0; i < spec->signal_count && i < KAPI_MAX_SIGNALS; i++) {
+ struct kapi_signal_spec *sig = &spec->signals[i];
+ seq_printf(m, " %s (%d):\n", sig->signal_name, sig->signal_num);
+ seq_puts(m, " direction: ");
+ if (sig->direction & KAPI_SIGNAL_SEND)
+ seq_puts(m, "send ");
+ if (sig->direction & KAPI_SIGNAL_RECEIVE)
+ seq_puts(m, "receive ");
+ if (sig->direction & KAPI_SIGNAL_HANDLE)
+ seq_puts(m, "handle ");
+ if (sig->direction & KAPI_SIGNAL_BLOCK)
+ seq_puts(m, "block ");
+ if (sig->direction & KAPI_SIGNAL_IGNORE)
+ seq_puts(m, "ignore ");
+ seq_puts(m, "\n");
+ seq_puts(m, " action: ");
+ switch (sig->action) {
+ case KAPI_SIGNAL_ACTION_DEFAULT:
+ seq_puts(m, "default");
+ break;
+ case KAPI_SIGNAL_ACTION_TERMINATE:
+ seq_puts(m, "terminate");
+ break;
+ case KAPI_SIGNAL_ACTION_COREDUMP:
+ seq_puts(m, "coredump");
+ break;
+ case KAPI_SIGNAL_ACTION_STOP:
+ seq_puts(m, "stop");
+ break;
+ case KAPI_SIGNAL_ACTION_CONTINUE:
+ seq_puts(m, "continue");
+ break;
+ case KAPI_SIGNAL_ACTION_CUSTOM:
+ seq_puts(m, "custom");
+ break;
+ case KAPI_SIGNAL_ACTION_RETURN:
+ seq_puts(m, "return");
+ break;
+ case KAPI_SIGNAL_ACTION_RESTART:
+ seq_puts(m, "restart");
+ break;
+ default:
+ seq_puts(m, "unknown");
+ break;
+ }
+ seq_puts(m, "\n");
+ if (strnlen(sig->description, sizeof(sig->description)) > 0)
+ seq_printf(m, " description: %.*s\n",
+ (int)sizeof(sig->description), sig->description);
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* Side effects */
+ if (spec->side_effect_count > 0) {
+ seq_printf(m, "Side effects (%u):\n", spec->side_effect_count);
+ for (i = 0; i < spec->side_effect_count && i < KAPI_MAX_SIDE_EFFECTS; i++) {
+ const struct kapi_side_effect *eff = &spec->side_effects[i];
+
+ seq_printf(m, " - %.*s",
+ (int)sizeof(eff->target), eff->target);
+ if (strnlen(eff->description, sizeof(eff->description)) > 0)
+ seq_printf(m, ": %.*s",
+ (int)sizeof(eff->description), eff->description);
+ if (eff->reversible)
+ seq_puts(m, " (reversible)");
+ seq_puts(m, "\n");
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* State transitions */
+ if (spec->state_trans_count > 0) {
+ seq_printf(m, "State transitions (%u):\n", spec->state_trans_count);
+ for (i = 0; i < spec->state_trans_count && i < KAPI_MAX_STATE_TRANS; i++) {
+ const struct kapi_state_transition *trans = &spec->state_transitions[i];
+
+ seq_printf(m, " %.*s: %.*s -> %.*s\n",
+ (int)sizeof(trans->object), trans->object,
+ (int)sizeof(trans->from_state), trans->from_state,
+ (int)sizeof(trans->to_state), trans->to_state);
+ if (strnlen(trans->description, sizeof(trans->description)) > 0)
+ seq_printf(m, " %.*s\n",
+ (int)sizeof(trans->description), trans->description);
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* Capabilities */
+ if (spec->capability_count > 0) {
+ seq_printf(m, "Capabilities (%u):\n", spec->capability_count);
+ for (i = 0; i < spec->capability_count && i < KAPI_MAX_CAPABILITIES; i++) {
+ const struct kapi_capability_spec *cap = &spec->capabilities[i];
+
+ seq_printf(m, " %.*s (%d):\n",
+ (int)sizeof(cap->cap_name), cap->cap_name,
+ cap->capability);
+ if (strnlen(cap->allows, sizeof(cap->allows)) > 0)
+ seq_printf(m, " allows: %.*s\n",
+ (int)sizeof(cap->allows), cap->allows);
+ if (strnlen(cap->without_cap, sizeof(cap->without_cap)) > 0)
+ seq_printf(m, " without: %.*s\n",
+ (int)sizeof(cap->without_cap), cap->without_cap);
+ }
+ seq_puts(m, "\n");
+ }
+
+ /* Additional info */
+ if (strnlen(spec->examples, sizeof(spec->examples)) > 0) {
+ seq_printf(m, "Examples:\n%.*s\n\n",
+ (int)sizeof(spec->examples), spec->examples);
+ }
+ if (strnlen(spec->notes, sizeof(spec->notes)) > 0) {
+ seq_printf(m, "Notes:\n%.*s\n\n",
+ (int)sizeof(spec->notes), spec->notes);
+ }
+ if (strnlen(spec->since_version, sizeof(spec->since_version)) > 0) {
+ seq_printf(m, "Since: %.*s\n",
+ (int)sizeof(spec->since_version), spec->since_version);
+ }
+
+ return 0;
+}
+
+static int kapi_spec_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, kapi_spec_show, inode->i_private);
+}
+
+static const struct file_operations kapi_spec_fops = {
+ .open = kapi_spec_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Show all available API specs.
+ *
+ * Note: This only iterates the static .kapi_specs section. Specs registered
+ * dynamically via kapi_register_spec() are not included in this listing
+ * or in the per-spec debugfs files.
+ */
+static int kapi_list_show(struct seq_file *m, void *v)
+{
+ struct kernel_api_spec *spec;
+ int count = 0;
+
+ seq_puts(m, "Available Kernel API Specifications\n");
+ seq_puts(m, "===================================\n\n");
+
+ for (spec = __start_kapi_specs; spec < __stop_kapi_specs; spec++) {
+ seq_printf(m, "%s - %s\n", spec->name, spec->description);
+ count++;
+ }
+
+ seq_printf(m, "\nTotal: %d specifications\n", count);
+ return 0;
+}
+
+static int kapi_list_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, kapi_list_show, NULL);
+}
+
+static const struct file_operations kapi_list_fops = {
+ .open = kapi_list_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init kapi_debugfs_init(void)
+{
+ struct kernel_api_spec *spec;
+ struct dentry *spec_dir;
+
+ /* Create main directory */
+ kapi_debugfs_root = debugfs_create_dir("kapi", NULL);
+
+ /* Create list file */
+ debugfs_create_file("list", 0444, kapi_debugfs_root, NULL, &kapi_list_fops);
+
+ /* Create specs subdirectory */
+ spec_dir = debugfs_create_dir("specs", kapi_debugfs_root);
+
+ /* Create a file for each API spec */
+ for (spec = __start_kapi_specs; spec < __stop_kapi_specs; spec++) {
+ debugfs_create_file(spec->name, 0444, spec_dir, spec, &kapi_spec_fops);
+ }
+
+ pr_info("Kernel API debugfs interface initialized\n");
+ return 0;
+}
+
+/* Initialize as part of kernel, not as a module */
+fs_initcall(kapi_debugfs_init);
--
2.51.0
next prev parent reply other threads:[~2026-03-13 15:09 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-13 15:09 [PATCH 0/9] Kernel API Specification Framework Sasha Levin
2026-03-13 15:09 ` [PATCH 1/9] kernel/api: introduce kernel API specification framework Sasha Levin
2026-03-17 17:49 ` Jonathan Corbet
2026-03-18 6:00 ` Mauro Carvalho Chehab
2026-03-18 14:53 ` Sasha Levin
2026-03-18 14:30 ` Sasha Levin
2026-03-18 16:50 ` Jonathan Corbet
2026-03-18 14:32 ` Sasha Levin
2026-03-18 16:51 ` Jonathan Corbet
2026-03-13 15:09 ` [PATCH 2/9] kernel/api: enable kerneldoc-based API specifications Sasha Levin
2026-03-13 15:09 ` Sasha Levin [this message]
2026-03-13 15:32 ` [PATCH 3/9] kernel/api: add debugfs interface for kernel " Greg Kroah-Hartman
2026-03-13 16:27 ` Sasha Levin
2026-03-13 15:09 ` [PATCH 4/9] tools/kapi: Add kernel API specification extraction tool Sasha Levin
2026-03-13 15:09 ` [PATCH 5/9] kernel/api: add API specification for sys_open Sasha Levin
2026-03-13 15:33 ` Greg Kroah-Hartman
2026-03-13 16:42 ` Sasha Levin
2026-03-17 18:37 ` Jonathan Corbet
2026-03-18 14:12 ` Sasha Levin
2026-03-18 14:16 ` Jonathan Corbet
2026-03-13 15:09 ` [PATCH 6/9] kernel/api: add API specification for sys_close Sasha Levin
2026-03-13 15:49 ` Greg Kroah-Hartman
2026-03-13 16:46 ` Sasha Levin
2026-03-13 15:52 ` Greg Kroah-Hartman
2026-03-13 16:55 ` Sasha Levin
2026-03-13 15:09 ` [PATCH 7/9] kernel/api: add API specification for sys_read Sasha Levin
2026-03-13 15:09 ` [PATCH 8/9] kernel/api: add API specification for sys_write Sasha Levin
2026-03-13 15:09 ` [PATCH 9/9] kernel/api: add runtime verification selftest Sasha Levin
2026-03-14 18:18 ` [PATCH 0/9] Kernel API Specification Framework Jakub Kicinski
2026-03-14 22:44 ` David Laight
2026-03-15 6:46 ` Sasha Levin
2026-03-15 6:36 ` Sasha Levin
2026-03-18 6:24 ` Mauro Carvalho Chehab
2026-03-18 14:14 ` Sasha Levin
2026-04-08 12:05 ` Geert Uytterhoeven
2026-03-16 7:05 ` Dmitry Vyukov
2026-03-16 22:57 ` Jakub Kicinski
2026-03-16 23:29 ` Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260313150928.2637368-4-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=arnd@arndb.de \
--cc=brauner@kernel.org \
--cc=chrubis@suse.cz \
--cc=corbet@lwn.net \
--cc=david.laight.linux@gmail.com \
--cc=dvyukov@google.com \
--cc=gpaoloni@redhat.com \
--cc=gregkh@linuxfoundation.org \
--cc=jake@lwn.net \
--cc=kees@kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=mchehab@kernel.org \
--cc=mingo@redhat.com \
--cc=paulmck@kernel.org \
--cc=rdunlap@infradead.org \
--cc=safinaskar@zohomail.com \
--cc=skhan@linuxfoundation.org \
--cc=tglx@kernel.org \
--cc=tools@kernel.org \
--cc=viro@zeniv.linux.org.uk \
--cc=workflows@vger.kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.