/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _GUNYAH_RSC_MGR_H #define _GUNYAH_RSC_MGR_H #include #include #include #include #define GH_VMID_INVAL U16_MAX #define GH_MEM_HANDLE_INVAL U32_MAX struct gh_rm; int gh_rm_call(void *rm, u32 message_id, const void *req_buf, size_t req_buf_size, void **resp_buf, size_t *resp_buf_size); int gh_rm_notifier_register(void *rm, struct notifier_block *nb); int gh_rm_notifier_unregister(void *rm, struct notifier_block *nb); struct device *gh_rm_get(struct gh_rm *rm); void gh_rm_put(struct gh_rm *rm); struct gh_rm_vm_exited_payload { __le16 vmid; __le16 exit_type; __le32 exit_reason_size; u8 exit_reason[]; } __packed; #define GH_RM_NOTIFICATION_VM_EXITED 0x56100001 enum gh_rm_vm_status { GH_RM_VM_STATUS_NO_STATE = 0, GH_RM_VM_STATUS_INIT = 1, GH_RM_VM_STATUS_READY = 2, GH_RM_VM_STATUS_RUNNING = 3, GH_RM_VM_STATUS_PAUSED = 4, GH_RM_VM_STATUS_LOAD = 5, GH_RM_VM_STATUS_AUTH = 6, GH_RM_VM_STATUS_INIT_FAILED = 8, GH_RM_VM_STATUS_EXITED = 9, GH_RM_VM_STATUS_RESETTING = 10, GH_RM_VM_STATUS_RESET = 11, }; struct gh_rm_vm_status_payload { __le16 vmid; u16 reserved; u8 vm_status; u8 os_status; __le16 app_status; } __packed; #define GH_RM_NOTIFICATION_VM_STATUS 0x56100008 #define GH_RM_ACL_X BIT(0) #define GH_RM_ACL_W BIT(1) #define GH_RM_ACL_R BIT(2) struct gh_rm_mem_acl_entry { __le16 vmid; u8 perms; u8 reserved; } __packed; struct gh_rm_mem_entry { __le64 phys_addr; __le64 size; } __packed; enum gh_rm_mem_type { GH_RM_MEM_TYPE_NORMAL = 0, GH_RM_MEM_TYPE_IO = 1, }; /* * struct gh_rm_mem_parcel - Info about memory to be lent/shared/donated/reclaimed * @mem_type: The type of memory: normal (DDR) or IO * @label: An client-specified identifier which can be used by the other VMs to identify the purpose * of the memory parcel. * @n_acl_entries: Count of the number of entries in the @acl_entries array. * @acl_entries: An array of access control entries. Each entry specifies a VM and what access * is allowed for the memory parcel. * @n_mem_entries: Count of the number of entries in the @mem_entries array. * @mem_entries: An array of regions to be associated with the memory parcel. Addresses should be * (intermediate) physical addresses from Linux's perspective. * @mem_handle: On success, filled with memory handle that RM allocates for this memory parcel */ struct gh_rm_mem_parcel { enum gh_rm_mem_type mem_type; u32 label; size_t n_acl_entries; struct gh_rm_mem_acl_entry *acl_entries; size_t n_mem_entries; struct gh_rm_mem_entry *mem_entries; u32 mem_handle; ANDROID_BACKPORT_RESERVED(1); ANDROID_BACKPORT_RESERVED(2); ANDROID_BACKPORT_RESERVED(3); ANDROID_BACKPORT_RESERVED(4); ANDROID_BACKPORT_RESERVED(5); ANDROID_BACKPORT_RESERVED(6); ANDROID_BACKPORT_RESERVED(7); ANDROID_BACKPORT_RESERVED(8); }; /* RPC Calls */ int gh_rm_mem_lend(struct gh_rm *rm, struct gh_rm_mem_parcel *parcel); int gh_rm_mem_share(struct gh_rm *rm, struct gh_rm_mem_parcel *parcel); int gh_rm_mem_reclaim(struct gh_rm *rm, struct gh_rm_mem_parcel *parcel); int gh_rm_alloc_vmid(struct gh_rm *rm, u16 vmid); int gh_rm_dealloc_vmid(struct gh_rm *rm, u16 vmid); int gh_rm_vm_reset(struct gh_rm *rm, u16 vmid); int gh_rm_vm_start(struct gh_rm *rm, u16 vmid); int gh_rm_vm_stop(struct gh_rm *rm, u16 vmid); int gh_rm_vm_set_firmware_mem(struct gh_rm *rm, u16 vmid, struct gh_rm_mem_parcel *parcel, u64 fw_offset, u64 fw_size); enum gh_rm_vm_auth_mechanism { GH_RM_VM_AUTH_NONE = 0, GH_RM_VM_AUTH_QCOM_PIL_ELF = 1, GH_RM_VM_AUTH_QCOM_ANDROID_PVM = 2, }; int gh_rm_vm_configure(struct gh_rm *rm, u16 vmid, enum gh_rm_vm_auth_mechanism auth_mechanism, u32 mem_handle, u64 image_offset, u64 image_size, u64 dtb_offset, u64 dtb_size); int gh_rm_vm_init(struct gh_rm *rm, u16 vmid); struct gh_rm_hyp_resource { u8 type; u8 reserved; __le16 partner_vmid; __le32 resource_handle; __le32 resource_label; __le64 cap_id; __le32 virq_handle; #define GH_RM_RESOURCE_NO_VIRQ 0xFFFFFFFF __le32 virq; __le64 base; __le64 size; } __packed; struct gh_rm_hyp_resources { __le32 n_entries; struct gh_rm_hyp_resource entries[]; } __packed; int gh_rm_get_hyp_resources(struct gh_rm *rm, u16 vmid, struct gh_rm_hyp_resources **resources); int gh_rm_get_vmid(struct gh_rm *rm, u16 *vmid); struct gh_resource *gh_rm_alloc_resource(struct gh_rm *rm, struct gh_rm_hyp_resource *hyp_resource); void gh_rm_free_resource(struct gh_resource *ghrsc); struct gh_rm_platform_ops { int (*pre_mem_share)(void *rm, struct gh_rm_mem_parcel *mem_parcel); int (*post_mem_reclaim)(void *rm, struct gh_rm_mem_parcel *mem_parcel); ANDROID_BACKPORT_RESERVED(1); ANDROID_BACKPORT_RESERVED(2); ANDROID_BACKPORT_RESERVED(3); ANDROID_BACKPORT_RESERVED(4); }; #if IS_ENABLED(CONFIG_GUNYAH_PLATFORM_HOOKS) int gh_rm_register_platform_ops(const struct gh_rm_platform_ops *platform_ops); void gh_rm_unregister_platform_ops(const struct gh_rm_platform_ops *platform_ops); int devm_gh_rm_register_platform_ops(struct device *dev, const struct gh_rm_platform_ops *ops); #else static inline int gh_rm_register_platform_ops(const struct gh_rm_platform_ops *platform_ops) { return 0; } static inline void gh_rm_unregister_platform_ops(const struct gh_rm_platform_ops *platform_ops) { } static inline int devm_gh_rm_register_platform_ops(struct device *dev, const struct gh_rm_platform_ops *ops) { return 0; } #endif #endif