Linux userland API discussions
 help / color / mirror / Atom feed
From: Jiri Pirko <jiri@resnulli.us>
To: linux-coco@lists.linux.dev
Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	x86@kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org,
	jgg@ziepe.ca, david.quigley@intel.com, lukas@wunner.de,
	ksinyuk@kernel.org, rodrigo.vivi@intel.com,
	cedric.xing@intel.com, sameo@meta.com, drdeeglaze@gmail.com,
	James.Bottomley@HansenPartnership.com, aik@amd.com,
	jpiotrowski@nvidia.com, qinkun@google.com, pgonda@google.com,
	jic23@kernel.org, alistair.francis@wdc.com, ankita@nvidia.com,
	suzuki.poulose@arm.com, kas@kernel.org,
	rick.p.edgecombe@intel.com, elena.reshetova@intel.com,
	dave.hansen@linux.intel.com,
	sathyanarayanan.kuppuswamy@linux.intel.com, peter.fang@intel.com
Subject: [PATCH RFC 02/20] ctlv: Add the UAPI wire format and family API
Date: Thu, 15 Oct 2026 16:50:35 +0200	[thread overview]
Message-ID: <20261015145053.3664509-3-jiri@resnulli.us> (raw)
In-Reply-To: <20261015145053.3664509-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Define CTLV's common TLV transport, ioctl, event records, identifiers
and limits. Add the in-kernel API used by family implementations and
generated code.

Assisted-by: Cursor: GPT-5.6 Sol
Assisted-by: Cursor: Claude Opus 5.5
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 .../userspace-api/ioctl/ioctl-number.rst      |   2 +
 MAINTAINERS                                   |   2 +
 include/linux/ctlv.h                          |  55 +++
 include/linux/ctlv_family.h                   | 316 ++++++++++++++++++
 include/uapi/linux/ctlv.h                     | 183 ++++++++++
 5 files changed, 558 insertions(+)
 create mode 100644 include/linux/ctlv.h
 create mode 100644 include/linux/ctlv_family.h
 create mode 100644 include/uapi/linux/ctlv.h

diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 2fc53093752d..e545669c773c 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -386,6 +386,8 @@ Code  Seq#    Include File                                             Comments
                                                                        <mailto:linux-hyperv@vger.kernel.org>
 0xBA  00-0F  uapi/linux/liveupdate.h                                   Pasha Tatashin
                                                                        <mailto:pasha.tatashin@soleen.com>
+0xBB  00-0F  uapi/linux/ctlv.h                                         CTLV
+                                                                       <mailto:jiri@resnulli.us>
 0xC0  00-0F  linux/usb/iowarrior.h
 0xCA  00-0F  uapi/misc/cxl.h                                           Dead since 6.15
 0xCA  10-2F  uapi/misc/ocxl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index a8508fbae37d..8ab0d6a7a2fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7006,6 +7006,8 @@ M:	Jiri Pirko <jiri@resnulli.us>
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 F:	Documentation/ctlv/
+F:	include/linux/ctlv*.h
+F:	include/uapi/linux/ctlv*.h
 F:	tools/ctlv/
 
 CTU CAN FD DRIVER
