mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
mem-buf: Add infrastructure for requesting specific IPA address
gh_rm_mem_accept allows a VM to request memory to be mapped to a specific IPA address. Modify function parameters to allow for future use of this feature. Change-Id: I6ad586886563e769549e4966369da48c27ca0a5c Signed-off-by: Patrick Daly <quic_pdaly@quicinc.com>
This commit is contained in:
parent
5a01357c0f
commit
0f6efbf911
|
|
@ -131,6 +131,24 @@ struct sg_table *dup_gh_sgl_desc_to_sgt(struct gh_sgl_desc *sgl_desc)
|
|||
}
|
||||
EXPORT_SYMBOL(dup_gh_sgl_desc_to_sgt);
|
||||
|
||||
struct gh_sgl_desc *dup_gh_sgl_desc(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
size_t size;
|
||||
struct gh_sgl_desc *copy;
|
||||
|
||||
if (!sgl_desc)
|
||||
return NULL;
|
||||
|
||||
size = offsetof(struct gh_sgl_desc, sgl_entries[sgl_desc->n_sgl_entries]);
|
||||
copy = kvmalloc(size, GFP_KERNEL);
|
||||
if (!copy)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memcpy(copy, sgl_desc, size);
|
||||
return copy;
|
||||
}
|
||||
EXPORT_SYMBOL(dup_gh_sgl_desc);
|
||||
|
||||
size_t mem_buf_get_sgl_buf_size(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
|
@ -176,13 +194,17 @@ static int mem_buf_hyp_assign_table_gh(struct gh_sgl_desc *sgl_desc, int src_vmi
|
|||
/*
|
||||
* @memparcel_hdl:
|
||||
* GH_RM_TRANS_TYPE_DONATE - memparcel_hdl will be set to MEM_BUF_MEMPARCEL_INVALID
|
||||
on success, and (possibly) set to a different valid memparcel on error. This is
|
||||
because accepting a donated memparcel handle destroys that handle.
|
||||
GH_RM_TRANS_TYPE_LEND - unmodified.
|
||||
GH_RM_TRANS_TYPE_SHARE - unmodified.
|
||||
* on success, and (possibly) set to a different valid memparcel on error. This is
|
||||
* because accepting a donated memparcel handle destroys that handle.
|
||||
* GH_RM_TRANS_TYPE_LEND - unmodified.
|
||||
* GH_RM_TRANS_TYPE_SHARE - unmodified.
|
||||
* @sgl_desc:
|
||||
* If *sgl_desc is not NULL, request specific IPA address(es). Otherwise, hypervisor
|
||||
* will choose the IPA address, and return it here.
|
||||
*/
|
||||
struct gh_sgl_desc *mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, int src_vmid)
|
||||
int mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, struct gh_sgl_desc **__sgl_desc,
|
||||
int src_vmid)
|
||||
{
|
||||
int ret, ret2;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
|
|
@ -190,24 +212,24 @@ struct gh_sgl_desc *mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparce
|
|||
GH_RM_MEM_ACCEPT_DONE;
|
||||
gh_memparcel_handle_t memparcel_hdl = *__memparcel_hdl;
|
||||
|
||||
if (!acl_desc)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (!acl_desc || !__sgl_desc)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* memory returns to its original IPA address when accepted by HLOS. For example,
|
||||
* scattered memory returns to being scattered memory.
|
||||
*/
|
||||
if (current_vmid != VMID_HLOS)
|
||||
if (current_vmid != VMID_HLOS || (*__sgl_desc && (*__sgl_desc)->n_sgl_entries == 1))
|
||||
flags |= GH_RM_MEM_ACCEPT_MAP_IPA_CONTIGUOUS;
|
||||
|
||||
pr_debug("%s: adding CPU MMU stage 2 mappings\n", __func__);
|
||||
sgl_desc = gh_rm_mem_accept(memparcel_hdl, GH_RM_MEM_TYPE_NORMAL, op,
|
||||
flags, 0, acl_desc, NULL,
|
||||
flags, 0, acl_desc, *__sgl_desc,
|
||||
NULL, 0);
|
||||
if (IS_ERR(sgl_desc)) {
|
||||
pr_err("%s failed to map memory in stage 2 rc: %d\n", __func__,
|
||||
PTR_ERR(sgl_desc));
|
||||
return sgl_desc;
|
||||
return PTR_ERR(sgl_desc);
|
||||
}
|
||||
|
||||
if (op == GH_RM_TRANS_TYPE_DONATE)
|
||||
|
|
@ -218,7 +240,8 @@ struct gh_sgl_desc *mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparce
|
|||
goto err_relinquish;
|
||||
|
||||
trace_map_mem_s2(memparcel_hdl, sgl_desc);
|
||||
return sgl_desc;
|
||||
*__sgl_desc = sgl_desc;
|
||||
return 0;
|
||||
|
||||
err_relinquish:
|
||||
if (op == GH_RM_TRANS_TYPE_DONATE)
|
||||
|
|
@ -226,12 +249,18 @@ struct gh_sgl_desc *mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparce
|
|||
__memparcel_hdl);
|
||||
else
|
||||
ret2 = mem_buf_unmap_mem_s2(memparcel_hdl);
|
||||
kvfree(sgl_desc);
|
||||
|
||||
/*
|
||||
* Only free sgl_desc if caller passed NULL in *__sgl_desc to request
|
||||
* gh_rm_mem_accept to allocate new IPA/sgl_desc.
|
||||
*/
|
||||
if (sgl_desc != *__sgl_desc)
|
||||
kvfree(sgl_desc);
|
||||
if (ret2) {
|
||||
pr_err("%s failed to recover\n", __func__);
|
||||
return ERR_PTR(-EADDRNOTAVAIL);
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
return ERR_PTR(ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_buf_map_mem_s2);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,13 +50,15 @@ static inline int mem_buf_unmap_mem_s1(struct gh_sgl_desc *sgl_desc)
|
|||
struct gh_acl_desc *mem_buf_vmid_perm_list_to_gh_acl(int *vmids, int *perms,
|
||||
unsigned int nr_acl_entries);
|
||||
struct gh_sgl_desc *mem_buf_sgt_to_gh_sgl_desc(struct sg_table *sgt);
|
||||
struct gh_sgl_desc *mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, int src_vmid);
|
||||
int mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, struct gh_sgl_desc **sgl_desc,
|
||||
int src_vmid);
|
||||
int mem_buf_unmap_mem_s2(gh_memparcel_handle_t memparcel_hdl);
|
||||
int mem_buf_gh_acl_desc_to_vmid_perm_list(struct gh_acl_desc *acl_desc,
|
||||
int **vmids, int **perms);
|
||||
size_t mem_buf_get_sgl_buf_size(struct gh_sgl_desc *sgl_desc);
|
||||
struct sg_table *dup_gh_sgl_desc_to_sgt(struct gh_sgl_desc *sgl_desc);
|
||||
struct gh_sgl_desc *dup_gh_sgl_desc(struct gh_sgl_desc *sgl_desc);
|
||||
int mem_buf_assign_mem_gunyah(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg);
|
||||
int mem_buf_unassign_mem_gunyah(gh_memparcel_handle_t memparcel_hdl);
|
||||
|
|
@ -82,10 +84,11 @@ static inline struct gh_sgl_desc *mem_buf_sgt_to_gh_sgl_desc(struct sg_table *sg
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline struct gh_sgl_desc *mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, int src_vmid)
|
||||
static inline int mem_buf_map_mem_s2(u32 op, gh_memparcel_handle_t *__memparcel_hdl,
|
||||
struct gh_acl_desc *acl_desc, struct gh_sgl_desc **__sgl_desc,
|
||||
int src_vmid)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int mem_buf_unmap_mem_s2(gh_memparcel_handle_t memparcel_hdl)
|
||||
|
|
@ -109,6 +112,11 @@ static inline struct sg_table *dup_gh_sgl_desc_to_sgt(struct gh_sgl_desc *sgl_de
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline struct gh_sgl_desc *dup_gh_sgl_desc(struct gh_sgl_desc *sgl_desc)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline int mem_buf_assign_mem_gunyah(u32 op, struct sg_table *sgt,
|
||||
struct mem_buf_lend_kernel_arg *arg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ static void mem_buf_cleanup_alloc_req(struct mem_buf_xfer_mem *xfer_mem,
|
|||
if (ret < 0)
|
||||
return;
|
||||
} else {
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
struct gh_sgl_desc *sgl_desc = NULL;
|
||||
struct gh_acl_desc *acl_desc;
|
||||
size_t size;
|
||||
|
||||
|
|
@ -409,9 +409,9 @@ static void mem_buf_cleanup_alloc_req(struct mem_buf_xfer_mem *xfer_mem,
|
|||
acl_desc->acl_entries[0].vmid = VMID_HLOS;
|
||||
acl_desc->acl_entries[0].perms = GH_RM_ACL_X | GH_RM_ACL_W | GH_RM_ACL_R;
|
||||
|
||||
sgl_desc = mem_buf_map_mem_s2(GH_RM_TRANS_TYPE_DONATE, &memparcel_hdl,
|
||||
acl_desc, VMID_TUIVM);
|
||||
if (IS_ERR(sgl_desc)) {
|
||||
ret = mem_buf_map_mem_s2(GH_RM_TRANS_TYPE_DONATE, &memparcel_hdl,
|
||||
acl_desc, &sgl_desc, VMID_TUIVM);
|
||||
if (ret) {
|
||||
kfree(acl_desc);
|
||||
return;
|
||||
}
|
||||
|
|
@ -879,7 +879,6 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
int ret;
|
||||
struct file *filp;
|
||||
struct mem_buf_desc *membuf;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
int perms = PERM_READ | PERM_WRITE | PERM_EXEC;
|
||||
|
||||
if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER))
|
||||
|
|
@ -897,6 +896,8 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
|
||||
pr_debug("%s: mem buf alloc begin\n", __func__);
|
||||
membuf->size = ALIGN(alloc_data->size, MEM_BUF_MHP_ALIGNMENT);
|
||||
|
||||
/* Create copies of data structures from alloc_data as they may be on-stack */
|
||||
membuf->acl_desc = mem_buf_vmid_perm_list_to_gh_acl(
|
||||
alloc_data->vmids, &perms,
|
||||
alloc_data->nr_acl_entries);
|
||||
|
|
@ -904,6 +905,15 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
ret = PTR_ERR(membuf->acl_desc);
|
||||
goto err_alloc_acl_list;
|
||||
}
|
||||
|
||||
if (alloc_data->sgl_desc) {
|
||||
membuf->sgl_desc = dup_gh_sgl_desc(alloc_data->sgl_desc);
|
||||
if (IS_ERR(membuf->sgl_desc)) {
|
||||
ret = PTR_ERR(membuf->sgl_desc);
|
||||
goto err_alloc_sgl_desc;
|
||||
}
|
||||
}
|
||||
|
||||
membuf->trans_type = alloc_data->trans_type;
|
||||
membuf->src_mem_type = alloc_data->src_mem_type;
|
||||
membuf->dst_mem_type = alloc_data->dst_mem_type;
|
||||
|
|
@ -936,11 +946,10 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
if (ret)
|
||||
goto err_mem_req;
|
||||
|
||||
sgl_desc = mem_buf_map_mem_s2(membuf->trans_type, &membuf->memparcel_hdl,
|
||||
membuf->acl_desc, VMID_HLOS);
|
||||
if (IS_ERR(sgl_desc))
|
||||
ret = mem_buf_map_mem_s2(membuf->trans_type, &membuf->memparcel_hdl,
|
||||
membuf->acl_desc, &membuf->sgl_desc, VMID_HLOS);
|
||||
if (ret)
|
||||
goto err_map_mem_s2;
|
||||
membuf->sgl_desc = sgl_desc;
|
||||
|
||||
ret = mem_buf_map_mem_s1(membuf->sgl_desc);
|
||||
if (ret)
|
||||
|
|
@ -975,7 +984,6 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
err_map_mem_s1:
|
||||
err_map_mem_s2:
|
||||
mem_buf_relinquish_mem(membuf);
|
||||
kvfree(membuf->sgl_desc);
|
||||
err_mem_req:
|
||||
mem_buf_destroy_txn(mem_buf_msgq_hdl, membuf->txn);
|
||||
err_init_txn:
|
||||
|
|
@ -983,6 +991,9 @@ static void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data)
|
|||
err_alloc_dst_data:
|
||||
mem_buf_free_mem_type_data(membuf->src_mem_type, membuf->src_data);
|
||||
err_alloc_src_data:
|
||||
if (membuf->sgl_desc)
|
||||
kvfree(membuf->sgl_desc);
|
||||
err_alloc_sgl_desc:
|
||||
kfree(membuf->acl_desc);
|
||||
err_alloc_acl_list:
|
||||
kfree(membuf);
|
||||
|
|
@ -1077,7 +1088,8 @@ struct dma_buf *mem_buf_retrieve(struct mem_buf_retrieve_kernel_arg *arg)
|
|||
int ret, op;
|
||||
struct qcom_sg_buffer *buffer;
|
||||
struct gh_acl_desc *acl_desc;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
/* Hypervisor picks the IPA address */
|
||||
struct gh_sgl_desc *sgl_desc = NULL;
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct dma_buf *dmabuf;
|
||||
struct sg_table *sgt;
|
||||
|
|
@ -1100,11 +1112,10 @@ struct dma_buf *mem_buf_retrieve(struct mem_buf_retrieve_kernel_arg *arg)
|
|||
}
|
||||
|
||||
op = mem_buf_get_mem_xfer_type_gh(acl_desc, arg->sender_vmid);
|
||||
sgl_desc = mem_buf_map_mem_s2(op, &arg->memparcel_hdl, acl_desc, arg->sender_vmid);
|
||||
if (IS_ERR(sgl_desc)) {
|
||||
ret = PTR_ERR(sgl_desc);
|
||||
ret = mem_buf_map_mem_s2(op, &arg->memparcel_hdl, acl_desc, &sgl_desc,
|
||||
arg->sender_vmid);
|
||||
if (ret)
|
||||
goto err_map_s2;
|
||||
}
|
||||
|
||||
ret = mem_buf_map_mem_s1(sgl_desc);
|
||||
if (ret < 0)
|
||||
|
|
@ -1173,6 +1184,7 @@ static int mem_buf_prep_alloc_data(struct mem_buf_allocation_data *alloc_data,
|
|||
goto err_acl;
|
||||
|
||||
/* alloc_data->trans_type set later according to src&dest_mem_type */
|
||||
alloc_data->sgl_desc = NULL;
|
||||
alloc_data->src_mem_type = allocation_args->src_mem_type;
|
||||
alloc_data->dst_mem_type = allocation_args->dst_mem_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ int mem_buf_dma_buf_set_destructor(struct dma_buf *dmabuf,
|
|||
* @acl_list: A list of VMID and permission pairs that describe what VMIDs will
|
||||
* have access to the memory, and with what permissions
|
||||
* @trans_type: One of GH_RM_TRANS_TYPE_DONATE/LEND/SHARE
|
||||
* @sgl_desc: Optional. Requests a specific set of IPA addresses.
|
||||
* @src_mem_type: The type of memory that the remote VM should allocate
|
||||
* (e.g. ION memory)
|
||||
* @src_data: A pointer to memory type specific data that the remote VM may need
|
||||
|
|
@ -55,6 +56,7 @@ struct mem_buf_allocation_data {
|
|||
int *vmids;
|
||||
int *perms;
|
||||
u32 trans_type;
|
||||
struct gh_sgl_desc *sgl_desc;
|
||||
enum mem_buf_mem_type src_mem_type;
|
||||
void *src_data;
|
||||
enum mem_buf_mem_type dst_mem_type;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user