Blame view

include/rdma/uverbs_ioctl.h 29.8 KB
6bf9d8f6f   Leon Romanovsky   RDMA/include: Rep...
1
  /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
a0aa309c3   Matan Barak   IB/core: Add a ge...
2
3
  /*
   * Copyright (c) 2017, Mellanox Technologies inc.  All rights reserved.
a0aa309c3   Matan Barak   IB/core: Add a ge...
4
5
6
7
8
9
   */
  
  #ifndef _UVERBS_IOCTL_
  #define _UVERBS_IOCTL_
  
  #include <rdma/uverbs_types.h>
354103065   Matan Barak   IB/core: Add macr...
10
11
  #include <linux/uaccess.h>
  #include <rdma/rdma_user_ioctl.h>
d70724f14   Matan Barak   IB/core: Add lega...
12
  #include <rdma/ib_user_ioctl_verbs.h>
1f7ff9d5d   Matan Barak   IB/uverbs: Move t...
13
  #include <rdma/ib_user_ioctl_cmds.h>
a0aa309c3   Matan Barak   IB/core: Add a ge...
14
15
16
17
18
19
  
  /*
   * =======================================
   *	Verbs action specifications
   * =======================================
   */
f43dbebfa   Matan Barak   IB/core: Add supp...
20
21
  enum uverbs_attr_type {
  	UVERBS_ATTR_TYPE_NA,
fac9658ca   Matan Barak   IB/core: Add new ...
22
23
  	UVERBS_ATTR_TYPE_PTR_IN,
  	UVERBS_ATTR_TYPE_PTR_OUT,
f43dbebfa   Matan Barak   IB/core: Add supp...
24
25
  	UVERBS_ATTR_TYPE_IDR,
  	UVERBS_ATTR_TYPE_FD,
494c5580a   Matan Barak   IB/uverbs: Add en...
26
  	UVERBS_ATTR_TYPE_ENUM_IN,
70cd20aed   Guy Levi   IB/uverbs: Add ID...
27
  	UVERBS_ATTR_TYPE_IDRS_ARRAY,
f43dbebfa   Matan Barak   IB/core: Add supp...
28
  };
a0aa309c3   Matan Barak   IB/core: Add a ge...
29
30
31
32
33
34
  enum uverbs_obj_access {
  	UVERBS_ACCESS_READ,
  	UVERBS_ACCESS_WRITE,
  	UVERBS_ACCESS_NEW,
  	UVERBS_ACCESS_DESTROY
  };
1f07e08fa   Matan Barak   IB/uverbs: Enable...
35
  /* Specification of a single attribute inside the ioctl message */
83bb44423   Jason Gunthorpe   RDMA/uverbs: Remo...
36
  /* good size 16 */
f43dbebfa   Matan Barak   IB/core: Add supp...
37
  struct uverbs_attr_spec {
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
38
  	u8 type;
83bb44423   Jason Gunthorpe   RDMA/uverbs: Remo...
39
40
  
  	/*
422e3d37e   Jason Gunthorpe   RDMA/uverbs: Comb...
41
42
43
  	 * Support extending attributes by length. Allow the user to provide
  	 * more bytes than ptr.len, but check that everything after is zero'd
  	 * by the user.
83bb44423   Jason Gunthorpe   RDMA/uverbs: Remo...
44
  	 */
422e3d37e   Jason Gunthorpe   RDMA/uverbs: Comb...
45
  	u8 zero_trailing:1;
83bb44423   Jason Gunthorpe   RDMA/uverbs: Remo...
46
47
48
49
50
51
  	/*
  	 * Valid only for PTR_IN. Allocate and copy the data inside
  	 * the parser
  	 */
  	u8 alloc_and_copy:1;
  	u8 mandatory:1;
07f05f40d   Jason Gunthorpe   RDMA/uverbs: Use ...
52
53
  	/* True if this is from UVERBS_ATTR_UHW */
  	u8 is_udata:1;
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
54

fac9658ca   Matan Barak   IB/core: Add new ...
55
  	union {
1f07e08fa   Matan Barak   IB/uverbs: Enable...
56
  		struct {
c66db3111   Matan Barak   IB/uverbs: Safely...
57
  			/* Current known size to kernel */
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
58
  			u16 len;
c66db3111   Matan Barak   IB/uverbs: Safely...
59
  			/* User isn't allowed to provide something < min_len */
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
60
  			u16 min_len;
1f07e08fa   Matan Barak   IB/uverbs: Enable...
61
  		} ptr;
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
62

1f07e08fa   Matan Barak   IB/uverbs: Enable...
63
  		struct {
fac9658ca   Matan Barak   IB/core: Add new ...
64
65
66
67
  			/*
  			 * higher bits mean the namespace and lower bits mean
  			 * the type id within the namespace.
  			 */
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
68
69
  			u16 obj_type;
  			u8 access;
fac9658ca   Matan Barak   IB/core: Add new ...
70
  		} obj;
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
71
72
73
74
75
  
  		struct {
  			u8 num_elems;
  		} enum_def;
  	} u;
70cd20aed   Guy Levi   IB/uverbs: Add ID...
76
  	/* This weird split lets us remove some padding */
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
77
  	union {
494c5580a   Matan Barak   IB/uverbs: Add en...
78
  		struct {
494c5580a   Matan Barak   IB/uverbs: Add en...
79
80
81
82
83
  			/*
  			 * The enum attribute can select one of the attributes
  			 * contained in the ids array. Currently only PTR_IN
  			 * attributes are supported in the ids array.
  			 */
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
84
  			const struct uverbs_attr_spec *ids;
494c5580a   Matan Barak   IB/uverbs: Add en...
85
  		} enum_def;
70cd20aed   Guy Levi   IB/uverbs: Add ID...
86
87
88
89
90
91
92
93
94
95
96
  
  		struct {
  			/*
  			 * higher bits mean the namespace and lower bits mean
  			 * the type id within the namespace.
  			 */
  			u16				obj_type;
  			u16				min_len;
  			u16				max_len;
  			u8				access;
  		} objs_arr;
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
97
  	} u2;
f43dbebfa   Matan Barak   IB/core: Add supp...
98
  };