diff --git a/include/linux/ctlv.h b/include/linux/ctlv.h
new file mode 100644
index 000000000000..addb893f4b8d
--- /dev/null
+++ b/include/linux/ctlv.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES
+ *
+ * CTLV family API.
+ */
+#ifndef _LINUX_CTLV_H
+#define _LINUX_CTLV_H
+
+#include <linux/types.h>
+
+#include <uapi/linux/ctlv.h>
+
+struct ctlv_device;
+struct ctlv_family;
+struct ctlv_msg;
+struct ctlv_op_ctx;
+struct ctlv_schema_tree;
+
+/**
+ * struct ctlv_cursor - One attr position in one message.
+ * @msg: the message this position is in, core-private bookkeeping
+ * @attr: the attr itself, or NULL when a lookup found nothing
+ * @parent: reading, the nest containing @attr, NULL at the root
+ * @up: writing, cursor of the nest containing @attr, NULL at the root. The
+ *	chain of them is the open-nest stack
+ * @start: writing, where @attr begins in the message. An append reaches what
+ *	it lengthens through the buffer rather than through @attr, that buffer
+ *	being the core's own
+ * @tree: schema tree the node belongs to, which is a fill's own tree for an
+ *	attr that arrived through one
+ * @node: index of the node within @tree
+ * @depth: nesting levels above this position, the root being zero
+ * @index_nest_scope: schema scope used to read members of the physical nest
+ * @index_scope: core-private schema scope containing this attr
+ *
+ * Fixed-size, so family code can put a child cursor on the stack. The members
+ * belong to the core: a family reaches a message through what was generated
+ * for the op it answers. One direction at a time, a helper of the other
+ * direction refusing the cursor.
+ */
+struct ctlv_cursor {
+	struct ctlv_msg *msg;
+	const struct ctlv_attr *attr;
+	const struct ctlv_attr *parent;
+	struct ctlv_cursor *up;
+	size_t start;
+	const struct ctlv_schema_tree *tree;
+	u32 node;
+	u32 depth;
+	u32 index_nest_scope;
+	u32 index_scope;
+};
+
+#endif /* _LINUX_CTLV_H */
diff --git a/include/linux/ctlv_family.h b/include/linux/ctlv_family.h
new file mode 100644
index 000000000000..1ae4d3a536f7
--- /dev/null
+++ b/include/linux/ctlv_family.h
@@ -0,0 +1,316 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES
+ *
+ * CTLV family metadata and generated-code support.
+ */
+#ifndef _LINUX_CTLV_FAMILY_H
+#define _LINUX_CTLV_FAMILY_H
+
+#include <linux/ctlv.h>
+#include <linux/gfp_types.h>
+#include <linux/kobject.h>
+#include <linux/types.h>
+
+#include <uapi/linux/ctlv.h>
+
+/* op-schema-get needs one level to describe the declared schema. */
+#define CTLV_MAX_DECLARED_NEST_DEPTH (CTLV_MAX_NEST_DEPTH - 1)
+
+struct ctlv_node_schema {
+	u64 attr_id;
+	u8 kind;
+	u8 unit;
+	s8 scale;
+	bool reenters;
+	u32 max_occurrences;
+	u32 first_child;
+	u32 children_count;
+	u32 required_children_count;
+	union {
+		struct {
+			u64 min;
+			u64 max;
+		} range;
+		u64 flags_mask;
+		struct {
+			u32 min_len;
+			u32 max_len;
+		} length;
+		struct {
+			u64 max_len;
+			u32 alignment;
+			u16 backings;
+			u8 direction;
+		} blob;
+	};
+};
+
+#define CTLV_NODE_SCHEMA_UNLIMITED 0
+
+#define __CTLV_NODE_SCHEMA(_attr, _kind, _occurrences, ...)	\
+	{ .attr_id = (_attr), .kind = (_kind),			\
+	  .max_occurrences = (_occurrences), __VA_ARGS__ }
+
+#define __CTLV_NODE_SCHEMA_CHILDREN(_first, _count, _required)	\
+	.first_child = (_first), .children_count = (_count),	\
+	.required_children_count = (_required)
+
+#define CTLV_NODE_SCHEMA_ROOT(_first, _count, _required)	\
+	__CTLV_NODE_SCHEMA(CTLV_ATTR_ROOT, CTLV_SCHEMA_NEST, 1,	\
+			   __CTLV_NODE_SCHEMA_CHILDREN(_first, _count, _required))
+
+#define CTLV_NODE_SCHEMA_NEST(_attr, _occurrences, _first, _count, _required) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_NEST, _occurrences,	\
+			   __CTLV_NODE_SCHEMA_CHILDREN(_first, _count, _required))
+
+#define CTLV_NODE_SCHEMA_NEST_REENTERS(_attr, _occurrences, _first, _count, _required) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_NEST, _occurrences,	\
+			   .reenters = true,				\
+			   __CTLV_NODE_SCHEMA_CHILDREN(_first, _count, _required))
+
+#define CTLV_NODE_SCHEMA_UINT(_attr, _occurrences, _min, _max)	\
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_UINT, _occurrences,	\
+			   .range = { .min = (_min), .max = (_max) })
+
+#define CTLV_NODE_SCHEMA_UINT_UNIT(_attr, _occurrences, _min, _max, _unit, _scale) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_UINT, _occurrences,	\
+			   .range = { .min = (_min), .max = (_max) },	\
+			   .unit = (_unit), .scale = (_scale))
+
+#define CTLV_NODE_SCHEMA_SINT(_attr, _occurrences, _min, _max)	\
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_SINT, _occurrences,	\
+			   .range = { .min = (_min), .max = (_max) })
+
+#define CTLV_NODE_SCHEMA_SINT_UNIT(_attr, _occurrences, _min, _max, _unit, _scale) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_SINT, _occurrences,	\
+			   .range = { .min = (_min), .max = (_max) },	\
+			   .unit = (_unit), .scale = (_scale))
+
+#define CTLV_NODE_SCHEMA_ENUM(_attr, _occurrences, _max)	\
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_ENUM, _occurrences,	\
+			   .range = { .min = 1, .max = (_max) })
+
+#define CTLV_NODE_SCHEMA_FLAGS(_attr, _occurrences, _mask)	\
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_FLAGS, _occurrences,	\
+			   .flags_mask = (_mask))
+
+#define CTLV_NODE_SCHEMA_BOOL(_attr, _occurrences)		\
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_BOOL, _occurrences)
+
+#define CTLV_NODE_SCHEMA_STRING(_attr, _occurrences, _min, _max) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_STRING, _occurrences,	\
+			   .length = { .min_len = (_min), .max_len = (_max) })
+
+#define CTLV_NODE_SCHEMA_BINARY(_attr, _occurrences, _min, _max) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_BINARY, _occurrences,	\
+			   .length = { .min_len = (_min), .max_len = (_max) })
+
+#define CTLV_NODE_SCHEMA_BLOB(_attr, _occurrences, _max, _alignment, _backings, _dir) \
+	__CTLV_NODE_SCHEMA(_attr, CTLV_SCHEMA_BLOB, _occurrences,	\
+			   .blob = { .max_len = (_max),			\
+				     .alignment = (_alignment),		\
+				     .backings = (_backings),		\
+				     .direction = (_dir) })
+
+struct ctlv_stub_schema {
+	u16 family_id;
+	u32 set_id;
+	u32 node;
+	bool optional;
+};
+
+#define __CTLV_STUB_SCHEMA(_family, _set, _node, _optional)	\
+	{ .family_id = (_family), .set_id = (_set),		\
+	  .node = (_node), .optional = (_optional) }
+
+#define CTLV_STUB_SCHEMA(_family, _set, _node)			\
+	__CTLV_STUB_SCHEMA(_family, _set, _node, false)
+
+#define CTLV_STUB_SCHEMA_OPTIONAL(_family, _set, _node)		\
+	__CTLV_STUB_SCHEMA(_family, _set, _node, true)
+
+struct ctlv_schema_tree {
+	const struct ctlv_node_schema *node_schemas;
+	u32 node_schemas_count;
+	const struct ctlv_stub_schema *stub_schemas;
+	u32 stub_schemas_count;
+};
+
+#define CTLV_SCHEMA_TREE(_name) {				\
+	.node_schemas = _name##_node_schemas,			\
+	.node_schemas_count = ARRAY_SIZE(_name##_node_schemas),	\
+}
+
+#define CTLV_SCHEMA_TREE_STUBS(_name) {				\
+	.node_schemas = _name##_node_schemas,			\
+	.node_schemas_count = ARRAY_SIZE(_name##_node_schemas),	\
+	.stub_schemas = _name##_stub_schemas,			\
+	.stub_schemas_count = ARRAY_SIZE(_name##_stub_schemas),	\
+}
+
+#define CTLV_SCHEMA_TREE_NONE() { }
+
+struct ctlv_stub_fill_schema {
+	u16 family_id;
+	u32 set_id;
+	struct ctlv_schema_tree members;
+};
+
+#define CTLV_STUB_FILL_SCHEMA(_family, _set, _name) {		\
+	.family_id = (_family),					\
+	.set_id = (_set),					\
+	.members = CTLV_SCHEMA_TREE(_name##_fill),		\
+}
+
+struct ctlv_op_sizes {
+	u32 request_max_len;
+	u32 action_reply_max_len;
+	u32 query_reply_min_len;
+	u32 query_reply_suggested_len;
+	u32 event_record_max_len;
+};
+
+struct ctlv_op_schema {
+	u64 op_id;
+	u8 type;
+	u8 fd_access;
+	u8 availability;
+	bool optional;
+	bool pre_post;
+	struct ctlv_schema_tree request;
+	struct ctlv_schema_tree reply;
+	struct ctlv_op_sizes sizes;
+};
+
+#define __CTLV_OP_SCHEMA(_op, _type, _availability, ...)	\
+	{ .op_id = (_op), .type = (_type),			\
+	  .availability = (_availability), __VA_ARGS__ }
+
+#define CTLV_OP_SCHEMA_ACTION(_op, _access, _availability, _request_len, _reply_len, \
+			      _request, _reply, ...)			\
+	__CTLV_OP_SCHEMA(_op, CTLV_OP_TYPE_ACTION, _availability,	\
+			 .fd_access = (_access),			\
+			 .request = _request, .reply = _reply,		\
+			 .sizes = {					\
+				.request_max_len = (_request_len),	\
+				.action_reply_max_len = (_reply_len),	\
+			 },						\
+			 __VA_ARGS__)
+
+#define CTLV_OP_SCHEMA_QUERY(_op, _access, _availability, _request_len, _reply_min, \
+			     _reply_suggested, _request, _reply, ...)	\
+	__CTLV_OP_SCHEMA(_op, CTLV_OP_TYPE_QUERY, _availability,	\
+			 .fd_access = (_access),			\
+			 .request = _request, .reply = _reply,		\
+			 .sizes = {					\
+				.request_max_len = (_request_len),	\
+				.query_reply_min_len = (_reply_min),	\
+				.query_reply_suggested_len =		\
+					(_reply_suggested),		\
+			 },						\
+			 __VA_ARGS__)
+
+#define CTLV_OP_SCHEMA_EVENT(_op, _record_len, _reply, ...)	\
+	__CTLV_OP_SCHEMA(_op, CTLV_OP_TYPE_EVENT,		\
+			 CTLV_OP_AVAILABILITY_FIXED,			\
+			 .reply = _reply,				\
+			 .sizes = {					\
+				.event_record_max_len = (_record_len),	\
+			 },						\
+			 __VA_ARGS__)
+
+struct ctlv_family_schema {
+	const char *name;
+	u16 family_id;
+	const struct ctlv_op_schema *ops;
+	u32 ops_count;
+	const struct ctlv_stub_fill_schema *stub_fill_schemas;
+	u32 stub_fill_schemas_count;
+};
+
+/* Leave half of a uevent environment to the device model. */
+#define CTLV_UEVENT_MAX_LEN (UEVENT_BUFFER_SIZE / 2)
+#define CTLV_UEVENT_MAX_VARS (UEVENT_NUM_ENVP / 2)
+
+struct ctlv_input_ref {
+	const struct ctlv_schema_tree *tree;
+	u64 attr_id;
+	u32 node;
+	u32 slot;
+	u8 kind;
+};
+
+typedef int (*ctlv_action_fn)(void *priv, struct ctlv_op_ctx *ctx,
+			      const struct ctlv_cursor *request,
+			      struct ctlv_cursor *reply);
+typedef int (*ctlv_query_fn)(void *priv, struct ctlv_op_ctx *ctx,
+			     const struct ctlv_cursor *request,
+			     struct ctlv_cursor *reply);
+typedef int (*ctlv_op_pre_fn)(void *priv, struct ctlv_op_ctx *ctx);
+typedef void (*ctlv_op_post_fn)(void *priv, struct ctlv_op_ctx *ctx);
+
+struct ctlv_op {
+	union {
+		ctlv_action_fn action;
+		ctlv_query_fn query;
+	};
+	ctlv_op_pre_fn pre;
+	ctlv_op_post_fn post;
+};
+
+#define CTLV_OP_ACTION(_name) { .action = _name##_action }
+#define CTLV_OP_QUERY(_name) { .query = _name##_query }
+#define CTLV_OP_ACTION_PRE_POST(_name)				\
+	{ .action = _name##_action, .pre = _name##_pre,		\
+	  .post = _name##_post }
+#define CTLV_OP_QUERY_PRE_POST(_name)				\
+	{ .query = _name##_query, .pre = _name##_pre,		\
+	  .post = _name##_post }
+
+typedef size_t (*ctlv_family_priv_size_fn)(void);
+typedef const void *(*ctlv_family_pre_init_fn)(const void *init_info);
+typedef int (*ctlv_family_init_fn)(struct ctlv_device *ctlvdev,
+				   const void *init_info, void *priv);
+typedef int (*ctlv_family_post_init_fn)(struct ctlv_device *ctlvdev,
+					void *priv);
+typedef void (*ctlv_family_pre_fini_fn)(struct ctlv_device *ctlvdev,
+					void *priv);
+typedef void (*ctlv_family_fini_fn)(struct ctlv_device *ctlvdev, void *priv);
+
+typedef int (*ctlv_stub_fill_fn)(void *priv, struct ctlv_op_ctx *ctx,
+				 const struct ctlv_cursor *request,
+				 struct ctlv_cursor *nest);
+
+struct ctlv_stub_ops {
+	u16 family_id;
+	u32 set_id;
+	ctlv_stub_fill_fn fill;
+};
+
+#define CTLV_STUB_OPS(_family, _set, _name) {			\
+	.family_id = (_family),					\
+	.set_id = (_set),					\
+	.fill = _name##_fill,					\
+}
+
+struct ctlv_family {
+	const struct ctlv_family_schema *schema;
+	const struct ctlv_family *parent;
+	const struct ctlv_op *ops;
+	u32 ops_count;
+	ctlv_op_pre_fn pre;
+	ctlv_op_post_fn post;
+	ctlv_family_priv_size_fn priv_size;
+	ctlv_family_pre_init_fn pre_init;
+	ctlv_family_init_fn init;
+	ctlv_family_post_init_fn post_init;
+	ctlv_family_pre_fini_fn pre_fini;
+	ctlv_family_fini_fn fini;
+	const struct ctlv_stub_ops *stub_ops;
+	u32 stub_ops_count;
+};
+
+extern const struct ctlv_family ctlv_family;
+
+#endif /* _LINUX_CTLV_FAMILY_H */
diff --git a/include/uapi/linux/ctlv.h b/include/uapi/linux/ctlv.h
new file mode 100644
index 000000000000..6bc0d1a296e6
--- /dev/null
+++ b/include/uapi/linux/ctlv.h
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/*
+ * Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES
+ *
+ * CTLV transport UAPI: the TLV wire format, the op-execution ioctl, the event
+ * record header and transport limits. Schema-free; a family's constants
+ * are generated into <linux/<family>_gen.h>, the root family's into
+ * <linux/ctlv_gen.h>.
+ */
+#ifndef _UAPI_LINUX_CTLV_H
+#define _UAPI_LINUX_CTLV_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct ctlv_attr - Attr header.
+ * @len: this header plus its payload, excluding this attr's trailing padding
+ * @flags: CTLV_ATTR_F_* bits
+ * @attr_id: complete attr ID, or CTLV_ATTR_ROOT for a message root
+ *
+ * Attrs are aligned to CTLV_ALIGNTO, which is why @attr_id is __aligned_u64: a
+ * 32-bit ABI would otherwise align this structure to four bytes. A nested
+ * payload is the concatenation of CTLV_ALIGN(child.len) bytes per child, so
+ * child padding counts inside the containing attr's @len while a leaf's own
+ * padding does not. Scalar payloads are native-endian. Within each request
+ * root or nest, occurrences of one @attr_id are contiguous; different IDs
+ * otherwise have no required order.
+ */
+struct ctlv_attr {
+	__u32 len;
+	__u32 flags;
+	__aligned_u64 attr_id;
+};
+
+#define CTLV_ALIGNTO 8
+#define CTLV_ALIGN(_len) (((_len) + CTLV_ALIGNTO - 1) & ~(CTLV_ALIGNTO - 1))
+
+/* Set exactly on root and nested attrs, clear on scalar attrs. */
+#define CTLV_ATTR_F_NESTED		(1U << 0)
+/* Query fragments: set on the root and each nest logically open at the end. */
+#define CTLV_ATTR_F_FRAG_MORE		(1U << 1)
+/*
+ * A request attr, never the root, that a device whose schema does not declare
+ * its ID skips whole instead of refusing the message. An ID that schema does
+ * declare is held to it wherever it appears, so this asks to be forgiven what
+ * this kernel has never heard of and nothing else.
+ */
+#define CTLV_ATTR_F_IGNORE_IF_UNKNOWN	(1U << 2)
+
+/* Root attr: carries CTLV_ATTR_F_NESTED, valid only at a message start. */
+#define CTLV_ATTR_ROOT 0ULL
+
+/* Complete attr: family in bits 63..48, group in 47..32, attr in 31..0. */
+#define CTLV_ATTR(_family, _group, _attr)	\
+	(((__u64)(_family) << 48) |		\
+	 ((__u64)(_group) << 32) |		\
+	 (__u64)(_attr))
+
+#define CTLV_ATTR_FAMILY(_attr)	((__u16)((_attr) >> 48))
+#define CTLV_ATTR_GROUP(_attr)	((__u16)((_attr) >> 32))
+#define CTLV_ATTR_NUMBER(_attr)	((__u32)(_attr))
+
+/* Complete op: family in bits 63..48, zero in 47..32, op in 31..0. */
+#define CTLV_OP(_family, _op)	\
+	(((__u64)(_family) << 48) | (__u64)(_op))
+
+#define CTLV_OP_FAMILY(_op)		((__u16)((_op) >> 48))
+#define CTLV_OP_NUMBER(_op)		((__u32)(_op))
+
+/**
+ * enum ctlv_unit - CTLV-defined unit of an integer attr payload.
+ * @CTLV_UNIT_NONE: dimensionless
+ * @CTLV_UNIT_SECONDS: seconds
+ * @CTLV_UNIT_HERTZ: hertz
+ * @CTLV_UNIT_BYTES: bytes
+ * @CTLV_UNIT_CELSIUS: degrees Celsius
+ *
+ * A payload is value * 10^scale of this unit, from the decimal scale the attr
+ * declares alongside. Changing either is an ABI break.
+ */
+enum ctlv_unit {
+	CTLV_UNIT_NONE = 0,
+	CTLV_UNIT_SECONDS,
+	CTLV_UNIT_HERTZ,
+	CTLV_UNIT_BYTES,
+	CTLV_UNIT_CELSIUS,
+};
+
+/**
+ * enum ctlv_schema_kind - CTLV-defined form of one attr payload.
+ * @CTLV_SCHEMA_UINT: unsigned integer payload bounded by a range
+ * @CTLV_SCHEMA_SINT: signed integer payload bounded by a range
+ * @CTLV_SCHEMA_BOOL: one payload byte holding zero or one
+ * @CTLV_SCHEMA_STRING: NUL-terminated string payload bounded by length
+ * @CTLV_SCHEMA_BINARY: opaque payload bounded by length
+ * @CTLV_SCHEMA_ENUM: unsigned integer payload restricted to a range
+ * @CTLV_SCHEMA_FLAGS: unsigned integer payload restricted to a mask
+ * @CTLV_SCHEMA_NEST: nested payload described by further nodes
+ * @CTLV_SCHEMA_BLOB: blob descriptor nest
+ *
+ * Exactly one form applies to an attr. These are the values op-schema-get
+ * reports, and the set is append-only.
+ */
+enum ctlv_schema_kind {
+	CTLV_SCHEMA_UINT,
+	CTLV_SCHEMA_SINT,
+	CTLV_SCHEMA_BOOL,
+	CTLV_SCHEMA_STRING,
+	CTLV_SCHEMA_BINARY,
+	CTLV_SCHEMA_ENUM,
+	CTLV_SCHEMA_FLAGS,
+	CTLV_SCHEMA_NEST,
+	CTLV_SCHEMA_BLOB,
+};
+
+/**
+ * struct ctlv_op_exec - Op-execution ioctl argument.
+ * @op_id: complete op ID; zero is invalid
+ * @request: struct ctlv_attr __user *, the mandatory complete request root
+ * @reply: struct ctlv_attr __user *, the success reply or the error
+ *	information
+ * @request_len: readable bytes beginning at @request, at least one root header;
+ *	the transport copy boundary, which may exceed the root's own length
+ * @reply_len: writable bytes beginning at @reply; input only, never
+ *	overwritten by the kernel
+ * @generation: query only; zero on a first fragment, the previously returned
+ *	value on continuation, and the query generation on output. Actions must
+ *	set zero.
+ * @cursor: query only; zero starts a query and a nonzero value resumes it. On
+ *	output it is the next cursor when the root carries
+ *	CTLV_ATTR_F_FRAG_MORE and zero when no further fragment exists. Actions
+ *	must set zero.
+ * @reserved: must be zero
+ *
+ * No size field: the ioctl number encodes the structure size and @reserved
+ * covers compatible growth. @request and @reply are fixed-width
+ * representations of userspace pointers so that the compat layout is identical.
+ */
+struct ctlv_op_exec {
+	__aligned_u64 op_id;
+	__aligned_u64 request;
+	__aligned_u64 reply;
+	__u32 request_len;
+	__u32 reply_len;
+	__aligned_u64 generation;
+	__aligned_u64 cursor;
+	__aligned_u64 reserved[2];
+};
+
+#define CTLV_IOC_MAGIC 0xBB
+
+#define CTLV_IOC_OP_EXEC _IOWR(CTLV_IOC_MAGIC, 0x00, struct ctlv_op_exec)
+
+/**
+ * struct ctlv_event_hdr - Header of one queued event record.
+ * @length: complete record length, this header plus the aligned root
+ * @flags: must be zero
+ * @op_id: complete op ID of the event op that produced the record
+ * @sequence: per open file description sequence number, assigned to every
+ *	eligible enqueue attempt including dropped ones
+ *
+ * Exactly one root attr follows the header, and one read() returns one record.
+ */
+struct ctlv_event_hdr {
+	__u32 length;
+	__u32 flags;
+	__aligned_u64 op_id;
+	__aligned_u64 sequence;
+};
+
+/* Implementation limits, not wire-field maxima: raising them is compatible. */
+
+/* Request roots, action replies, query reply fragments and event roots. */
+#define CTLV_MAX_INLINE_MESSAGE_LEN	0x100000	/* 1 MiB */
+/* Includes the error information root. */
+#define CTLV_MAX_ERROR_LEN		0x4000		/* 16 KiB */
+/* The root attr is at depth zero. */
+#define CTLV_MAX_NEST_DEPTH		32
+#define CTLV_DEFAULT_QUERY_REPLY_LEN	0x10000		/* 64 KiB */
+#define CTLV_MAX_EVENT_QUEUE_LEN	0x1000000	/* 16 MiB */
+
+#endif /* _UAPI_LINUX_CTLV_H */
-- 
2.56.0


  parent reply	other threads:[~2026-10-15 14:51 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 14:50 [PATCH RFC 00/20] attestation: Add a common subsystem and TDX support Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 01/20] ctlv: Add the schema language and generator Jiri Pirko
2026-10-15 14:50 ` Jiri Pirko [this message]
2026-10-15 14:50 ` [PATCH RFC 03/20] ctlv: Add the root family specification and generated files Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 04/20] Documentation: ctlv: Add userspace ABI Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 05/20] ctlv: Prepare message input handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 06/20] ctlv: Prepare blob descriptor validation Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 07/20] ctlv: Prepare schema validation Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 08/20] ctlv: Prepare message output handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 09/20] ctlv: Prepare VA blob handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 10/20] ctlv: Prepare event queue support Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 11/20] ctlv: Prepare runtime introspection Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 12/20] ctlv: Add device and operation dispatch Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 13/20] Documentation: ctlv: Describe how to write a family Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 14/20] attestation: Add the base family specification and generated files Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 15/20] attestation: Prepare provider and instance core Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 16/20] attestation: Prepare measurement register journal Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 17/20] attestation: Add CTLV operation handling Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 18/20] tdx-guest: Expose the native attestation service API Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 19/20] attestation: Add the TDX family specification and generated files Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 20/20] attestation: Add the TDX family implementation Jiri Pirko

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=20261015145053.3664509-3-jiri@resnulli.us \
    --to=jiri@resnulli.us \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=aik@amd.com \
    --cc=alistair.francis@wdc.com \
    --cc=ankita@nvidia.com \
    --cc=cedric.xing@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=david.quigley@intel.com \
    --cc=drdeeglaze@gmail.com \
    --cc=elena.reshetova@intel.com \
    --cc=jgg@ziepe.ca \
    --cc=jic23@kernel.org \
    --cc=jpiotrowski@nvidia.com \
    --cc=kas@kernel.org \
    --cc=ksinyuk@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=peter.fang@intel.com \
    --cc=pgonda@google.com \
    --cc=qinkun@google.com \
    --cc=rick.p.edgecombe@intel.com \
    --cc=rodrigo.vivi@intel.com \
    --cc=sameo@meta.com \
    --cc=sathyanarayanan.kuppuswamy@linux.intel.com \
    --cc=suzuki.poulose@arm.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox