mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yeoreum Yun <yeoreum.yun@arm.com>
To: Jiri Pirko <jiri@resnulli.us>
Cc: linux-coco@lists.linux.dev, 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: Re: [PATCH RFC 02/20] ctlv: Add the UAPI wire format and family API
Date: Mon, 26 Oct 2026 18:55:12 +0000	[thread overview]
Message-ID: <at-iEMxN98nie1Qr@e129823.arm.com> (raw)
In-Reply-To: <20261015145053.3664509-3-jiri@resnulli.us>

Hi,

> 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

JFYI, when I tested with CTLV_MAX_NEST_DEPTH as 32 and try to run
ctlv_msg_test_as_deep_as_the_core_allows() message_kunit.c test,
It experiences the *real stack overflow* on FVP
(lesser value (e.g. 16) is fine):

[    3.834419]     ok 22 ctlv_msg_test_the_bit_where_it_means_nothing
[    3.836499]     ok 23 ctlv_msg_test_a_bit_no_version_declares
[    3.837852] Insufficient stack space to handle exception!
[    3.837875] ESR: 0x0000000096000047 -- DABT (current EL)
[    3.837916] FAR: 0xffff800084efffe0
[    3.837953] Task stack:     [0xffff800084f00000..0xffff800084f04000]
[    3.838001] IRQ stack:      [0xffff800083d50000..0xffff800083d54000]
[    3.838049] Overflow stack: [0xffff00087b7c3150..0xffff00087b7c4150]
[    3.838114] CPU: 7 UID: 0 PID: 257 Comm: kunit_try_catch Tainted: G                 N
** replaying previous printk message **
[    3.838114] CPU: 7 UID: 0 PID: 257 Comm: kunit_try_catch Tainted: G                 N  7.3.0-rc4+ #1216 PREEMPTLAZY
[    3.838219] Tainted: [N]=TEST
[    3.838249] Hardware name:  , BIOS
[    3.838279] pstate: 21400009 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[    3.838360] pc : __kmalloc_flags_noprof+0x10/0x540
[    3.838433] lr : __alloc_empty_sheaf+0x48/0x88
[    3.838501] sp : ffff800084efffa0
[    3.838534] x29: ffff800084f00030 x28: 0000000000000400 x27: 0000000000000400
[    3.838657] x26: ffff000803d721c0 x25: 0000000000000000 x24: 0000000000400cc0
[    3.838780] x23: ffff00087b7e3398 x22: 16e0800080564b98 x21: ffff0008000a0900
[    3.838908] x20: 0000000000000000 x19: ffff000800013600 x18: 0000000000000000
[    3.839029] x17: 0000000000000001 x16: 0000000000000002 x15: ffffffff00000001
[    3.839150] x14: 0000001c000001c0 x13: ffffffff00000001 x12: ffff000800013500
[    3.839275] x11: ffff00080370a800 x10: 0000000000000060 x9 : ffff8000805627d0
[    3.839401] x8 : 0000000000000000 x7 : ffffffff00000001 x6 : 0000001d000001d0
[    3.839521] x5 : ffff800080567b68 x4 : 00000000ffffffff x3 : 0000000000000004
[    3.839640] x2 : 0000000000000dc0 x1 : 0000000000000008 x0 : 0000000000000080
[    3.839761] Kernel panic - not syncing: kernel stack overflow
[    3.841533] CPU: 7 UID: 0 PID: 257 Comm: kunit_try_catch Tainted: G                 N  7.3.0-rc4+ #1216 PREEMPTLAZY
[    3.841783] Tainted: [N]=TEST
[    3.841877] Hardware name:  , BIOS
[    3.841980] Call trace:
[    3.842065]  show_stack+0x20/0x40 (C)
[    3.842246]  __dump_stack+0x28/0x48
[    3.842427]  dump_stack_lvl+0x28/0xb0
[    3.842609]  dump_stack+0x18/0x34
[    3.842788]  vpanic+0x208/0x5b8
[    3.842944]  panic+0x54/0x60
[    3.843096]  nmi_panic+0xc0/0xc8
[    3.843273]  panic_bad_stack+0x10c/0x128
[    3.843466]  handle_bad_stack+0x34/0x38
[    3.843622]  __bad_stack+0x98/0xa0
[    3.843773]  __kmalloc_flags_noprof+0x10/0x540 (P)
[    3.843950]  __pcs_replace_empty_main+0x2ac/0x3e8
[    3.844139]  __kmalloc_node_track_caller_noprof+0x440/0x520
[    3.844328]  krealloc_node_align_noprof+0x178/0x390
[    3.844509]  kvrealloc_node_align_noprof+0x98/0x130
[    3.844690]  ctlv_schema_index_scope_add+0xb0/0x3f8
[    3.844882]  ctlv_schema_check_indexed_nest+0x1e8/0x958

(repeat ctlv_schema_check_attr()/ctlv_schema_check_indexed_nest())