5009010fb   Matan Barak   IB/core: Declare ...
99
  /*
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
100
101
102
103
104
105
106
107
108
109
110
111
112
   * Information about the API is loaded into a radix tree. For IOCTL we start
   * with a tuple of:
   *  object_id, attr_id, method_id
   *
   * Which is a 48 bit value, with most of the bits guaranteed to be zero. Based
   * on the current kernel support this is compressed into 16 bit key for the
   * radix tree. Since this compression is entirely internal to the kernel the
   * below limits can be revised if the kernel gains additional data.
   *
   * With 64 leafs per node this is a 3 level radix tree.
   *
   * The tree encodes multiple types, and uses a scheme where OBJ_ID,0,0 returns
   * the object slot, and OBJ_ID,METH_ID,0 and returns the method slot.
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
113
114
115
116
117
118
119
   *
   * This also encodes the tables for the write() and write() extended commands
   * using the coding
   *   OBJ_ID,UVERBS_API_METHOD_IS_WRITE,command #
   *   OBJ_ID,UVERBS_API_METHOD_IS_WRITE_EX,command_ex #
   * ie the WRITE path is treated as a special method type in the ioctl
   * framework.
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
120
121
122
123
124
125
126
   */
  enum uapi_radix_data {
  	UVERBS_API_NS_FLAG = 1U << UVERBS_ID_NS_SHIFT,
  
  	UVERBS_API_ATTR_KEY_BITS = 6,
  	UVERBS_API_ATTR_KEY_MASK = GENMASK(UVERBS_API_ATTR_KEY_BITS - 1, 0),
  	UVERBS_API_ATTR_BKEY_LEN = (1 << UVERBS_API_ATTR_KEY_BITS) - 1,
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
127
  	UVERBS_API_WRITE_KEY_NUM = 1 << UVERBS_API_ATTR_KEY_BITS,
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
128
129
130
  
  	UVERBS_API_METHOD_KEY_BITS = 5,
  	UVERBS_API_METHOD_KEY_SHIFT = UVERBS_API_ATTR_KEY_BITS,
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
131
132
133
134
135
136
  	UVERBS_API_METHOD_KEY_NUM_CORE = 22,
  	UVERBS_API_METHOD_IS_WRITE = 30 << UVERBS_API_METHOD_KEY_SHIFT,
  	UVERBS_API_METHOD_IS_WRITE_EX = 31 << UVERBS_API_METHOD_KEY_SHIFT,
  	UVERBS_API_METHOD_KEY_NUM_DRIVER =
  		(UVERBS_API_METHOD_IS_WRITE >> UVERBS_API_METHOD_KEY_SHIFT) -
  		UVERBS_API_METHOD_KEY_NUM_CORE,
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
137
138
139
140
141
142
143
  	UVERBS_API_METHOD_KEY_MASK = GENMASK(
  		UVERBS_API_METHOD_KEY_BITS + UVERBS_API_METHOD_KEY_SHIFT - 1,
  		UVERBS_API_METHOD_KEY_SHIFT),
  
  	UVERBS_API_OBJ_KEY_BITS = 5,
  	UVERBS_API_OBJ_KEY_SHIFT =
  		UVERBS_API_METHOD_KEY_BITS + UVERBS_API_METHOD_KEY_SHIFT,
342ee59de   Yishai Hadas   IB/mlx5: Expose U...
144
  	UVERBS_API_OBJ_KEY_NUM_CORE = 20,
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  	UVERBS_API_OBJ_KEY_NUM_DRIVER =
  		(1 << UVERBS_API_OBJ_KEY_BITS) - UVERBS_API_OBJ_KEY_NUM_CORE,
  	UVERBS_API_OBJ_KEY_MASK = GENMASK(31, UVERBS_API_OBJ_KEY_SHIFT),
  
  	/* This id guaranteed to not exist in the radix tree */
  	UVERBS_API_KEY_ERR = 0xFFFFFFFF,
  };
  
  static inline __attribute_const__ u32 uapi_key_obj(u32 id)
  {
  	if (id & UVERBS_API_NS_FLAG) {
  		id &= ~UVERBS_API_NS_FLAG;
  		if (id >= UVERBS_API_OBJ_KEY_NUM_DRIVER)
  			return UVERBS_API_KEY_ERR;
  		id = id + UVERBS_API_OBJ_KEY_NUM_CORE;
  	} else {
  		if (id >= UVERBS_API_OBJ_KEY_NUM_CORE)
  			return UVERBS_API_KEY_ERR;
  	}
  
  	return id << UVERBS_API_OBJ_KEY_SHIFT;
  }
  
  static inline __attribute_const__ bool uapi_key_is_object(u32 key)
  {
  	return (key & ~UVERBS_API_OBJ_KEY_MASK) == 0;
  }
  
  static inline __attribute_const__ u32 uapi_key_ioctl_method(u32 id)
  {
  	if (id & UVERBS_API_NS_FLAG) {
  		id &= ~UVERBS_API_NS_FLAG;
  		if (id >= UVERBS_API_METHOD_KEY_NUM_DRIVER)
  			return UVERBS_API_KEY_ERR;
  		id = id + UVERBS_API_METHOD_KEY_NUM_CORE;
  	} else {
  		id++;
  		if (id >= UVERBS_API_METHOD_KEY_NUM_CORE)
  			return UVERBS_API_KEY_ERR;
  	}
  
  	return id << UVERBS_API_METHOD_KEY_SHIFT;
  }
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  static inline __attribute_const__ u32 uapi_key_write_method(u32 id)
  {
  	if (id >= UVERBS_API_WRITE_KEY_NUM)
  		return UVERBS_API_KEY_ERR;
  	return UVERBS_API_METHOD_IS_WRITE | id;
  }
  
  static inline __attribute_const__ u32 uapi_key_write_ex_method(u32 id)
  {
  	if (id >= UVERBS_API_WRITE_KEY_NUM)
  		return UVERBS_API_KEY_ERR;
  	return UVERBS_API_METHOD_IS_WRITE_EX | id;
  }
  
  static inline __attribute_const__ u32
  uapi_key_attr_to_ioctl_method(u32 attr_key)
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
204
205
206
207
208
209
210
  {
  	return attr_key &
  	       (UVERBS_API_OBJ_KEY_MASK | UVERBS_API_METHOD_KEY_MASK);
  }
  
  static inline __attribute_const__ bool uapi_key_is_ioctl_method(u32 key)
  {
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
211
212
213
  	unsigned int method = key & UVERBS_API_METHOD_KEY_MASK;
  
  	return method != 0 && method < UVERBS_API_METHOD_IS_WRITE &&
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
214
215
  	       (key & UVERBS_API_ATTR_KEY_MASK) == 0;
  }
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
216
217
218
219
220
221
222
223
224
225
  static inline __attribute_const__ bool uapi_key_is_write_method(u32 key)
  {
  	return (key & UVERBS_API_METHOD_KEY_MASK) == UVERBS_API_METHOD_IS_WRITE;
  }
  
  static inline __attribute_const__ bool uapi_key_is_write_ex_method(u32 key)
  {
  	return (key & UVERBS_API_METHOD_KEY_MASK) ==
  	       UVERBS_API_METHOD_IS_WRITE_EX;
  }
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  static inline __attribute_const__ u32 uapi_key_attrs_start(u32 ioctl_method_key)
  {
  	/* 0 is the method slot itself */
  	return ioctl_method_key + 1;
  }
  
  static inline __attribute_const__ u32 uapi_key_attr(u32 id)
  {
  	/*
  	 * The attr is designed to fit in the typical single radix tree node
  	 * of 64 entries. Since allmost all methods have driver attributes we
  	 * organize things so that the driver and core attributes interleave to
  	 * reduce the length of the attributes array in typical cases.
  	 */
  	if (id & UVERBS_API_NS_FLAG) {
  		id &= ~UVERBS_API_NS_FLAG;
  		id++;
  		if (id >= 1 << (UVERBS_API_ATTR_KEY_BITS - 1))
  			return UVERBS_API_KEY_ERR;
  		id = (id << 1) | 0;
  	} else {
  		if (id >= 1 << (UVERBS_API_ATTR_KEY_BITS - 1))
  			return UVERBS_API_KEY_ERR;
  		id = (id << 1) | 1;
  	}
  
  	return id;
  }
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
254
  /* Only true for ioctl methods */
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
255
256
  static inline __attribute_const__ bool uapi_key_is_attr(u32 key)
  {
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
257
258
259
  	unsigned int method = key & UVERBS_API_METHOD_KEY_MASK;
  
  	return method != 0 && method < UVERBS_API_METHOD_IS_WRITE &&
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
260
261
262
263
264
265
266
267
268
269
270
271
272
  	       (key & UVERBS_API_ATTR_KEY_MASK) != 0;
  }
  
  /*
   * This returns a value in the range [0 to UVERBS_API_ATTR_BKEY_LEN),
   * basically it undoes the reservation of 0 in the ID numbering. attr_key
   * must already be masked with UVERBS_API_ATTR_KEY_MASK, or be the output of
   * uapi_key_attr().
   */
  static inline __attribute_const__ u32 uapi_bkey_attr(u32 attr_key)
  {
  	return attr_key - 1;
  }
