• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  */
5 
6 #ifndef _LINUX_GUNYAH_H
7 #define _LINUX_GUNYAH_H
8 
9 #include <linux/bitfield.h>
10 #include <linux/errno.h>
11 #include <linux/interrupt.h>
12 #include <linux/limits.h>
13 #include <linux/list.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/types.h>
16 
17 #include <uapi/linux/gunyah.h>
18 
19 struct gunyah_vm;
20 
21 int __must_check gunyah_vm_get(struct gunyah_vm *ghvm);
22 void gunyah_vm_put(struct gunyah_vm *ghvm);
23 
24 /**
25  * struct gunyah_auth_vm_mgr_ops - Auth VM Mgr helper ops
26  * auth_vm_mgr driver will add the specific ops to setup the VM before
27  * the VM starts
28  * @pre_alloc_vmid: QTVMs have predetermined vmids. This callback can be
29  *              used by the auth vm mgr to request RM to assign the
30  *              same vmid for the VM. (Optional)
31  * @pre_vm_configure: Fill in the arguments of VM_CONFIGURE RM call. Most of
32  *                    the auth vm mgrs would need this, as different AUTH has
33  *                    a different layout of image or metadata or dtb offsets.
34  * @vm_authenticate: Callback to make an RM call if it is a qtvm. (Optional)
35  * @pre_vm_init: Callback before RM sets up all the objects/resources
36  *               needed by the VM. For ex, this would be when you can
37  *               choose to setup if you want demand paged VM or not. (Optional)
38  * @pre_vm_start: Callback for any setup before VM start where client
39  *                drivers can share/lend memory. (Optional)
40  * @pre_vm_reset: Callback for any cleanup before VM reset. All resources
41  *                tracked by RM will be cleaned at this stage (Optional)
42  * @post_vm_reset: Callback for any cleanup after VM reset (Optional)
43  * @start_fail: Needed when roll back is needed before auth_mgr can
44  *           clean up at a later stage.
45  **/
46 struct gunyah_auth_vm_mgr_ops {
47 	u16 (*pre_alloc_vmid)(struct gunyah_vm *ghvm);
48 	int (*pre_vm_configure)(struct gunyah_vm *ghvm);
49 	int (*vm_authenticate)(struct gunyah_vm *ghvm);
50 	int (*pre_vm_init)(struct gunyah_vm *ghvm);
51 	int (*pre_vm_start)(struct gunyah_vm *ghvm);
52 	int (*pre_vm_reset)(struct gunyah_vm *ghvm);
53 	int (*post_vm_reset)(struct gunyah_vm *ghvm);
54 	void (*vm_start_fail)(struct gunyah_vm *ghvm);
55 };
56 
57 /**
58  * struct gunyah_auth_vm - Represents an authentication type handler
59  * @type: value from &enum gunyah_auth_type
60  * @name: friendly name for debug purposes
61  * @mod: owner of the auth type
62  * @vm_attach: attach ops/private_data with the VM.
63  * @vm_detach: detach ops/private_data with the VM.
64  */
65 struct gunyah_auth_vm_mgr {
66 	u32 type;
67 	const char *name;
68 	struct module *mod;
69 	long (*vm_attach)(struct gunyah_vm *ghvm, struct gunyah_auth_desc *d);
70 	void (*vm_detach)(struct gunyah_vm *ghvm);
71 };
72 int gunyah_auth_vm_mgr_register(struct gunyah_auth_vm_mgr *auth_vm);
73 void gunyah_auth_vm_mgr_unregister(struct gunyah_auth_vm_mgr *auth_vm);
74 
75 struct gunyah_vm_function_instance;
76 /**
77  * struct gunyah_vm_function - Represents a function type
78  * @type: value from &enum gunyah_fn_type
79  * @name: friendly name for debug purposes
80  * @mod: owner of the function type
81  * @bind: Called when a new function of this type has been allocated.
82  * @unbind: Called when the function instance is being destroyed.
83  * @compare: Compare function instance @f's argument to the provided arg.
84  *           Return true if they are equivalent. Used on GUNYAH_VM_REMOVE_FUNCTION.
85  */
86 struct gunyah_vm_function {
87 	u32 type;
88 	const char *name;
89 	struct module *mod;
90 	long (*bind)(struct gunyah_vm_function_instance *f);
91 	void (*unbind)(struct gunyah_vm_function_instance *f);
92 	bool (*compare)(const struct gunyah_vm_function_instance *f,
93 			const void *arg, size_t size);
94 };
95 
96 /**
97  * struct gunyah_vm_function_instance - Represents one function instance
98  * @arg_size: size of user argument
99  * @argp: pointer to user argument
100  * @ghvm: Pointer to VM instance
101  * @rm: Pointer to resource manager for the VM instance
102  * @fn: The ops for the function
103  * @data: Private data for function
104  * @vm_list: for gunyah_vm's functions list
105  */
106 struct gunyah_vm_function_instance {
107 	size_t arg_size;
108 	void *argp;
109 	struct gunyah_vm *ghvm;
110 	struct gunyah_rm *rm;
111 	struct gunyah_vm_function *fn;
112 	void *data;
113 	struct list_head vm_list;
114 };
115 
116 int gunyah_vm_function_register(struct gunyah_vm_function *f);
117 void gunyah_vm_function_unregister(struct gunyah_vm_function *f);
118 
119 /* Since the function identifiers were setup in a uapi header as an
120  * enum and we do no want to change that, the user must supply the expanded
121  * constant as well and the compiler checks they are the same.
122  * See also MODULE_ALIAS_RDMA_NETLINK.
123  */
124 #define MODULE_ALIAS_GUNYAH_VM_FUNCTION(_type, _idx)        \
125 	static inline void __maybe_unused __chk##_idx(void) \
126 	{                                                   \
127 		BUILD_BUG_ON(_type != _idx);                \
128 	}                                                   \
129 	MODULE_ALIAS("ghfunc:" __stringify(_idx))
130 
131 #define DECLARE_GUNYAH_VM_FUNCTION(_name, _type, _bind, _unbind, _compare) \
132 	static struct gunyah_vm_function _name = {                         \
133 		.type = _type,                                             \
134 		.name = __stringify(_name),                                \
135 		.mod = THIS_MODULE,                                        \
136 		.bind = _bind,                                             \
137 		.unbind = _unbind,                                         \
138 		.compare = _compare,                                       \
139 	}
140 
141 #define module_gunyah_vm_function(__gf)                  \
142 	module_driver(__gf, gunyah_vm_function_register, \
143 		      gunyah_vm_function_unregister)
144 
145 #define DECLARE_GUNYAH_VM_FUNCTION_INIT(_name, _type, _idx, _bind, _unbind, \
146 					_compare)                           \
147 	DECLARE_GUNYAH_VM_FUNCTION(_name, _type, _bind, _unbind, _compare); \
148 	module_gunyah_vm_function(_name);                                   \
149 	MODULE_ALIAS_GUNYAH_VM_FUNCTION(_type, _idx)
150 
151 /* Matches resource manager's resource types for VM_GET_HYP_RESOURCES RPC */
152 enum gunyah_resource_type {
153 	/* clang-format off */
154 	GUNYAH_RESOURCE_TYPE_BELL_TX	= 0,
155 	GUNYAH_RESOURCE_TYPE_BELL_RX	= 1,
156 	GUNYAH_RESOURCE_TYPE_MSGQ_TX	= 2,
157 	GUNYAH_RESOURCE_TYPE_MSGQ_RX	= 3,
158 	GUNYAH_RESOURCE_TYPE_VCPU	= 4,
159 	GUNYAH_RESOURCE_TYPE_MEM_EXTENT	= 9,
160 	GUNYAH_RESOURCE_TYPE_ADDR_SPACE	= 10,
161 	/* clang-format on */
162 };
163 
164 struct gunyah_resource {
165 	enum gunyah_resource_type type;
166 	u64 capid;
167 	unsigned int irq;
168 
169 	struct list_head list;
170 	u32 rm_label;
171 };
172 
173 /**
174  * struct gunyah_vm_resource_ticket - Represents a ticket to reserve access to VM resource(s)
175  * @vm_list: for @gunyah_vm->resource_tickets
176  * @resources: List of resource(s) associated with this ticket
177  *             (members are from @gunyah_resource->list)
178  * @resource_type: Type of resource this ticket reserves
179  * @label: Label of the resource from resource manager this ticket reserves.
180  * @owner: owner of the ticket
181  * @populate: callback provided by the ticket owner and called when a resource is found that
182  *            matches @resource_type and @label. Note that this callback could be called
183  *            multiple times if userspace created mutliple resources with the same type/label.
184  *            This callback may also have significant delay after gunyah_vm_add_resource_ticket()
185  *            since gunyah_vm_add_resource_ticket() could be called before the VM starts.
186  * @unpopulate: callback provided by the ticket owner and called when the ticket owner should no
187  *              longer use the resource provided in the argument. When unpopulate() returns,
188  *              the ticket owner should not be able to use the resource any more as the resource
189  *              might being freed.
190  */
191 struct gunyah_vm_resource_ticket {
192 	struct list_head vm_list;
193 	struct list_head resources;
194 	enum gunyah_resource_type resource_type;
195 	u32 label;
196 
197 	struct module *owner;
198 	bool (*populate)(struct gunyah_vm_resource_ticket *ticket,
199 			 struct gunyah_resource *ghrsc);
200 	void (*unpopulate)(struct gunyah_vm_resource_ticket *ticket,
201 			   struct gunyah_resource *ghrsc);
202 };
203 
204 int gunyah_vm_add_resource_ticket(struct gunyah_vm *ghvm,
205 				  struct gunyah_vm_resource_ticket *ticket);
206 void gunyah_vm_remove_resource_ticket(struct gunyah_vm *ghvm,
207 				      struct gunyah_vm_resource_ticket *ticket);
208 
209 /*
210  * gunyah_vm_io_handler contains the info about an io device and its associated
211  * addr and the ops associated with the io device.
212  */
213 struct gunyah_vm_io_handler {
214 	struct rb_node node;
215 	u64 addr;
216 
217 	bool datamatch;
218 	u8 len;
219 	u64 data;
220 	struct gunyah_vm_io_handler_ops *ops;
221 };
222 
223 /*
224  * gunyah_vm_io_handler_ops contains function pointers associated with an iodevice.
225  */
226 struct gunyah_vm_io_handler_ops {
227 	int (*read)(struct gunyah_vm_io_handler *io_dev, u64 addr, u32 len,
228 		    u64 data);
229 	int (*write)(struct gunyah_vm_io_handler *io_dev, u64 addr, u32 len,
230 		     u64 data);
231 };
232 
233 int gunyah_vm_add_io_handler(struct gunyah_vm *ghvm,
234 			     struct gunyah_vm_io_handler *io_dev);
235 void gunyah_vm_remove_io_handler(struct gunyah_vm *ghvm,
236 				 struct gunyah_vm_io_handler *io_dev);
237 
238 #define GUNYAH_RM_ACL_X BIT(0)
239 #define GUNYAH_RM_ACL_W BIT(1)
240 #define GUNYAH_RM_ACL_R BIT(2)
241 
242 struct gunyah_rm_mem_acl_entry {
243 	__le16 vmid;
244 	u8 perms;
245 	u8 reserved;
246 } __packed;
247 
248 struct gunyah_rm_mem_entry {
249 	__le64 phys_addr;
250 	__le64 size;
251 } __packed;
252 
253 enum gunyah_rm_mem_type {
254 	GUNYAH_RM_MEM_TYPE_NORMAL = 0,
255 	GUNYAH_RM_MEM_TYPE_IO = 1,
256 };
257 
258 /*
259  * struct gunyah_rm_mem_parcel - Info about memory to be lent/shared/donated/reclaimed
260  * @mem_type: The type of memory: normal (DDR) or IO
261  * @label: An client-specified identifier which can be used by the other VMs to identify the purpose
262  *         of the memory parcel.
263  * @n_acl_entries: Count of the number of entries in the @acl_entries array.
264  * @acl_entries: An array of access control entries. Each entry specifies a VM and what access
265  *               is allowed for the memory parcel.
266  * @n_mem_entries: Count of the number of entries in the @mem_entries array.
267  * @mem_entries: An array of regions to be associated with the memory parcel. Addresses should be
268  *               (intermediate) physical addresses from Linux's perspective.
269  * @mem_handle: On success, filled with memory handle that RM allocates for this memory parcel
270  */
271 struct gunyah_rm_mem_parcel {
272 	enum gunyah_rm_mem_type mem_type;
273 	u32 label;
274 	size_t n_acl_entries;
275 	struct gunyah_rm_mem_acl_entry *acl_entries;
276 	size_t n_mem_entries;
277 	struct gunyah_rm_mem_entry *mem_entries;
278 	u32 mem_handle;
279 };
280 
281 enum gunyah_pagetable_access {
282 	/* clang-format off */
283 	GUNYAH_PAGETABLE_ACCESS_NONE		= 0,
284 	GUNYAH_PAGETABLE_ACCESS_X		= 1,
285 	GUNYAH_PAGETABLE_ACCESS_W		= 2,
286 	GUNYAH_PAGETABLE_ACCESS_R		= 4,
287 	GUNYAH_PAGETABLE_ACCESS_RX		= 5,
288 	GUNYAH_PAGETABLE_ACCESS_RW		= 6,
289 	GUNYAH_PAGETABLE_ACCESS_RWX		= 7,
290 	/* clang-format on */
291 };
292 
293 struct gunyah_rm_platform_ops {
294 	int (*pre_mem_share)(struct gunyah_rm *rm,
295 			     struct gunyah_rm_mem_parcel *mem_parcel);
296 	int (*post_mem_reclaim)(struct gunyah_rm *rm,
297 				struct gunyah_rm_mem_parcel *mem_parcel);
298 
299 	int (*pre_demand_page)(struct gunyah_rm *rm, u16 vmid,
300 			       enum gunyah_pagetable_access access,
301 			       struct folio *folio);
302 	int (*release_demand_page)(struct gunyah_rm *rm, u16 vmid,
303 				   enum gunyah_pagetable_access access,
304 				   struct folio *folio);
305 };
306 
307 #if IS_ENABLED(CONFIG_GUNYAH_PLATFORM_HOOKS)
308 int gunyah_rm_register_platform_ops(
309 	const struct gunyah_rm_platform_ops *platform_ops);
310 void gunyah_rm_unregister_platform_ops(
311 	const struct gunyah_rm_platform_ops *platform_ops);
312 int devm_gunyah_rm_register_platform_ops(
313 	struct device *dev, const struct gunyah_rm_platform_ops *ops);
314 #else
gunyah_rm_register_platform_ops(const struct gunyah_rm_platform_ops * platform_ops)315 static inline int gunyah_rm_register_platform_ops(
316 	const struct gunyah_rm_platform_ops *platform_ops)
317 {
318 	return 0;
319 }
gunyah_rm_unregister_platform_ops(const struct gunyah_rm_platform_ops * platform_ops)320 static inline void gunyah_rm_unregister_platform_ops(
321 	const struct gunyah_rm_platform_ops *platform_ops)
322 {
323 }
324 static inline int
devm_gunyah_rm_register_platform_ops(struct device * dev,const struct gunyah_rm_platform_ops * ops)325 devm_gunyah_rm_register_platform_ops(struct device *dev,
326 				     const struct gunyah_rm_platform_ops *ops)
327 {
328 	return 0;
329 }
330 #endif
331 
332 /******************************************************************************/
333 /* Common arch-independent definitions for Gunyah hypercalls                  */
334 #define GUNYAH_CAPID_INVAL U64_MAX
335 #define GUNYAH_VMID_ROOT_VM 0xff
336 
337 enum gunyah_error {
338 	/* clang-format off */
339 	GUNYAH_ERROR_OK				= 0,
340 	GUNYAH_ERROR_UNIMPLEMENTED		= -1,
341 	GUNYAH_ERROR_RETRY			= -2,
342 
343 	GUNYAH_ERROR_ARG_INVAL			= 1,
344 	GUNYAH_ERROR_ARG_SIZE			= 2,
345 	GUNYAH_ERROR_ARG_ALIGN			= 3,
346 
347 	GUNYAH_ERROR_NOMEM			= 10,
348 
349 	GUNYAH_ERROR_ADDR_OVFL			= 20,
350 	GUNYAH_ERROR_ADDR_UNFL			= 21,
351 	GUNYAH_ERROR_ADDR_INVAL			= 22,
352 
353 	GUNYAH_ERROR_DENIED			= 30,
354 	GUNYAH_ERROR_BUSY			= 31,
355 	GUNYAH_ERROR_IDLE			= 32,
356 
357 	GUNYAH_ERROR_IRQ_BOUND			= 40,
358 	GUNYAH_ERROR_IRQ_UNBOUND		= 41,
359 
360 	GUNYAH_ERROR_CSPACE_CAP_NULL		= 50,
361 	GUNYAH_ERROR_CSPACE_CAP_REVOKED		= 51,
362 	GUNYAH_ERROR_CSPACE_WRONG_OBJ_TYPE	= 52,
363 	GUNYAH_ERROR_CSPACE_INSUF_RIGHTS	= 53,
364 	GUNYAH_ERROR_CSPACE_FULL		= 54,
365 
366 	GUNYAH_ERROR_MSGQUEUE_EMPTY		= 60,
367 	GUNYAH_ERROR_MSGQUEUE_FULL		= 61,
368 	/* clang-format on */
369 };
370 
371 /**
372  * gunyah_error_remap() - Remap Gunyah hypervisor errors into a Linux error code
373  * @gunyah_error: Gunyah hypercall return value
374  */
gunyah_error_remap(enum gunyah_error gunyah_error)375 static inline int gunyah_error_remap(enum gunyah_error gunyah_error)
376 {
377 	switch (gunyah_error) {
378 	case GUNYAH_ERROR_OK:
379 		return 0;
380 	case GUNYAH_ERROR_NOMEM:
381 		return -ENOMEM;
382 	case GUNYAH_ERROR_DENIED:
383 	case GUNYAH_ERROR_CSPACE_CAP_NULL:
384 	case GUNYAH_ERROR_CSPACE_CAP_REVOKED:
385 	case GUNYAH_ERROR_CSPACE_WRONG_OBJ_TYPE:
386 	case GUNYAH_ERROR_CSPACE_INSUF_RIGHTS:
387 		return -EACCES;
388 	case GUNYAH_ERROR_CSPACE_FULL:
389 	case GUNYAH_ERROR_BUSY:
390 	case GUNYAH_ERROR_IDLE:
391 		return -EBUSY;
392 	case GUNYAH_ERROR_IRQ_BOUND:
393 	case GUNYAH_ERROR_IRQ_UNBOUND:
394 	case GUNYAH_ERROR_MSGQUEUE_FULL:
395 	case GUNYAH_ERROR_MSGQUEUE_EMPTY:
396 		return -EIO;
397 	case GUNYAH_ERROR_UNIMPLEMENTED:
398 		return -EOPNOTSUPP;
399 	case GUNYAH_ERROR_RETRY:
400 		return -EAGAIN;
401 	default:
402 		return -EINVAL;
403 	}
404 }
405 
406 enum gunyah_api_feature {
407 	/* clang-format off */
408 	GUNYAH_FEATURE_DOORBELL		= 1,
409 	GUNYAH_FEATURE_MSGQUEUE		= 2,
410 	GUNYAH_FEATURE_VCPU		= 5,
411 	GUNYAH_FEATURE_MEMEXTENT	= 6,
412 	/* clang-format on */
413 };
414 
415 bool arch_is_gunyah_guest(void);
416 
417 enum gunyah_info_owner {
418 	/* clang-format off */
419 	GUNYAH_INFO_OWNER_INVALID	= 0,
420 	GUNYAH_INFO_OWNER_HYP		= 1,
421 	GUNYAH_INFO_OWNER_ROOTVM	= 2,
422 	GUNYAH_INFO_OWNER_RM		= 3,
423 	GUNYAH_INFO_OWNER_QCRM		= 16,
424 	/* clang-format on */
425 };
426 
427 void *gunyah_get_info(u16 owner, u16 id, size_t *size);
428 
429 #define GUNYAH_API_V1 1
430 
431 /* Other bits reserved for future use and will be zero */
432 /* clang-format off */
433 #define GUNYAH_API_INFO_API_VERSION_MASK	GENMASK_ULL(13, 0)
434 #define GUNYAH_API_INFO_BIG_ENDIAN		BIT_ULL(14)
435 #define GUNYAH_API_INFO_IS_64BIT		BIT_ULL(15)
436 #define GUNYAH_API_INFO_VARIANT_MASK 		GENMASK_ULL(63, 56)
437 /* clang-format on */
438 
439 struct gunyah_hypercall_hyp_identify_resp {
440 	u64 api_info;
441 	u64 flags[3];
442 };
443 
444 static inline u16
gunyah_api_version(const struct gunyah_hypercall_hyp_identify_resp * gunyah_api)445 gunyah_api_version(const struct gunyah_hypercall_hyp_identify_resp *gunyah_api)
446 {
447 	return FIELD_GET(GUNYAH_API_INFO_API_VERSION_MASK,
448 			 gunyah_api->api_info);
449 }
450 
451 void gunyah_hypercall_hyp_identify(
452 	struct gunyah_hypercall_hyp_identify_resp *hyp_identity);
453 
454 enum gunyah_error gunyah_hypercall_bell_send(u64 capid, u64 new_flags,
455 					     u64 *old_flags);
456 enum gunyah_error gunyah_hypercall_bell_set_mask(u64 capid, u64 enable_mask,
457 						 u64 ack_mask);
458 
459 /* Immediately raise RX vIRQ on receiver VM */
460 #define GUNYAH_HYPERCALL_MSGQ_TX_FLAGS_PUSH BIT(0)
461 
462 enum gunyah_error gunyah_hypercall_msgq_send(u64 capid, size_t size, void *buff,
463 					     u64 tx_flags, bool *ready);
464 enum gunyah_error gunyah_hypercall_msgq_recv(u64 capid, void *buff, size_t size,
465 					     size_t *recv_size, bool *ready);
466 
467 #define GUNYAH_ADDRSPACE_SELF_CAP 0
468 
469 /* clang-format off */
470 #define GUNYAH_MEMEXTENT_MAPPING_USER_ACCESS		GENMASK_ULL(2, 0)
471 #define GUNYAH_MEMEXTENT_MAPPING_KERNEL_ACCESS		GENMASK_ULL(6, 4)
472 #define GUNYAH_MEMEXTENT_MAPPING_TYPE			GENMASK_ULL(23, 16)
473 /* clang-format on */
474 
475 enum gunyah_memextent_donate_type {
476 	/* clang-format off */
477 	GUNYAH_MEMEXTENT_DONATE_TO_CHILD		= 0,
478 	GUNYAH_MEMEXTENT_DONATE_TO_PARENT		= 1,
479 	GUNYAH_MEMEXTENT_DONATE_TO_SIBLING		= 2,
480 	GUNYAH_MEMEXTENT_DONATE_TO_PROTECTED		= 3,
481 	GUNYAH_MEMEXTENT_DONATE_FROM_PROTECTED		= 4,
482 	/* clang-format on */
483 };
484 
485 enum gunyah_addrspace_map_flag_bits {
486 	/* clang-format off */
487 	GUNYAH_ADDRSPACE_MAP_FLAG_PARTIAL	= 0,
488 	GUNYAH_ADDRSPACE_MAP_FLAG_PRIVATE	= 1,
489 	GUNYAH_ADDRSPACE_MAP_FLAG_VMMIO		= 2,
490 	GUNYAH_ADDRSPACE_MAP_FLAG_NOSYNC	= 31,
491 	/* clang-format on */
492 };
493 
494 enum gunyah_error gunyah_hypercall_addrspace_map(u64 capid, u64 extent_capid,
495 						 u64 vbase, u32 extent_attrs,
496 						 u32 flags, u64 offset,
497 						 u64 size);
498 enum gunyah_error gunyah_hypercall_addrspace_unmap(u64 capid, u64 extent_capid,
499 						   u64 vbase, u32 flags,
500 						   u64 offset, u64 size);
501 
502 /* clang-format off */
503 #define GUNYAH_MEMEXTENT_OPTION_TYPE_MASK	GENMASK_ULL(7, 0)
504 #define GUNYAH_MEMEXTENT_OPTION_NOSYNC		BIT(31)
505 /* clang-format on */
506 
507 enum gunyah_error gunyah_hypercall_memextent_donate(u32 options, u64 from_capid,
508 						    u64 to_capid, u64 offset,
509 						    u64 size);
510 
511 struct gunyah_hypercall_vcpu_run_resp {
512 	union {
513 		enum {
514 			/* clang-format off */
515 			/* VCPU is ready to run */
516 			GUNYAH_VCPU_STATE_READY			= 0,
517 			/* VCPU is sleeping until an interrupt arrives */
518 			GUNYAH_VCPU_STATE_EXPECTS_WAKEUP	= 1,
519 			/* VCPU is powered off */
520 			GUNYAH_VCPU_STATE_POWERED_OFF		= 2,
521 			/* VCPU is blocked in EL2 for unspecified reason */
522 			GUNYAH_VCPU_STATE_BLOCKED		= 3,
523 			/* VCPU has returned for MMIO READ */
524 			GUNYAH_VCPU_ADDRSPACE_VMMIO_READ	= 4,
525 			/* VCPU has returned for MMIO WRITE */
526 			GUNYAH_VCPU_ADDRSPACE_VMMIO_WRITE	= 5,
527 			/* VCPU blocked on fault where we can demand page */
528 			GUNYAH_VCPU_ADDRSPACE_PAGE_FAULT	= 7,
529 			/* VCPU is powered off due to some system event/reset */
530 			GUNYAH_VCPU_STATE_SYSTEM_OFF		= 0x100,
531 			/* clang-format on */
532 		} state;
533 		u64 sized_state;
534 	};
535 	u64 state_data[3];
536 };
537 
538 enum {
539 	GUNYAH_ADDRSPACE_VMMIO_ACTION_EMULATE = 0,
540 	GUNYAH_ADDRSPACE_VMMIO_ACTION_RETRY = 1,
541 	GUNYAH_ADDRSPACE_VMMIO_ACTION_FAULT = 2,
542 };
543 
544 /**
545  * struct gunyah_vcpu - Track an instance of gunyah vCPU
546  * @f: Function instance (how we get associated with the main VM)
547  * @rsc: Pointer to the Gunyah vCPU resource, will be NULL until VM starts
548  * @run_lock: One userspace thread at a time should run the vCPU
549  * @ghvm: Pointer to the main VM struct; quicker look up than going through
550  *        @f->ghvm
551  * @vcpu_run: Pointer to page shared with userspace to communicate vCPU state
552  * @state: Our copy of the state of the vCPU, since userspace could trick
553  *         kernel to behave incorrectly if we relied on @vcpu_run
554  * @mmio_read_len: Our copy of @vcpu_run->mmio.len; see also @state
555  * @mmio_addr: Our copy of @vcpu_run->mmio.phys_addr; see also @state
556  * @ready: if vCPU goes to sleep, hypervisor reports to us that it's sleeping
557  *         and will signal interrupt (from @rsc) when it's time to wake up.
558  *         This completion signals that we can run vCPU again.
559  * @nb: When VM exits, the status of VM is reported via @vcpu_run->status.
560  *      We need to track overall VM status, and the nb gives us the updates from
561  *      Resource Manager.
562  * @ticket: resource ticket to claim vCPU# for the VM
563  * @kref: Reference counter
564  */
565 struct gunyah_vcpu {
566 	struct gunyah_vm_function_instance *f;
567 	struct gunyah_resource *rsc;
568 	struct mutex run_lock;
569 	struct gunyah_vm *ghvm;
570 
571 	struct gunyah_vcpu_run *vcpu_run;
572 
573 	/**
574 	 * Track why the vcpu_run hypercall returned. This mirrors the vcpu_run
575 	 * structure shared with userspace, except is used internally to avoid
576 	 * trusting userspace to not modify the vcpu_run structure.
577 	 */
578 	enum {
579 		GUNYAH_VCPU_RUN_STATE_UNKNOWN = 0,
580 		GUNYAH_VCPU_RUN_STATE_READY,
581 		GUNYAH_VCPU_RUN_STATE_MMIO_READ,
582 		GUNYAH_VCPU_RUN_STATE_MMIO_WRITE,
583 		GUNYAH_VCPU_RUN_STATE_SYSTEM_DOWN,
584 	} state;
585 	u8 mmio_read_len;
586 	u64 mmio_addr;
587 
588 	struct completion ready;
589 
590 	struct notifier_block nb;
591 	struct gunyah_vm_resource_ticket ticket;
592 	struct kref kref;
593 };
594 
595 enum gunyah_error
596 gunyah_hypercall_vcpu_run(u64 capid, unsigned long *resume_data,
597 			  struct gunyah_hypercall_vcpu_run_resp *resp);
598 
599 #define GUNYAH_ADDRSPC_MODIFY_FLAG_UNLOCK_BIT		0
600 #define GUNYAH_ADDRSPC_MODIFY_FLAG_SANITIZE_BIT		1
601 enum gunyah_error
602 gunyah_hypercall_addrspc_modify_pages(u64 capid, u64 addr, u64 size, u64 flags);
603 enum gunyah_error
604 gunyah_hypercall_addrspace_find_info_area(unsigned long *ipa, unsigned long *size);
605 enum gunyah_error
606 #define GUNYAH_ADDRSPACE_VMMIO_CONFIGURE_OP_ADD_RANGE	0
607 gunyah_hypercall_addrspc_configure_vmmio_range(u64 capid, u64 base, u64 size, u64 op);
608 #endif
609