mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
neuron: ch_haven: Add memory sharing support
The carved out or allocated memory may not be configured to be accessible by both the owner and consumer vms. Add support to share memory through hyp_assign_phy() and assign a label to the resultant memparcel through hh_rm_mem_qcom_lookup_sgl(). This sharing sequence should only be done by the owner of the reserved memory region. Currently we indicate this with the qcom,primary tag in device tree. Change-Id: Idf5658ab4cf0d1c022f6b919914a8e782318c8d7 Signed-off-by: Chris Lew <clew@codeaurora.org>
This commit is contained in:
parent
6826400d8d
commit
66af98dc3f
3 changed files with 164 additions and 0 deletions
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm-generic/barrier.h>
|
||||
#include <linux/haven/hh_rm_drv.h>
|
||||
#include <linux/haven/hh_dbl.h>
|
||||
#include <soc/qcom/secure_buffer.h>
|
||||
#include "ch_mq_shmem_common.h"
|
||||
|
||||
#define CHANNEL_VERSION NEURON_SHMEM_CHANNEL_V1
|
||||
|
|
@ -295,6 +296,82 @@ static int channel_sync_thread(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int channel_hh_share_mem(struct neuron_mq_data_priv *priv,
|
||||
hh_vmid_t self, hh_vmid_t peer)
|
||||
{
|
||||
u32 src_vmlist[1] = {self};
|
||||
int dst_vmlist[2] = {self, peer};
|
||||
int dst_perms[2] = {PERM_READ | PERM_WRITE, PERM_READ | PERM_WRITE};
|
||||
struct hh_acl_desc *acl;
|
||||
struct hh_sgl_desc *sgl;
|
||||
int ret;
|
||||
|
||||
ret = hyp_assign_phys(priv->buffer.start, resource_size(&priv->buffer),
|
||||
src_vmlist, 1,
|
||||
dst_vmlist, dst_perms, 2);
|
||||
if (ret) {
|
||||
pr_err("hyp_assign_phys failed addr=%x size=%u err=%d\n",
|
||||
priv->buffer.start, resource_size(&priv->buffer), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
acl = kzalloc(offsetof(struct hh_acl_desc, acl_entries[2]), GFP_KERNEL);
|
||||
if (!acl)
|
||||
return -ENOMEM;
|
||||
sgl = kzalloc(offsetof(struct hh_sgl_desc, sgl_entries[1]), GFP_KERNEL);
|
||||
if (!sgl) {
|
||||
kfree(acl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
acl->n_acl_entries = 2;
|
||||
acl->acl_entries[0].vmid = (u16)self;
|
||||
acl->acl_entries[0].perms = HH_RM_ACL_R | HH_RM_ACL_W;
|
||||
acl->acl_entries[1].vmid = (u16)peer;
|
||||
acl->acl_entries[1].perms = HH_RM_ACL_R | HH_RM_ACL_W;
|
||||
|
||||
sgl->n_sgl_entries = 1;
|
||||
sgl->sgl_entries[0].ipa_base = priv->buffer.start;
|
||||
sgl->sgl_entries[0].size = resource_size(&priv->buffer);
|
||||
ret = hh_rm_mem_qcom_lookup_sgl(HH_RM_MEM_TYPE_NORMAL,
|
||||
priv->haven_label,
|
||||
acl, sgl, NULL,
|
||||
&priv->shm_memparcel);
|
||||
kfree(acl);
|
||||
kfree(sgl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int channel_hh_rm_cb(struct notifier_block *nb, unsigned long cmd,
|
||||
void *data)
|
||||
{
|
||||
struct hh_rm_notif_vm_status_payload *vm_status_payload;
|
||||
struct neuron_mq_data_priv *priv;
|
||||
hh_vmid_t peer_vmid;
|
||||
hh_vmid_t self_vmid;
|
||||
|
||||
priv = container_of(nb, struct neuron_mq_data_priv, rm_nb);
|
||||
|
||||
if (cmd != HH_RM_NOTIF_VM_STATUS)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
vm_status_payload = data;
|
||||
if (vm_status_payload->vm_status != HH_RM_VM_STATUS_READY)
|
||||
return NOTIFY_DONE;
|
||||
if (hh_rm_get_vmid(priv->peer_name, &peer_vmid))
|
||||
return NOTIFY_DONE;
|
||||
if (hh_rm_get_vmid(HH_PRIMARY_VM, &self_vmid))
|
||||
return NOTIFY_DONE;
|
||||
if (peer_vmid != vm_status_payload->vmid)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (channel_hh_share_mem(priv, self_vmid, peer_vmid))
|
||||
pr_err("%s: failed to share memory\n", __func__);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
|
||||
struct device *dev)
|
||||
{
|
||||
|
|
@ -344,6 +421,10 @@ static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
|
|||
&priv->peer_name);
|
||||
if (ret)
|
||||
priv->peer_name = HH_SELF_VM;
|
||||
|
||||
priv->rm_nb.notifier_call = channel_hh_rm_cb;
|
||||
priv->rm_nb.priority = INT_MAX;
|
||||
hh_rm_register_notifier(&priv->rm_nb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm-generic/barrier.h>
|
||||
#include <linux/haven/hh_rm_drv.h>
|
||||
#include <linux/haven/hh_dbl.h>
|
||||
#include <soc/qcom/secure_buffer.h>
|
||||
#include "ch_mq_shmem_common.h"
|
||||
|
||||
#define CHANNEL_VERSION NEURON_SHMEM_CHANNEL_V1
|
||||
|
|
@ -280,6 +281,80 @@ static int channel_sync_thread(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int channel_hh_share_mem(struct neuron_mq_data_priv *priv,
|
||||
hh_vmid_t self, hh_vmid_t peer)
|
||||
{
|
||||
u32 src_vmlist[1] = {self};
|
||||
int dst_vmlist[2] = {self, peer};
|
||||
int dst_perms[2] = {PERM_READ | PERM_WRITE, PERM_READ | PERM_WRITE};
|
||||
struct hh_acl_desc *acl;
|
||||
struct hh_sgl_desc *sgl;
|
||||
int ret;
|
||||
|
||||
ret = hyp_assign_phys(priv->buffer.start, resource_size(&priv->buffer),
|
||||
src_vmlist, 1,
|
||||
dst_vmlist, dst_perms, 2);
|
||||
if (ret) {
|
||||
pr_err("hyp_assign_phys failed addr=%x size=%u err=%d\n",
|
||||
priv->buffer.start, resource_size(&priv->buffer), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
acl = kzalloc(offsetof(struct hh_acl_desc, acl_entries[2]), GFP_KERNEL);
|
||||
if (!acl)
|
||||
return -ENOMEM;
|
||||
sgl = kzalloc(offsetof(struct hh_sgl_desc, sgl_entries[1]), GFP_KERNEL);
|
||||
if (!sgl) {
|
||||
kfree(acl);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
acl->n_acl_entries = 2;
|
||||
acl->acl_entries[0].vmid = (u16)self;
|
||||
acl->acl_entries[0].perms = HH_RM_ACL_R | HH_RM_ACL_W;
|
||||
acl->acl_entries[1].vmid = (u16)peer;
|
||||
acl->acl_entries[1].perms = HH_RM_ACL_R | HH_RM_ACL_W;
|
||||
|
||||
sgl->n_sgl_entries = 1;
|
||||
sgl->sgl_entries[0].ipa_base = priv->buffer.start;
|
||||
sgl->sgl_entries[0].size = resource_size(&priv->buffer);
|
||||
ret = hh_rm_mem_qcom_lookup_sgl(HH_RM_MEM_TYPE_NORMAL,
|
||||
priv->haven_label,
|
||||
acl, sgl, NULL,
|
||||
&priv->shm_memparcel);
|
||||
kfree(acl);
|
||||
kfree(sgl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int channel_hh_rm_cb(struct notifier_block *nb, unsigned long cmd,
|
||||
void *data)
|
||||
{
|
||||
struct hh_rm_notif_vm_status_payload *vm_status_payload = data;
|
||||
struct neuron_mq_data_priv *priv;
|
||||
hh_vmid_t peer_vmid;
|
||||
hh_vmid_t self_vmid;
|
||||
|
||||
priv = container_of(nb, struct neuron_mq_data_priv, rm_nb);
|
||||
if (cmd != HH_RM_NOTIF_VM_STATUS)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (vm_status_payload->vm_status != HH_RM_VM_STATUS_READY)
|
||||
return NOTIFY_DONE;
|
||||
if (hh_rm_get_vmid(priv->peer_name, &peer_vmid))
|
||||
return NOTIFY_DONE;
|
||||
if (hh_rm_get_vmid(HH_PRIMARY_VM, &self_vmid))
|
||||
return NOTIFY_DONE;
|
||||
if (peer_vmid != vm_status_payload->vmid)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (channel_hh_share_mem(priv, self_vmid, peer_vmid))
|
||||
pr_err("%s: failed to share memory\n", __func__);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
|
||||
struct device *dev)
|
||||
{
|
||||
|
|
@ -329,6 +404,10 @@ static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
|
|||
&priv->peer_name);
|
||||
if (ret)
|
||||
priv->peer_name = HH_SELF_VM;
|
||||
|
||||
priv->rm_nb.notifier_call = channel_hh_rm_cb;
|
||||
priv->rm_nb.priority = INT_MAX;
|
||||
hh_rm_register_notifier(&priv->rm_nb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ struct neuron_mq_data_priv {
|
|||
void *tx_dbl;
|
||||
/* haven rx doorbell descriptor */
|
||||
void *rx_dbl;
|
||||
/* memparcel handle after assigning label to shared memory */
|
||||
u32 shm_memparcel;
|
||||
/* haven rm status notifier block */
|
||||
struct notifier_block rm_nb;
|
||||
/* pointer to the device structure */
|
||||
struct neuron_channel *dev;
|
||||
/* shared memory mapped address */
|
||||
|
|
|
|||
Loading…
Reference in a new issue