70cd20aed   Guy Levi   IB/uverbs: Add ID...
273
274
275
276
  static inline __attribute_const__ u32 uapi_bkey_to_key_attr(u32 attr_bkey)
  {
  	return attr_bkey + 1;
  }
9ed3e5f44   Jason Gunthorpe   IB/uverbs: Build ...
277
  /*
5009010fb   Matan Barak   IB/core: Declare ...
278
279
280
281
   * =======================================
   *	Verbs definitions
   * =======================================
   */
09e3ebf8c   Matan Barak   IB/core: Add DEVI...
282
283
284
285
286
287
288
289
290
291
292
  struct uverbs_attr_def {
  	u16                           id;
  	struct uverbs_attr_spec       attr;
  };
  
  struct uverbs_method_def {
  	u16                                  id;
  	/* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
  	u32				     flags;
  	size_t				     num_attrs;
  	const struct uverbs_attr_def * const (*attrs)[];
15a1b4bec   Jason Gunthorpe   RDMA/uverbs: Do n...
293
  	int (*handler)(struct uverbs_attr_bundle *attrs);
09e3ebf8c   Matan Barak   IB/core: Add DEVI...
294
  };
5009010fb   Matan Barak   IB/core: Declare ...
295
  struct uverbs_object_def {
09e3ebf8c   Matan Barak   IB/core: Add DEVI...
296
  	u16					 id;
5009010fb   Matan Barak   IB/core: Declare ...
297
  	const struct uverbs_obj_type	        *type_attrs;
09e3ebf8c   Matan Barak   IB/core: Add DEVI...
298
299
300
  	size_t				         num_methods;
  	const struct uverbs_method_def * const (*methods)[];
  };
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
301
302
  enum uapi_definition_kind {
  	UAPI_DEF_END = 0,
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
303
304
  	UAPI_DEF_OBJECT_START,
  	UAPI_DEF_WRITE,
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
305
306
  	UAPI_DEF_CHAIN_OBJ_TREE,
  	UAPI_DEF_CHAIN,
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
307
308
309
310
311
312
  	UAPI_DEF_IS_SUPPORTED_FUNC,
  	UAPI_DEF_IS_SUPPORTED_DEV_FN,
  };
  
  enum uapi_definition_scope {
  	UAPI_SCOPE_OBJECT = 1,
a140692a5   Jason Gunthorpe   RDMA/uverbs: Chec...
313
  	UAPI_SCOPE_METHOD = 2,
5009010fb   Matan Barak   IB/core: Declare ...
314
  };
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
315
316
  struct uapi_definition {
  	u8 kind;
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
317
  	u8 scope;
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
318
319
320
321
  	union {
  		struct {
  			u16 object_id;
  		} object_start;
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
322
  		struct {
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
323
  			u16 command_num;
669dac1e0   Jason Gunthorpe   RDMA/uverbs: Add ...
324
325
326
327
328
  			u8 is_ex:1;
  			u8 has_udata:1;
  			u8 has_resp:1;
  			u8 req_size;
  			u8 resp_size;
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
329
  		} write;
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
330
331
332
  	};
  
  	union {
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
333
  		bool (*func_is_supported)(struct ib_device *device);
974d6b4b2   Jason Gunthorpe   RDMA/uverbs: Use ...
334
  		int (*func_write)(struct uverbs_attr_bundle *attrs);
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
335
336
  		const struct uapi_definition *chain;
  		const struct uverbs_object_def *chain_obj_tree;
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
337
  		size_t needs_fn_offset;
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
338
339
  	};
  };
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
340
341
342
343
344
345
346
347
348
  /* Define things connected to object_id */
  #define DECLARE_UVERBS_OBJECT(_object_id, ...)                                 \
  	{                                                                      \
  		.kind = UAPI_DEF_OBJECT_START,                                 \
  		.object_start = { .object_id = _object_id },                   \
  	},                                                                     \
  		##__VA_ARGS__
  
  /* Use in a var_args of DECLARE_UVERBS_OBJECT */
669dac1e0   Jason Gunthorpe   RDMA/uverbs: Add ...
349
  #define DECLARE_UVERBS_WRITE(_command_num, _func, _cmd_desc, ...)              \
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
350
351
352
353
354
  	{                                                                      \
  		.kind = UAPI_DEF_WRITE,                                        \
  		.scope = UAPI_SCOPE_OBJECT,                                    \
  		.write = { .is_ex = 0, .command_num = _command_num },          \
  		.func_write = _func,                                           \
669dac1e0   Jason Gunthorpe   RDMA/uverbs: Add ...
355
  		_cmd_desc,                                                     \
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
356
357
358
359
  	},                                                                     \
  		##__VA_ARGS__
  
  /* Use in a var_args of DECLARE_UVERBS_OBJECT */
669dac1e0   Jason Gunthorpe   RDMA/uverbs: Add ...
360
  #define DECLARE_UVERBS_WRITE_EX(_command_num, _func, _cmd_desc, ...)           \
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
361
362
363
364
  	{                                                                      \
  		.kind = UAPI_DEF_WRITE,                                        \
  		.scope = UAPI_SCOPE_OBJECT,                                    \
  		.write = { .is_ex = 1, .command_num = _command_num },          \
974d6b4b2   Jason Gunthorpe   RDMA/uverbs: Use ...
365
  		.func_write = _func,                                           \
669dac1e0   Jason Gunthorpe   RDMA/uverbs: Add ...
366
  		_cmd_desc,                                                     \
6884c6c4b   Jason Gunthorpe   RDMA/verbs: Store...
367
368
  	},                                                                     \
  		##__VA_ARGS__
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
369
370
371
372
373
374
375
376
377
  /*
   * Object is only supported if the function pointer named ibdev_fn in struct
   * ib_device is not NULL.
   */
  #define UAPI_DEF_OBJ_NEEDS_FN(ibdev_fn)                                        \
  	{                                                                      \
  		.kind = UAPI_DEF_IS_SUPPORTED_DEV_FN,                          \
  		.scope = UAPI_SCOPE_OBJECT,                                    \
  		.needs_fn_offset =                                             \
3023a1e93   Kamal Heib   RDMA: Start use i...
378
  			offsetof(struct ib_device_ops, ibdev_fn) +             \
bebcfe85f   Gustavo A. R. Silva   RDMA/core: Use si...
379
380
381
  			BUILD_BUG_ON_ZERO(sizeof_field(struct ib_device_ops,   \
  						       ibdev_fn) !=            \
  					  sizeof(void *)),                     \
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
382
  	}
a140692a5   Jason Gunthorpe   RDMA/uverbs: Chec...
383
384
385
386
387
388
389
390
391
  /*
   * Method is only supported if the function pointer named ibdev_fn in struct
   * ib_device is not NULL.
   */
  #define UAPI_DEF_METHOD_NEEDS_FN(ibdev_fn)                                     \
  	{                                                                      \
  		.kind = UAPI_DEF_IS_SUPPORTED_DEV_FN,                          \
  		.scope = UAPI_SCOPE_METHOD,                                    \
  		.needs_fn_offset =                                             \
3023a1e93   Kamal Heib   RDMA: Start use i...
392
  			offsetof(struct ib_device_ops, ibdev_fn) +             \
bebcfe85f   Gustavo A. R. Silva   RDMA/core: Use si...
393
394
395
  			BUILD_BUG_ON_ZERO(sizeof_field(struct ib_device_ops,   \
  						       ibdev_fn) !=            \
  					  sizeof(void *)),                     \
a140692a5   Jason Gunthorpe   RDMA/uverbs: Chec...
396
  	}
6829c1c2b   Jason Gunthorpe   RDMA/uverbs: Add ...
397
398
399
400
401
402
  /* Call a function to determine if the entire object is supported or not */
  #define UAPI_DEF_IS_OBJ_SUPPORTED(_func)                                       \
  	{                                                                      \
  		.kind = UAPI_DEF_IS_SUPPORTED_FUNC,                            \
  		.scope = UAPI_SCOPE_OBJECT, .func_is_supported = _func,        \
  	}
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
403
404
405
406
407
408
409
  /* Include another struct uapi_definition in this one */
  #define UAPI_DEF_CHAIN(_def_var)                                               \
  	{                                                                      \
  		.kind = UAPI_DEF_CHAIN, .chain = _def_var,                     \
  	}
  
  /* Temporary until the tree base description is replaced */
a1462351b   Leon Romanovsky   RDMA/mlx5: Fail e...
410
  #define UAPI_DEF_CHAIN_OBJ_TREE(_object_enum, _object_ptr, ...)                \
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
411
412
413
414
  	{                                                                      \
  		.kind = UAPI_DEF_CHAIN_OBJ_TREE,                               \
  		.object_start = { .object_id = _object_enum },                 \
  		.chain_obj_tree = _object_ptr,                                 \
a1462351b   Leon Romanovsky   RDMA/mlx5: Fail e...
415
  	},								       \
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
416
  		##__VA_ARGS__
a1462351b   Leon Romanovsky   RDMA/mlx5: Fail e...
417
418
419
  #define UAPI_DEF_CHAIN_OBJ_TREE_NAMED(_object_enum, ...)                       \
  	UAPI_DEF_CHAIN_OBJ_TREE(_object_enum, &UVERBS_OBJECT(_object_enum),    \
  				##__VA_ARGS__)
0cbf432db   Jason Gunthorpe   RDMA/uverbs: Use ...
420

d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
421
422
423
424
425
  /*
   * =======================================
   *	Attribute Specifications
   * =======================================
   */
c66db3111   Matan Barak   IB/uverbs: Safely...
426

c66db3111   Matan Barak   IB/uverbs: Safely...
427
  #define UVERBS_ATTR_SIZE(_min_len, _len)			\
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
428
  	.u.ptr.min_len = _min_len, .u.ptr.len = _len
422e3d37e   Jason Gunthorpe   RDMA/uverbs: Comb...
429

fd44e3853   Yishai Hadas   IB/mlx5: Introduc...
430
  #define UVERBS_ATTR_NO_DATA() UVERBS_ATTR_SIZE(0, 0)
422e3d37e   Jason Gunthorpe   RDMA/uverbs: Comb...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  /*
   * Specifies a uapi structure that cannot be extended. The user must always
   * supply the whole structure and nothing more. The structure must be declared
   * in a header under include/uapi/rdma.
   */
  #define UVERBS_ATTR_TYPE(_type)					\
  	.u.ptr.min_len = sizeof(_type), .u.ptr.len = sizeof(_type)
  /*
   * Specifies a uapi structure where the user must provide at least up to
   * member 'last'.  Anything after last and up until the end of the structure
   * can be non-zero, anything longer than the end of the structure must be
   * zero. The structure must be declared in a header under include/uapi/rdma.
   */
  #define UVERBS_ATTR_STRUCT(_type, _last)                                       \
  	.zero_trailing = 1,                                                    \
ffd7339a2   Jason Gunthorpe   RDMA/core: Use of...
446
  	UVERBS_ATTR_SIZE(offsetofend(_type, _last), sizeof(_type))
540cd6920   Jason Gunthorpe   RDMA/uverbs: Use ...
447
448
449
450
451
  /*
   * Specifies at least min_len bytes must be passed in, but the amount can be
   * larger, up to the protocol maximum size. No check for zeroing is done.
   */
  #define UVERBS_ATTR_MIN_SIZE(_min_len) UVERBS_ATTR_SIZE(_min_len, USHRT_MAX)
c66db3111   Matan Barak   IB/uverbs: Safely...
452

d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
453
  /* Must be used in the '...' of any UVERBS_ATTR */
83bb44423   Jason Gunthorpe   RDMA/uverbs: Remo...
454
455
  #define UA_ALLOC_AND_COPY .alloc_and_copy = 1
  #define UA_MANDATORY .mandatory = 1
83bb44423   Jason Gunthorpe   RDMA/uverbs: Remo...
456
  #define UA_OPTIONAL .mandatory = 0
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
457

70cd20aed   Guy Levi   IB/uverbs: Add ID...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  /*
   * min_len must be bigger than 0 and _max_len must be smaller than 4095.  Only
   * READ\WRITE accesses are supported.
   */
  #define UVERBS_ATTR_IDRS_ARR(_attr_id, _idr_type, _access, _min_len, _max_len, \
  			     ...)                                              \
  	(&(const struct uverbs_attr_def){                                      \
  		.id = (_attr_id) +                                             \
  		      BUILD_BUG_ON_ZERO((_min_len) == 0 ||                     \
  					(_max_len) >                           \
  						PAGE_SIZE / sizeof(void *) ||  \
  					(_min_len) > (_max_len) ||             \
  					(_access) == UVERBS_ACCESS_NEW ||      \
  					(_access) == UVERBS_ACCESS_DESTROY),   \
  		.attr = { .type = UVERBS_ATTR_TYPE_IDRS_ARRAY,                 \
  			  .u2.objs_arr.obj_type = _idr_type,                   \
  			  .u2.objs_arr.access = _access,                       \
  			  .u2.objs_arr.min_len = _min_len,                     \
  			  .u2.objs_arr.max_len = _max_len,                     \
  			  __VA_ARGS__ } })
4d7e8cc57   Yishai Hadas   IB/core: Introduc...
478
479
480
481
482
  /*
   * Only for use with UVERBS_ATTR_IDR, allows any uobject type to be accepted,
   * the user must validate the type of the uobject instead.
   */
  #define UVERBS_IDR_ANY_OBJECT 0xFFFF
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
483
  #define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...)                     \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
484
  	(&(const struct uverbs_attr_def){                                      \
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
485
486
487
488
489
490
491
  		.id = _attr_id,                                                \
  		.attr = { .type = UVERBS_ATTR_TYPE_IDR,                        \
  			  .u.obj.obj_type = _idr_type,                         \
  			  .u.obj.access = _access,                             \
  			  __VA_ARGS__ } })
  
  #define UVERBS_ATTR_FD(_attr_id, _fd_type, _access, ...)                       \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
492
  	(&(const struct uverbs_attr_def){                                      \
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
493
494
495
496
497
498
499
500
501
  		.id = (_attr_id) +                                             \
  		      BUILD_BUG_ON_ZERO((_access) != UVERBS_ACCESS_NEW &&      \
  					(_access) != UVERBS_ACCESS_READ),      \
  		.attr = { .type = UVERBS_ATTR_TYPE_FD,                         \
  			  .u.obj.obj_type = _fd_type,                          \
  			  .u.obj.access = _access,                             \
  			  __VA_ARGS__ } })
  
  #define UVERBS_ATTR_PTR_IN(_attr_id, _type, ...)                               \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
502
  	(&(const struct uverbs_attr_def){                                      \
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
503
504
505
506
507
508
  		.id = _attr_id,                                                \
  		.attr = { .type = UVERBS_ATTR_TYPE_PTR_IN,                     \
  			  _type,                                               \
  			  __VA_ARGS__ } })
  
  #define UVERBS_ATTR_PTR_OUT(_attr_id, _type, ...)                              \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
509
  	(&(const struct uverbs_attr_def){                                      \
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
510
511
512
513
514
515
516
  		.id = _attr_id,                                                \
  		.attr = { .type = UVERBS_ATTR_TYPE_PTR_OUT,                    \
  			  _type,                                               \
  			  __VA_ARGS__ } })
  
  /* _enum_arry should be a 'static const union uverbs_attr_spec[]' */
  #define UVERBS_ATTR_ENUM_IN(_attr_id, _enum_arr, ...)                          \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
517
  	(&(const struct uverbs_attr_def){                                      \
d108dac08   Jason Gunthorpe   RDMA/uverbs: Simp...
518
519
520
521
522
523
  		.id = _attr_id,                                                \
  		.attr = { .type = UVERBS_ATTR_TYPE_ENUM_IN,                    \
  			  .u2.enum_def.ids = _enum_arr,                        \
  			  .u.enum_def.num_elems = ARRAY_SIZE(_enum_arr),       \
  			  __VA_ARGS__ },                                       \
  	})
354103065   Matan Barak   IB/core: Add macr...
524

0953fffec   Mark Bloch   RDMA/uverbs: Add ...
525
526
527
528
529
530
531
532
  /* An input value that is a member in the enum _enum_type. */
  #define UVERBS_ATTR_CONST_IN(_attr_id, _enum_type, ...)                        \
  	UVERBS_ATTR_PTR_IN(                                                    \
  		_attr_id,                                                      \
  		UVERBS_ATTR_SIZE(                                              \
  			sizeof(u64) + BUILD_BUG_ON_ZERO(!sizeof(_enum_type)),  \
  			sizeof(u64)),                                          \
  		__VA_ARGS__)
354103065   Matan Barak   IB/core: Add macr...
533
  /*
bccd06223   Jason Gunthorpe   IB/uverbs: Add UV...
534
535
536
537
538
539
540
541
542
543
544
545
546
   * An input value that is a bitwise combination of values of _enum_type.
   * This permits the flag value to be passed as either a u32 or u64, it must
   * be retrieved via uverbs_get_flag().
   */
  #define UVERBS_ATTR_FLAGS_IN(_attr_id, _enum_type, ...)                        \
  	UVERBS_ATTR_PTR_IN(                                                    \
  		_attr_id,                                                      \
  		UVERBS_ATTR_SIZE(sizeof(u32) + BUILD_BUG_ON_ZERO(              \
  						       !sizeof(_enum_type *)), \
  				 sizeof(u64)),                                 \
  		__VA_ARGS__)
  
  /*
6c61d2a55   Jason Gunthorpe   RDMA/uverbs: Simp...
547
548
549
550
551
   * This spec is used in order to pass information to the hardware driver in a
   * legacy way. Every verb that could get driver specific data should get this
   * spec.
   */
  #define UVERBS_ATTR_UHW()                                                      \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
552
  	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_UHW_IN,                                 \
540cd6920   Jason Gunthorpe   RDMA/uverbs: Use ...
553
  			   UVERBS_ATTR_MIN_SIZE(0),			       \
07f05f40d   Jason Gunthorpe   RDMA/uverbs: Use ...
554
555
  			   UA_OPTIONAL,                                        \
  			   .is_udata = 1),				       \
