memshare: Add support for hypervisor mapping

This patch adds support for the hyp call to set up permissions
for the memory allocated for the modem clients.
This patch also identifies the debug messages with memshare
driver.

CRs-Fixed: 970173
Change-Id: I862a3c21eb4f791d5c7d93d4fb523bf8714c20cb
Signed-off-by: Katish Paran <kparan@codeaurora.org>
Signed-off-by: Manoj Prabhu B <bmanoj@codeaurora.org>
This commit is contained in:
Manoj Prabhu B 2016-02-02 15:40:55 +05:30 committed by David Keitel
parent 71910a2a13
commit 1c00b9fb2d
2 changed files with 67 additions and 11 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -25,6 +25,8 @@
#include "msm_memshare.h"
#include "heap_mem_ext_v01.h"
#include <soc/qcom/secure_buffer.h>
/* Macros */
#define MEMSHARE_DEV_NAME "memshare"
#define MEMSHARE_CHILD_DEV_NAME "memshare_child"
@ -144,14 +146,10 @@ static int check_client(int client_id, int proc, int request)
void free_client(int id)
{
memblock[id].size = 0;
memblock[id].phy_addr = 0;
memblock[id].virtual_addr = 0;
memblock[id].alloted = 0;
memblock[id].client_id = DHMS_MEM_CLIENT_INVALID;
memblock[id].guarantee = 0;
memblock[id].peripheral = -1;
memblock[id].sequence_id = -1;
memblock[id].memory_type = MEMORY_CMA;
@ -191,6 +189,7 @@ void initialize_client(void)
memblock[i].sequence_id = -1;
memblock[i].memory_type = MEMORY_CMA;
memblock[i].free_memory = 0;
memblock[i].hyp_mapping = 0;
}
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
}
@ -199,6 +198,10 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
void *_cmd)
{
int i;
int ret;
u32 source_vmlist[2] = {VMID_HLOS, VMID_MSS_MSA};
int dest_vmids[1] = {VMID_HLOS};
int dest_perms[1] = {PERM_READ|PERM_WRITE};
switch (code) {
@ -222,8 +225,28 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
DHMS_MEM_PROC_MPSS_V01 &&
!memblock[i].guarantee &&
memblock[i].alloted) {
pr_err("memshare: Freeing memory for client id: %d\n",
pr_debug("memshare: Freeing memory for client id: %d\n",
memblock[i].client_id);
ret = hyp_assign_phys(
memblock[i].phy_addr,
memblock[i].size,
source_vmlist,
2, dest_vmids,
dest_perms, 1);
if (ret &&
memblock[i].hyp_mapping == 1) {
/*
* This is an error case as hyp
* mapping was successful
* earlier but during unmap
* it lead to failure.
*/
pr_err("memshare: %s, failed to unmap the region\n",
__func__);
memblock[i].hyp_mapping = 1;
} else {
memblock[i].hyp_mapping = 0;
}
dma_free_attrs(memsh_drv->dev,
memblock[i].size,
memblock[i].virtual_addr,
@ -248,6 +271,32 @@ static struct notifier_block nb = {
.notifier_call = modem_notifier_cb,
};
static void shared_hyp_mapping(int client_id)
{
int ret;
u32 source_vmlist[1] = {VMID_HLOS};
int dest_vmids[2] = {VMID_HLOS, VMID_MSS_MSA};
int dest_perms[2] = {PERM_READ|PERM_WRITE,
PERM_READ|PERM_WRITE};
if (client_id == DHMS_MEM_CLIENT_INVALID) {
pr_err("memshare: %s, Invalid Client\n", __func__);
return;
}
ret = hyp_assign_phys(memblock[client_id].phy_addr,
memblock[client_id].size,
source_vmlist, 1, dest_vmids,
dest_perms, 2);
if (ret != 0) {
pr_err("memshare: hyp_assign_phys failed size=%u err=%d\n",
memblock[client_id].size, ret);
return;
}
memblock[client_id].hyp_mapping = 1;
}
static int handle_alloc_req(void *req_h, void *req, void *conn_h)
{
struct mem_alloc_req_msg_v01 *alloc_req;
@ -341,9 +390,15 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
memblock[client_id].sequence_id = alloc_req->sequence_id;
fill_alloc_response(alloc_resp, client_id, &resp);
/*
* Perform the Hypervisor mapping in order to avoid XPU viloation
* to the allocated region for Modem Clients
*/
if (!memblock[client_id].hyp_mapping &&
memblock[client_id].alloted)
shared_hyp_mapping(client_id);
mutex_unlock(&memsh_drv->mem_share);
pr_debug("alloc_resp.num_bytes :%d, alloc_resp.handle :%lx, alloc_resp.mem_req_result :%lx\n",
pr_debug("memshare: alloc_resp.num_bytes :%d, alloc_resp.handle :%lx, alloc_resp.mem_req_result :%lx\n",
alloc_resp->dhms_mem_alloc_addr_info[0].num_bytes,
(unsigned long int)
alloc_resp->dhms_mem_alloc_addr_info[0].phy_addr,
@ -355,7 +410,6 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
if (rc < 0)
pr_err("In %s, Error sending the alloc request: %d\n",
__func__, rc);
return rc;
}
@ -405,7 +459,7 @@ static int handle_free_generic_req(void *req_h, void *req, void *conn_h)
memset(&free_resp, 0, sizeof(struct mem_free_generic_resp_msg_v01));
free_resp.resp.error = QMI_ERR_INTERNAL_V01;
free_resp.resp.result = QMI_RESULT_FAILURE_V01;
pr_debug("Client id: %d proc id: %d\n", free_req->client_id,
pr_debug("memshare: Client id: %d proc id: %d\n", free_req->client_id,
free_req->proc_id);
client_id = check_client(free_req->client_id, free_req->proc_id, FREE);
if (client_id == DHMS_MEM_CLIENT_INVALID) {

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -49,6 +49,8 @@ struct mem_blocks {
void *virtual_addr;
/* Release memory only when XPU is released*/
uint8_t free_memory;
/* Need Hypervisor mapping*/
uint8_t hyp_mapping;
};
int memshare_alloc(struct device *dev,