diff --git a/drivers/virt/haven/hh_rm_drv_private.h b/drivers/virt/haven/hh_rm_drv_private.h index 5bee0a07aa86..8aca2dc4db56 100644 --- a/drivers/virt/haven/hh_rm_drv_private.h +++ b/drivers/virt/haven/hh_rm_drv_private.h @@ -218,6 +218,13 @@ struct hh_mem_qcom_lookup_sgl_resp_payload { hh_memparcel_handle_t memparcel_handle; } __packed; +/* Call: MEM_RELEASE/MEM_RECLAIM */ +struct hh_mem_release_req_payload { + hh_memparcel_handle_t memparcel_handle; + u32 flags:8; + u32 reserved:24; +} __packed; + /* End Message ID headers */ /* Common function declerations */ diff --git a/drivers/virt/haven/hh_rm_iface.c b/drivers/virt/haven/hh_rm_iface.c index 6386bd0c50d5..3b31424dab15 100644 --- a/drivers/virt/haven/hh_rm_iface.c +++ b/drivers/virt/haven/hh_rm_iface.c @@ -13,6 +13,9 @@ #include "hh_rm_drv_private.h" +#define HH_RM_MEM_RELEASE_VALID_FLAGS HH_RM_MEM_RELEASE_CLEAR +#define HH_RM_MEM_RECLAIM_VALID_FLAGS HH_RM_MEM_RECLAIM_CLEAR + static struct hh_vm_property hh_vm_table[HH_VM_MAX]; int hh_update_vm_prop_table(enum hh_vm_names vm_name, @@ -750,3 +753,68 @@ err_rm_call: return ret; } EXPORT_SYMBOL(hh_rm_mem_qcom_lookup_sgl); + +static int hh_rm_mem_release_helper(u32 fn_id, hh_memparcel_handle_t handle, + u8 flags) +{ + struct hh_mem_release_req_payload req_payload = {}; + void *resp; + size_t resp_size; + int ret, hh_ret; + + if ((fn_id == HH_RM_RPC_MSG_ID_CALL_MEM_RELEASE) && + (flags & ~HH_RM_MEM_RELEASE_VALID_FLAGS)) + return -EINVAL; + else if ((fn_id == HH_RM_RPC_MSG_ID_CALL_MEM_RECLAIM) && + (flags & ~HH_RM_MEM_RECLAIM_VALID_FLAGS)) + return -EINVAL; + + req_payload.memparcel_handle = handle; + req_payload.flags = flags; + + resp = hh_rm_call(fn_id, &req_payload, sizeof(req_payload), &resp_size, + &hh_ret); + if (hh_ret) { + ret = PTR_ERR(resp); + pr_err("%s failed with err: %d\n", __func__, ret); + return ret; + } + + return 0; +} + +/** + * hh_rm_mem_release: Release a handle representing memory. This results in + * the RM unmapping the associated memory from the stage-2 + * page-tables of the current VM + * @handle: The memparcel handle associated with the memory + * @flags: Bitmask of values to influence the behavior of the RM when it unmaps + * the memory. + * + * On success, the function will return 0. Otherwise, a negative number will be + * returned. + */ +int hh_rm_mem_release(hh_memparcel_handle_t handle, u8 flags) +{ + return hh_rm_mem_release_helper(HH_RM_RPC_MSG_ID_CALL_MEM_RELEASE, + handle, flags); +} +EXPORT_SYMBOL(hh_rm_mem_release); + +/** + * hh_rm_mem_reclaim: Reclaim a memory represented by a handle. This results in + * the RM mapping the associated memory into the stage-2 + * page-tables of the owner VM + * @handle: The memparcel handle associated with the memory + * @flags: Bitmask of values to influence the behavior of the RM when it unmaps + * the memory. + * + * On success, the function will return 0. Otherwise, a negative number will be + * returned. + */ +int hh_rm_mem_reclaim(hh_memparcel_handle_t handle, u8 flags) +{ + return hh_rm_mem_release_helper(HH_RM_RPC_MSG_ID_CALL_MEM_RECLAIM, + handle, flags); +} +EXPORT_SYMBOL(hh_rm_mem_reclaim); diff --git a/include/linux/haven/hh_rm_drv.h b/include/linux/haven/hh_rm_drv.h index cc36f5961697..8104d2b2b7c1 100644 --- a/include/linux/haven/hh_rm_drv.h +++ b/include/linux/haven/hh_rm_drv.h @@ -27,6 +27,9 @@ #define HH_RM_ACL_W BIT(1) #define HH_RM_ACL_R BIT(2) +#define HH_RM_MEM_RELEASE_CLEAR BIT(0) +#define HH_RM_MEM_RECLAIM_CLEAR BIT(0) + struct hh_rm_mem_shared_acl_entry; struct hh_rm_mem_shared_sgl_entry; struct hh_rm_mem_shared_attr_entry; @@ -168,5 +171,7 @@ int hh_rm_mem_qcom_lookup_sgl(u8 mem_type, hh_label_t label, struct hh_sgl_desc *sgl_desc, struct hh_mem_attr_desc *mem_attr_desc, hh_memparcel_handle_t *handle); +int hh_rm_mem_release(hh_memparcel_handle_t handle, u8 flags); +int hh_rm_mem_reclaim(hh_memparcel_handle_t handle, u8 flags); #endif