9a119cd59   Jason Gunthorpe   RDMA/uverbs: Get ...
556
  	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_UHW_OUT,                               \
540cd6920   Jason Gunthorpe   RDMA/uverbs: Use ...
557
  			    UVERBS_ATTR_MIN_SIZE(0),			       \
07f05f40d   Jason Gunthorpe   RDMA/uverbs: Use ...
558
559
  			    UA_OPTIONAL,                                       \
  			    .is_udata = 1)
6c61d2a55   Jason Gunthorpe   RDMA/uverbs: Simp...
560

fac9658ca   Matan Barak   IB/core: Add new ...
561
562
563
564
  /* =================================================
   *              Parsing infrastructure
   * =================================================
   */
3a863577a   Jason Gunthorpe   IB/uverbs: Use uv...
565

fac9658ca   Matan Barak   IB/core: Add new ...
566
  struct uverbs_ptr_attr {
8762d149e   Matan Barak   IB/uverbs: Add PT...
567
568
569
570
571
572
573
574
  	/*
  	 * If UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY is set then the 'ptr' is
  	 * used.
  	 */
  	union {
  		void *ptr;
  		u64 data;
  	};
fac9658ca   Matan Barak   IB/core: Add new ...
575
  	u16		len;
6a1f444fe   Jason Gunthorpe   IB/uverbs: Remove...
576
  	u16		uattr_idx;
494c5580a   Matan Barak   IB/uverbs: Add en...
577
  	u8		enum_id;
fac9658ca   Matan Barak   IB/core: Add new ...
578
  };
