From patchwork Mon May 15 17:25:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Dwivedi, Avaneesh Kumar (avani)" X-Patchwork-Id: 9727677 X-Patchwork-Delegate: agross@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BB42260231 for ; Mon, 15 May 2017 17:26:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A52762899D for ; Mon, 15 May 2017 17:26:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 99E01289A0; Mon, 15 May 2017 17:26:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1A1C92899D for ; Mon, 15 May 2017 17:26:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760276AbdEOR0C (ORCPT ); Mon, 15 May 2017 13:26:02 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:49516 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758801AbdEOR0A (ORCPT ); Mon, 15 May 2017 13:26:00 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E6F1E60D62; Mon, 15 May 2017 17:25:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1494869159; bh=QE7NqjMcBSWKJYepMjWz8aR18VFEnSz/6sco7+qMXOE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oVXfE6/iuLabkO/tBg6ilGkBkpyCKPQlrjG0/tEx3aYLh1m+b14VR71/gp3EQaH+W qIrWp17fI2I1EEIlqZvq0fL/OHtVwivDKMqEk3DXFmBM4a8s8WzcKLUZSXDrb81MCj ykppbAibBZKVY0XWyQfIxHScNgm1ZbczDFn0WPms= Received: from akdwived-linux.qualcomm.com (unknown [202.46.23.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: akdwived@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id E95E260D6E; Mon, 15 May 2017 17:25:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1494869159; bh=QE7NqjMcBSWKJYepMjWz8aR18VFEnSz/6sco7+qMXOE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oVXfE6/iuLabkO/tBg6ilGkBkpyCKPQlrjG0/tEx3aYLh1m+b14VR71/gp3EQaH+W qIrWp17fI2I1EEIlqZvq0fL/OHtVwivDKMqEk3DXFmBM4a8s8WzcKLUZSXDrb81MCj ykppbAibBZKVY0XWyQfIxHScNgm1ZbczDFn0WPms= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org E95E260D6E Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=akdwived@codeaurora.org From: Avaneesh Kumar Dwivedi To: bjorn.andersson@linaro.org Cc: sboyd@codeaurora.org, agross@codeaurora.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, Avaneesh Kumar Dwivedi Subject: [PATCH v4 1/4] firmware: scm: Add support for shared access of a memory Date: Mon, 15 May 2017 22:55:41 +0530 Message-Id: <1494869144-4174-2-git-send-email-akdwived@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1494869144-4174-1-git-send-email-akdwived@codeaurora.org> References: <1494869144-4174-1-git-send-email-akdwived@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Two different processors on a SOC need to share memory during loading. So memory access between them need to be synchronized, which is done via level two memory mapping by secure layer. This patch provide interface for making secure monitor call for access sharing or access right transfer between two subsystems. Signed-off-by: Avaneesh Kumar Dwivedi --- drivers/firmware/qcom_scm-64.c | 27 +++++++++++++++ drivers/firmware/qcom_scm.c | 75 ++++++++++++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.h | 4 +++ include/linux/qcom_scm.h | 14 ++++++++ 4 files changed, 120 insertions(+) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 6e6d561..77ef5c9 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -439,3 +439,30 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, return ret; } + +int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_addr, + size_t mem_sz, phys_addr_t srcVm, size_t srcVm_sz, + phys_addr_t destVm, size_t destVm_sz) +{ + int ret; + struct qcom_scm_desc desc = {0}; + struct arm_smccc_res res; + + desc.args[0] = mem_addr; + desc.args[1] = mem_sz; + desc.args[2] = srcVm; + desc.args[3] = srcVm_sz; + desc.args[4] = destVm; + desc.args[5] = destVm_sz; + desc.args[6] = 0; + + desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL, + QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, + QCOM_MEM_PROT_ASSIGN_ID, + &desc, &res); + + return ret ? : res.a1; +} diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index bb16510..a2363e2 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -40,6 +40,24 @@ struct qcom_scm { struct reset_controller_dev reset; }; +struct qcom_scm_current_perm_info { + __le32 destVm; + __le32 destVmPerm; + __le64 ctx; + __le32 ctx_size; +}; + +struct qcom_scm_mem_map_info { + __le64 mem_addr; + __le64 mem_size; +}; + +struct qcom_scm_hyp_map_info { + __le32 srcVm[2]; + struct qcom_scm_mem_map_info mem_region; + struct qcom_scm_current_perm_info destVm[2]; +}; + static struct qcom_scm *__scm; static int qcom_scm_clk_enable(void) @@ -292,6 +310,63 @@ int qcom_scm_pas_shutdown(u32 peripheral) } EXPORT_SYMBOL(qcom_scm_pas_shutdown); +/** + * qcom_scm_assign_mem() - Provide interface to request to map a memory + * region into intermediate physical address table as well map + * access permissions for any other proc on SOC. So that when other proc + * applies the same intermediate physical address passed by requesting + * processor in this case apps proc, on memory bus it can access the + * region without fault. + * @mem_addr: Start pointer of region which need to be mapped. + * @mem_sz: Size of the region. + * @srcVm: Detail of current owners, each set bit in flag indicate id of + * shared owners. + * @newVm: Details of new owners and permission flags for each of them. + * @newVm_sz: Size of array pointed by newVm. + * Return 0 on success. + */ +int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, int srcVm, + struct qcom_scm_destVmPerm *newVm, size_t newVm_sz) +{ + unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; + struct qcom_scm_hyp_map_info *hmi; + phys_addr_t addr[3]; + size_t size[3]; + int ret; + int i; + + hmi = dma_alloc_attrs(__scm->dev, sizeof(*hmi), + &addr[1], GFP_KERNEL, dma_attrs); + hmi->mem_region.mem_addr = cpu_to_le64(mem_addr); + hmi->mem_region.mem_size = cpu_to_le64(mem_sz); + + addr[0] = addr[1] + sizeof(hmi->srcVm); + size[0] = sizeof(hmi->mem_region); + + ret = hweight_long(srcVm); + for (i = 0; i < ret; i++) { + hmi->srcVm[i] = cpu_to_le32(ffs(srcVm) - 0x1); + srcVm ^= 1 << (ffs(srcVm) - 0x1); + } + size[1] = ret * sizeof(srcVm); + + ret = newVm_sz/sizeof(struct qcom_scm_destVmPerm); + for (i = 0; i < ret; i++) { + hmi->destVm[i].destVm = cpu_to_le32(newVm[i].destVm); + hmi->destVm[i].destVmPerm = cpu_to_le32(newVm[i].destVmPerm); + hmi->destVm[i].ctx = 0; + hmi->destVm[i].ctx_size = 0; + } + addr[2] = addr[0] + sizeof(hmi->mem_region); + size[2] = ret * sizeof(struct qcom_scm_current_perm_info); + + ret = __qcom_scm_assign_mem(__scm->dev, addr[0], + size[0], addr[1], size[1], addr[2], size[2]); + dma_free_attrs(__scm->dev, sizeof(*hmi), hmi, addr[1], dma_attrs); + return ret; +} +EXPORT_SYMBOL(qcom_scm_assign_mem); + static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev, unsigned long idx) { diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 9bea691..0837b96 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -95,5 +95,9 @@ extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, size_t *size); extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare); +#define QCOM_MEM_PROT_ASSIGN_ID 0x16 +extern int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_addr, + size_t mem_sz, phys_addr_t srcVm, size_t srcVm_sz, + phys_addr_t destVm, size_t destVm_sz); #endif diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index e538047..cb930d9 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -23,6 +23,18 @@ struct qcom_scm_hdcp_req { u32 val; }; +struct qcom_scm_destVmPerm { + int destVm; + int destVmPerm; +}; + +#define QCOM_SCM_VMID_HLOS 0x3 +#define QCOM_SCM_VMID_MSS_MSA 0xF +#define QCOM_SCM_PERM_READ 0x4 +#define QCOM_SCM_PERM_WRITE 0x2 +#define QCOM_SCM_PERM_EXEC 0x1 +#define QCOM_SCM_PERM_RW (QCOM_SCM_PERM_READ | QCOM_SCM_PERM_WRITE) + #if IS_ENABLED(CONFIG_QCOM_SCM) extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); @@ -37,6 +49,8 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size); extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); +extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, int currVm, + struct qcom_scm_destVmPerm *newVm, size_t newVm_sz); extern void qcom_scm_cpu_power_down(u32 flags); extern u32 qcom_scm_get_version(void); extern int qcom_scm_set_remote_state(u32 state, u32 id);