All of lore.kernel.org
 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: 172+ 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:58   ` sashiko-bot
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-15 15:06   ` sashiko-bot
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 15:14   ` sashiko-bot
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 15:14   ` sashiko-bot
2026-10-15 14:50 ` [PATCH RFC 10/20] ctlv: Prepare event queue support Jiri Pirko
2026-10-15 15:22   ` sashiko-bot
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-15 15:28   ` sashiko-bot
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-15 15:20   ` sashiko-bot
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-29 10:04     ` Jiri Pirko
2026-10-15 14:50 ` [PATCH RFC 15/20] attestation: Prepare provider and instance core Jiri Pirko
2026-10-15 15:30   ` sashiko-bot
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 15:33   ` sashiko-bot
2026-10-15 14:50 ` [PATCH RFC 18/20] tdx-guest: Expose the native attestation service API Jiri Pirko
2026-10-15 15:40   ` sashiko-bot
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-15 15:40   ` sashiko-bot
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
2026-10-28 19:16         ` Dave Jiang
2026-10-29 14:09           ` Jason Gunthorpe
2026-10-29  9:32         ` Jiri Pirko
2026-10-29  9:30       ` Jiri Pirko
2026-10-29 10:07   ` Jiri Pirko
2026-10-29  7:37 ` Nikolay Borisov
2026-10-29 14:16   ` 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 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.