f43dbebfa   Matan Barak   IB/core: Add supp...
579
580
  struct uverbs_obj_attr {
  	struct ib_uobject		*uobject;
3a863577a   Jason Gunthorpe   IB/uverbs: Use uv...
581
  	const struct uverbs_api_attr	*attr_elm;
f43dbebfa   Matan Barak   IB/core: Add supp...
582
  };
70cd20aed   Guy Levi   IB/uverbs: Add ID...
583
584
585
586
  struct uverbs_objs_arr_attr {
  	struct ib_uobject **uobjects;
  	u16 len;
  };
f43dbebfa   Matan Barak   IB/core: Add supp...
587
  struct uverbs_attr {
fac9658ca   Matan Barak   IB/core: Add new ...
588
589
590
  	union {
  		struct uverbs_ptr_attr	ptr_attr;
  		struct uverbs_obj_attr	obj_attr;
70cd20aed   Guy Levi   IB/uverbs: Add ID...
591
  		struct uverbs_objs_arr_attr objs_arr_attr;
fac9658ca   Matan Barak   IB/core: Add new ...
592
  	};
f43dbebfa   Matan Barak   IB/core: Add supp...
593
  };
f43dbebfa   Matan Barak   IB/core: Add supp...
594
  struct uverbs_attr_bundle {
ef87df2c7   Jason Gunthorpe   RDMA/uverbs: Use ...
595
  	struct ib_udata driver_udata;
c2a939fda   Jason Gunthorpe   RDMA/uverbs: Use ...
596
  	struct ib_udata ucore;
4b3dd2bbf   Jason Gunthorpe   IB/uverbs: Provid...
597
  	struct ib_uverbs_file *ufile;
3d9dfd060   Shamir Rabinovitch   IB/uverbs: Add ib...
598
  	struct ib_ucontext *context;
0f63ef1dd   Leon Romanovsky   RDMA/core: Align ...
599
  	struct ib_uobject *uobject;
3a863577a   Jason Gunthorpe   IB/uverbs: Use uv...
600
601
  	DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN);
  	struct uverbs_attr attrs[];