[    3.856919]  ctlv_schema_check_attr+0x3dc/0x538
[    3.857105]  ctlv_schema_check_indexed_nest+0x788/0x958
[    3.857301]  ctlv_schema_validate+0x88/0x180
[    3.857482]  ctlv_msg_test_as_deep_as_the_core_allows+0x11c/0x1e8
[    3.857698]  kunit_try_run_case+0x64/0x188
[    3.857878]  kunit_generic_run_threadfn_adapter+0x30/0x68
[    3.858086]  kthread+0x10c/0x140
[    3.858245]  ret_from_fork+0x10/0x20
[    3.858398] SMP: stopping secondary CPUs
[    3.858630] Kernel Offset: disabled
[    3.858720] CPU features: 0x0,00000000,00b0802e,9f190bc3,2affe72f
[    3.858872] Memory Limit: none
[    3.858976] ---[ end Kernel panic - not syncing: kernel stack overflow ]---

[...]

I think it might be good to configurable according to architecture
unless it's not good to reduce the CTLV_MAX_NEST_DEPTH number
otherwise, increasing stack size when CTLV is enabled seems unresonable...

-- 
Sincerely,
Yeoreum Yun

  parent reply	other threads:[~2026-10-26 18:55 UTC|newest]

Thread overview: 153+ 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-20 22:31   ` Jonathan Cameron
2026-10-21 13:23     ` Jiri Pirko
2026-10-27  8:34     ` Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 02/20] ctlv: Add the UAPI wire format and family API Jiri Pirko
2026-10-19 23:29   ` Jason Gunthorpe
2026-10-20 12:26     ` Jiri Pirko
2026-10-20 23:00   ` Jonathan Cameron
2026-10-20 23:39     ` Jonathan Cameron
2026-10-21 13:54     ` Jiri Pirko
2026-10-26 18:55   ` Yeoreum Yun [this message]
2026-10-27  8:02     ` Jiri Pirko
2026-10-27 14:15       ` Jason Gunthorpe
2026-10-27 14:48         ` Yeoreum Yun
2026-10-27 15:17           ` Jason Gunthorpe
2026-10-27 15:55             ` Yeoreum Yun
2026-10-15 14:50 ` [PATCH RFC 03/20] ctlv: Add the root family specification and generated files Jiri Pirko
2026-10-19 23:29   ` Jason Gunthorpe
2026-10-20 12:28     ` Jiri Pirko
2026-10-20 12:55       ` Jason Gunthorpe
2026-10-20 14:07         ` Jiri Pirko
2026-10-20 23:30   ` Jonathan Cameron
2026-10-21 16:25     ` Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 04/20] Documentation: ctlv: Add userspace ABI Jiri Pirko
2026-10-19 23:29   ` Jason Gunthorpe
2026-10-20 14:06     ` Jiri Pirko
2026-10-21  0:11   ` Jonathan Cameron
2026-10-22  9:01     ` Jiri Pirko
2026-10-23 19:23       ` Jonathan Cameron
2026-10-15 14:50 ` [PATCH RFC 05/20] ctlv: Prepare message input handling Jiri Pirko
2026-10-21  0:43   ` Jonathan Cameron
2026-10-22  8:27     ` Jiri Pirko
2026-10-22 18:39     ` Jason Gunthorpe
2026-10-23 12:55       ` Jiri Pirko
2026-10-26 14:07   ` Jason Gunthorpe
2026-10-27 10:17     ` 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-26 14:07   ` Jason Gunthorpe
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-21  1:12   ` Jonathan Cameron
2026-10-22  9:04     ` Jiri Pirko
2026-10-26 14:07   ` Jason Gunthorpe
2026-10-26 14:45     ` Jiri Pirko
2026-10-27 12:38   ` Yeoreum Yun
2026-10-15 14:50 ` [PATCH RFC 11/20] ctlv: Prepare runtime introspection Jiri Pirko
2026-10-26 14:07   ` Jason Gunthorpe
2026-10-26 14:52     ` Jiri Pirko
2026-10-26 16:12       ` Jason Gunthorpe
2026-10-27 10:21     ` Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 12/20] ctlv: Add device and operation dispatch Jiri Pirko
2026-10-21  1:25   ` Jonathan Cameron
2026-10-22  9:05     ` Jiri Pirko
2026-10-22 18:43     ` Jason Gunthorpe
2026-10-23 12:58       ` Jiri Pirko
2026-10-23 14:26         ` Jason Gunthorpe
2026-10-26 13:48           ` Jiri Pirko
2026-10-26 14:07   ` Jason Gunthorpe
2026-10-27 13:38     ` Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 13/20] Documentation: ctlv: Describe how to write a family Jiri Pirko
2026-10-19 23:29   ` Jason Gunthorpe
2026-10-21 14:23     ` Jiri Pirko
2026-10-21 14:49       ` Jason Gunthorpe
2026-10-21 16:24         ` Jiri Pirko
2026-10-21 16:48           ` Jason Gunthorpe
2026-10-22  8:22             ` Jiri Pirko
2026-10-22 19:21               ` Jason Gunthorpe
2026-10-23 13:01                 ` Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 14/20] attestation: Add the base family specification and generated files Jiri Pirko
2026-10-26 14:07   ` Jason Gunthorpe
2026-10-15 14:50 ` [PATCH RFC 15/20] attestation: Prepare provider and instance core Jiri Pirko
2026-10-19 23:29   ` Jason Gunthorpe
2026-10-21 13:04     ` 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-26 14:07   ` Jason Gunthorpe
2026-10-27 10:03     ` 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
2026-10-22 22:07   ` Edgecombe, Rick P
2026-10-23 14:12     ` Jason Gunthorpe
2026-10-23 19:40       ` Edgecombe, Rick P
2026-10-23 22:00         ` Jason Gunthorpe
2026-10-23 18:15     ` Jiri Pirko
2026-10-23 19:41       ` Edgecombe, Rick P
2026-10-16 23:43 ` [PATCH RFC 00/20] attestation: Add a common subsystem and TDX support Jason Gunthorpe
2026-10-17 18:16   ` Dionna Glaze
2026-10-17 19:06     ` Jarkko Sakkinen
2026-10-17 19:08       ` Jarkko Sakkinen
2026-10-17 19:22         ` Jarkko Sakkinen
2026-10-17 20:55       ` Jason Gunthorpe
2026-10-17 21:14         ` Jarkko Sakkinen
2026-10-17 20:34     ` Jason Gunthorpe
2026-10-17 20:55       ` Jarkko Sakkinen
2026-10-17 23:10         ` Jason Gunthorpe
2026-10-18 23:53           ` Dionna Glaze
2026-10-19 12:08             ` Jiri Pirko
2026-10-19 16:10               ` Dionna Glaze
2026-10-19 22:56                 ` Jason Gunthorpe
2026-10-21  8:33                   ` Jiri Pirko
2026-10-21 14:12                     ` Mimi Zohar
2026-10-21 14:35                       ` Jason Gunthorpe
2026-10-21 19:05                         ` Mimi Zohar
2026-10-22 10:54                           ` Jiri Pirko
2026-10-22 11:24                             ` Mimi Zohar
2026-10-22 18:51                               ` Jason Gunthorpe
2026-10-22 19:19                                 ` Jarkko Sakkinen
2026-10-22 19:23                                   ` Jason Gunthorpe
2026-10-22 19:40                                     ` Jarkko Sakkinen
2026-10-22 19:40                                     ` James Bottomley
2026-10-22 12:26                         ` James Bottomley
2026-10-22 13:11                           ` Jason Gunthorpe
2026-10-22 14:07                             ` James Bottomley
2026-10-22 19:19                               ` Jason Gunthorpe
2026-10-22 19:37                                 ` Mimi Zohar
2026-10-22 19:45                                   ` Jason Gunthorpe
2026-10-22 19:52                                     ` James Bottomley
2026-10-22 20:43                                       ` Mimi Zohar
2026-10-20  9:26                 ` Jiri Pirko
2026-10-20 13:45                 ` Mimi Zohar
2026-10-20 14:06                   ` Jason Gunthorpe
2026-10-20 15:22                     ` Mimi Zohar
2026-10-20 16:11                       ` Yeoreum Yun
2026-10-20 16:52                         ` Jason Gunthorpe
2026-10-21 12:23                           ` Mimi Zohar
2026-10-21 13:18                             ` Jarkko Sakkinen
2026-10-21 13:50                               ` Yeoreum Yun
2026-10-21 13:51                             ` Jason Gunthorpe
2026-10-21 14:31                               ` Mimi Zohar
2026-10-21 14:39                                 ` Jason Gunthorpe
2026-10-21 12:48                         ` James Bottomley
2026-10-21 13:55                           ` Jason Gunthorpe
2026-10-19 12:40             ` Jarkko Sakkinen
2026-10-19 23:11             ` Jason Gunthorpe
2026-10-20 12:49       ` James Bottomley
2026-10-20 13:13         ` Jason Gunthorpe
2026-10-22 10:30 ` Aneesh Kumar K.V
2026-10-22 15:38   ` Jiri Pirko
2026-10-22 16:42     ` Jason Gunthorpe
2026-10-23  8:04     ` Aneesh Kumar K.V
2026-10-23 11:32       ` Jiri Pirko
2026-10-23 14:20       ` Jason Gunthorpe
2026-10-23 15:28         ` Aneesh Kumar K.V
2026-10-23 15:42           ` Jason Gunthorpe
2026-10-23 19:13             ` Jonathan Cameron
2026-10-27 18:43 ` Dave Jiang
2026-10-27 19:36   ` Jason Gunthorpe
2026-10-27 23:09     ` Dave Jiang
2026-10-27 23:46       ` Jason Gunthorpe

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=at-iEMxN98nie1Qr@e129823.arm.com \
    --to=yeoreum.yun@arm.com \
    --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=jiri@resnulli.us \
    --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

all inboxes | Powered by JetHome®