f43dbebfa   Matan Barak   IB/core: Add supp...
602
  };
354103065   Matan Barak   IB/core: Add macr...
603
604
605
  static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_bundle,
  					unsigned int idx)
  {
3a863577a   Jason Gunthorpe   IB/uverbs: Use uv...
606
607
  	return test_bit(uapi_bkey_attr(uapi_key_attr(idx)),
  			attrs_bundle->attr_present);
354103065   Matan Barak   IB/core: Add macr...
608
  }
730623f4a   Shamir Rabinovitch   IB/verbs: Add hel...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  /**
   * rdma_udata_to_drv_context - Helper macro to get the driver's context out of
   *                             ib_udata which is embedded in uverbs_attr_bundle.
   *
   * If udata is not NULL this cannot fail. Otherwise a NULL udata will result
   * in a NULL ucontext pointer, as a safety precaution. Callers should be using
   * 'udata' to determine if the driver call is in user or kernel mode, not
   * 'ucontext'.
   *
   */
  #define rdma_udata_to_drv_context(udata, drv_dev_struct, member)               \
  	(udata ? container_of(container_of(udata, struct uverbs_attr_bundle,   \
  					   driver_udata)                       \
  				      ->context,                               \
  			      drv_dev_struct, member) :                        \
  		 (drv_dev_struct *)NULL)
41b2a71fc   Matan Barak   IB/uverbs: Move i...
625
  #define IS_UVERBS_COPY_ERR(_ret)		((_ret) && (_ret) != -ENOENT)
d70724f14   Matan Barak   IB/core: Add lega...
626
627
628
  static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle,
  							u16 idx)
  {
d70724f14   Matan Barak   IB/core: Add lega...
629
630
  	if (!uverbs_attr_is_valid(attrs_bundle, idx))
  		return ERR_PTR(-ENOENT);
3a863577a   Jason Gunthorpe   IB/uverbs: Use uv...
631
  	return &attrs_bundle->attrs[uapi_bkey_attr(uapi_key_attr(idx))];
d70724f14   Matan Barak   IB/core: Add lega...
632
  }
494c5580a   Matan Barak   IB/uverbs: Add en...
633
634
635
636
637
638
639
640
641
642
  static inline int uverbs_attr_get_enum_id(const struct uverbs_attr_bundle *attrs_bundle,
  					  u16 idx)
  {
  	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
  
  	if (IS_ERR(attr))
  		return PTR_ERR(attr);
  
  	return attr->ptr_attr.enum_id;
  }
be934cca9   Ariel Levkovich   IB/uverbs: Add de...
643
644
645
  static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
  					u16 idx)
  {
f4602cbb0   Jason Gunthorpe   IB/uverbs: Fix uv...
646
  	const struct uverbs_attr *attr;
be934cca9   Ariel Levkovich   IB/uverbs: Add de...
647

f4602cbb0   Jason Gunthorpe   IB/uverbs: Fix uv...
648
649
650
  	attr = uverbs_attr_get(attrs_bundle, idx);
  	if (IS_ERR(attr))
  		return ERR_CAST(attr);
be934cca9   Ariel Levkovich   IB/uverbs: Add de...
651

f4602cbb0   Jason Gunthorpe   IB/uverbs: Fix uv...
652
  	return attr->obj_attr.uobject->object;
be934cca9   Ariel Levkovich   IB/uverbs: Add de...
653
  }
3efa38125   Matan Barak   IB/uverbs: Add an...
654
655
656
657
658
659
660
661
662
663
  static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_attr_bundle *attrs_bundle,
  							 u16 idx)
  {
  	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
  
  	if (IS_ERR(attr))
  		return ERR_CAST(attr);
  
  	return attr->obj_attr.uobject;
  }
8762d149e   Matan Barak   IB/uverbs: Add PT...
664
665
666
667
668
669
670
671
672
673
  static inline int
  uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
  {
  	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
  
  	if (IS_ERR(attr))
  		return PTR_ERR(attr);
  
  	return attr->ptr_attr.len;
  }
0ac8903cb   Jason Gunthorpe   RDMA/core: Allow ...
674
675
  void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *attrs_bundle,
  				 u16 idx);
cbfdd442c   Moni Shoua   IB/uverbs: Add he...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
  /*
   * uverbs_attr_ptr_get_array_size() - Get array size pointer by a ptr
   * attribute.
   * @attrs: The attribute bundle
   * @idx: The ID of the attribute
   * @elem_size: The size of the element in the array
   */
  static inline int
  uverbs_attr_ptr_get_array_size(struct uverbs_attr_bundle *attrs, u16 idx,
  			       size_t elem_size)
  {
  	int size = uverbs_attr_get_len(attrs, idx);
  
  	if (size < 0)
  		return size;
  
  	if (size % elem_size)
  		return -EINVAL;
  
  	return size / elem_size;
  }
70cd20aed   Guy Levi   IB/uverbs: Add ID...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
  /**
   * uverbs_attr_get_uobjs_arr() - Provides array's properties for attribute for
   * UVERBS_ATTR_TYPE_IDRS_ARRAY.
   * @arr: Returned pointer to array of pointers for uobjects or NULL if
   *       the attribute isn't provided.
   *
   * Return: The array length or 0 if no attribute was provided.
   */
  static inline int uverbs_attr_get_uobjs_arr(
  	const struct uverbs_attr_bundle *attrs_bundle, u16 attr_idx,
  	struct ib_uobject ***arr)
  {
  	const struct uverbs_attr *attr =
  			uverbs_attr_get(attrs_bundle, attr_idx);
  
  	if (IS_ERR(attr)) {
  		*arr = NULL;
  		return 0;
  	}
  
  	*arr = attr->objs_arr_attr.uobjects;
  
  	return attr->objs_arr_attr.len;
  }
89d9e8d3f   Matan Barak   IB/uverbs: Always...
721
722
723
724
  static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
  {
  	return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
  }
8762d149e   Matan Barak   IB/uverbs: Add PT...
725
726
727
728
729
730
731
732
733
734
735
  static inline void *uverbs_attr_get_alloced_ptr(
  	const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
  {
  	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
  
  	if (IS_ERR(attr))
  		return (void *)attr;
  
  	return uverbs_attr_ptr_is_inline(attr) ? (void *)&attr->ptr_attr.data :
  						 attr->ptr_attr.ptr;
  }
89d9e8d3f   Matan Barak   IB/uverbs: Always...
736
  static inline int _uverbs_copy_from(void *to,
d70724f14   Matan Barak   IB/core: Add lega...
737
  				    const struct uverbs_attr_bundle *attrs_bundle,
89d9e8d3f   Matan Barak   IB/uverbs: Always...
738
739
  				    size_t idx,
  				    size_t size)
d70724f14   Matan Barak   IB/core: Add lega...
740
741
742
743
744
  {
  	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
  
  	if (IS_ERR(attr))
  		return PTR_ERR(attr);
89d9e8d3f   Matan Barak   IB/uverbs: Always...
745
746
  	/*
  	 * Validation ensures attr->ptr_attr.len >= size. If the caller is
c66db3111   Matan Barak   IB/uverbs: Safely...
747
748
  	 * using UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO then it must call
  	 * uverbs_copy_from_or_zero.
89d9e8d3f   Matan Barak   IB/uverbs: Always...
749
750
751
752
753
  	 */
  	if (unlikely(size < attr->ptr_attr.len))
  		return -EINVAL;
  
  	if (uverbs_attr_ptr_is_inline(attr))
d70724f14   Matan Barak   IB/core: Add lega...
754
  		memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
2f36028ce   Jason Gunthorpe   IB/uverbs: Use u6...
755
756
  	else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
  				attr->ptr_attr.len))
d70724f14   Matan Barak   IB/core: Add lega...
757
758
759
760
  		return -EFAULT;
  
  	return 0;
  }
c66db3111   Matan Barak   IB/uverbs: Safely...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  static inline int _uverbs_copy_from_or_zero(void *to,
  					    const struct uverbs_attr_bundle *attrs_bundle,
  					    size_t idx,
  					    size_t size)
  {
  	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
  	size_t min_size;
  
  	if (IS_ERR(attr))
  		return PTR_ERR(attr);
  
  	min_size = min_t(size_t, size, attr->ptr_attr.len);
  
  	if (uverbs_attr_ptr_is_inline(attr))
  		memcpy(to, &attr->ptr_attr.data, min_size);
  	else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
  				min_size))
  		return -EFAULT;
  
  	if (size > min_size)
  		memset(to + min_size, 0, size - min_size);
  
  	return 0;
  }
d70724f14   Matan Barak   IB/core: Add lega...
785
  #define uverbs_copy_from(to, attrs_bundle, idx)				      \
89d9e8d3f   Matan Barak   IB/uverbs: Always...
786
  	_uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
d70724f14   Matan Barak   IB/core: Add lega...
787

c66db3111   Matan Barak   IB/uverbs: Safely...
788
789
  #define uverbs_copy_from_or_zero(to, attrs_bundle, idx)			      \
  	_uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
8313c10fa   Jason Gunthorpe   RDMA/uverbs: Repl...
790
791
792
793
794
  static inline struct ib_ucontext *
  ib_uverbs_get_ucontext(const struct uverbs_attr_bundle *attrs)
  {
  	return ib_uverbs_get_ucontext_file(attrs->ufile);
  }
bccd06223   Jason Gunthorpe   IB/uverbs: Add UV...
795
796
797
798
799
  #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
  int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
  		       size_t idx, u64 allowed_bits);
  int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
  		       size_t idx, u64 allowed_bits);
6a1f444fe   Jason Gunthorpe   IB/uverbs: Remove...
800
801
  int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, size_t idx,
  		   const void *from, size_t size);
461bb2eee   Jason Gunthorpe   IB/uverbs: Add a ...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size,
  			     gfp_t flags);
  
  static inline __malloc void *uverbs_alloc(struct uverbs_attr_bundle *bundle,
  					  size_t size)
  {
  	return _uverbs_alloc(bundle, size, GFP_KERNEL);
  }
  
  static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
  					   size_t size)
  {
  	return _uverbs_alloc(bundle, size, GFP_KERNEL | __GFP_ZERO);
  }
1cbcdec82   Avihai Horon   RDMA/uverbs: Fix ...
816
817
818
819
820
821
822
823
824
825
  
  static inline __malloc void *uverbs_kcalloc(struct uverbs_attr_bundle *bundle,
  					    size_t n, size_t size)
  {
  	size_t bytes;
  
  	if (unlikely(check_mul_overflow(n, size, &bytes)))
  		return ERR_PTR(-EOVERFLOW);
  	return uverbs_zalloc(bundle, bytes);
  }
0953fffec   Mark Bloch   RDMA/uverbs: Add ...
826
827
828
  int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
  		      size_t idx, s64 lower_bound, u64 upper_bound,
  		      s64 *def_val);
2e8039c65   Michael Guralnik   IB/core: uverbs c...
829
830
  int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
  				  size_t idx, const void *from, size_t size);
bccd06223   Jason Gunthorpe   IB/uverbs: Add UV...
831
832
833
834
835
836
837
838
839
840
841
842
843
  #else
  static inline int
  uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
  		   size_t idx, u64 allowed_bits)
  {
  	return -EINVAL;
  }
  static inline int
  uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
  		   size_t idx, u64 allowed_bits)
  {
  	return -EINVAL;
  }
6a1f444fe   Jason Gunthorpe   IB/uverbs: Remove...
844
845
846
847
848
  static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
  				 size_t idx, const void *from, size_t size)
  {
  	return -EINVAL;
  }
461bb2eee   Jason Gunthorpe   IB/uverbs: Add a ...
849
850
851
852
853
854
855
856
857
858
  static inline __malloc void *uverbs_alloc(struct uverbs_attr_bundle *bundle,
  					  size_t size)
  {
  	return ERR_PTR(-EINVAL);
  }
  static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
  					   size_t size)
  {
  	return ERR_PTR(-EINVAL);
  }
0953fffec   Mark Bloch   RDMA/uverbs: Add ...
859
860
861
862
863
864
865
  static inline int
  _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
  		  size_t idx, s64 lower_bound, u64 upper_bound,
  		  s64 *def_val)
  {
  	return -EINVAL;
  }
2e8039c65   Michael Guralnik   IB/core: uverbs c...
866
867
868
869
870
871
  static inline int
  uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
  			      size_t idx, const void *from, size_t size)
  {
  	return -EINVAL;
  }
bccd06223   Jason Gunthorpe   IB/uverbs: Add UV...
872
  #endif
0953fffec   Mark Bloch   RDMA/uverbs: Add ...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
  #define uverbs_get_const(_to, _attrs_bundle, _idx)                             \
  	({                                                                     \
  		s64 _val;                                                      \
  		int _ret = _uverbs_get_const(&_val, _attrs_bundle, _idx,       \
  					     type_min(typeof(*_to)),           \
  					     type_max(typeof(*_to)), NULL);    \
  		(*_to) = _val;                                                 \
  		_ret;                                                          \
  	})
  
  #define uverbs_get_const_default(_to, _attrs_bundle, _idx, _default)           \
  	({                                                                     \
  		s64 _val;                                                      \
  		s64 _def_val = _default;                                       \
  		int _ret =                                                     \
  			_uverbs_get_const(&_val, _attrs_bundle, _idx,          \
  					  type_min(typeof(*_to)),              \
  					  type_max(typeof(*_to)), &_def_val);  \
  		(*_to) = _val;                                                 \
  		_ret;                                                          \
  	})
118620d36   Matan Barak   IB/core: Add uver...
894
  #endif