Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1569586 > unrolled thread

[PATCH v2 0/3] Enable msm8996 support in mss rproc driver.

Started byAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>
First post2017-01-30 12:00 +0100
Last post2017-01-30 12:00 +0100
Articles 3 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/3] Enable msm8996 support in mss rproc driver. Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> - 2017-01-30 12:00 +0100
    [PATCH v2 2/3] remoteproc: qcom: Add scm call to protect modem mem in mss rproc drv. Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> - 2017-01-30 12:00 +0100
    [PATCH v2 1/3] soc: qcom: Add scm call to protect modem mem in qcom scm driver. Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> - 2017-01-30 12:00 +0100

#1569586 — [PATCH v2 0/3] Enable msm8996 support in mss rproc driver.

FromAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>
Date2017-01-30 12:00 +0100
Subject[PATCH v2 0/3] Enable msm8996 support in mss rproc driver.
Message-ID<t5hQK-2Xv-5@gated-at.bofh.it>
In continuation of earlier RFC patch series, this series consist three patches, which add following.
	1- Add hypervisor call support to enable second stage translation of intermediat physical address generated
	   by individual subsystem, second stage mapping of address is supported armv8 onwards.
	2- Modify already floating mss rproc driver to enable mss remoteproc support for msm8996.
Differences WRT patchset 1 is as follow.
	1- Secure_buffer.c file is removed which was added as a separate driver in patchset 1.
	   Instead now to make translation scm call one additional function is added in rproc driver itself.
	2- Address other comments by sboyd on RFC patch.

This patch series is dependednt on https://patchwork.kernel.org/patch/9492177/

Avaneesh Kumar Dwivedi (3):
  soc: qcom: Add scm call to protect modem mem in qcom scm driver.
  remoteproc: qcom: Add scm call to protect modem mem in mss rproc drv.
  remoteproc: qcom: Add msm8996 specific changes in mss rproc driver.

 .../devicetree/bindings/remoteproc/qcom,q6v5.txt   |   1 +
 drivers/firmware/qcom_scm-64.c                     |  17 +
 drivers/firmware/qcom_scm.c                        |  14 +
 drivers/firmware/qcom_scm.h                        |   3 +
 drivers/remoteproc/qcom_q6v5_pil.c                 | 380 +++++++++++++++++++--
 include/linux/qcom_scm.h                           |   1 +
 6 files changed, 387 insertions(+), 29 deletions(-)

-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

[toc] | [next] | [standalone]


#1569588 — [PATCH v2 2/3] remoteproc: qcom: Add scm call to protect modem mem in mss rproc drv.

FromAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>
Date2017-01-30 12:00 +0100
Subject[PATCH v2 2/3] remoteproc: qcom: Add scm call to protect modem mem in mss rproc drv.
Message-ID<t5hQL-2Xv-27@gated-at.bofh.it>
In reply to#1569586
This patch add hypervisor call support for second stage translation from
mss remoteproc driver, this is required so that modem on msm8996 which is
based on armv8 architecture can access DDR region where modem firmware
are loaded.

Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org>
---
 drivers/remoteproc/qcom_q6v5_pil.c | 202 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 198 insertions(+), 4 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index e5edefa..35eee68 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -93,6 +93,23 @@
 #define QDSS_BHS_ON			BIT(21)
 #define QDSS_LDO_BYP			BIT(22)
 
+struct dest_vm_and_perm_info {
+	__le32 vm;
+	__le32 perm;
+	__le32 *ctx;
+	__le32 ctx_size;
+};
+
+struct mem_prot_info {
+	__le64 addr;
+	__le64 size;
+};
+
+struct scm_desc {
+	__le32 arginfo;
+	__le64 args[10];
+};
+
 struct reg_info {
 	struct regulator *reg;
 	int uV;
@@ -111,6 +128,7 @@ struct rproc_hexagon_res {
 	struct qcom_mss_reg_res active_supply[2];
 	char **proxy_clk_names;
 	char **active_clk_names;
+	int version;
 };
 
 struct q6v5 {
@@ -152,8 +170,29 @@ struct q6v5 {
 	phys_addr_t mpss_reloc;
 	void *mpss_region;
 	size_t mpss_size;
+	int version;
+	int protection_cmd;
+};
+
+enum {
+	MSS_MSM8916,
+	MSS_MSM8974,
+	MSS_MSM8996,
 };
 
+enum {
+	ASSIG_ACCESS_MSA,
+	REMOV_ACCESS_MSA,
+	SHARE_ACCESS_MSA,
+	REMOV_SHARE_MSA,
+};
+
+#define VMID_HLOS	0x3
+#define VMID_MSS_MSA	0xF
+#define PERM_READ	0x4
+#define PERM_WRITE	0x2
+#define PERM_EXEC	0x1
+#define PERM_RW	(0x4 | 0x2)
 static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
 				const struct qcom_mss_reg_res *reg_res)
 {
@@ -273,12 +312,123 @@ static void q6v5_clk_disable(struct device *dev,
 		clk_disable_unprepare(clks[i]);
 }
 
+int hyp_mem_access(struct q6v5 *qproc, phys_addr_t addr, size_t size)
+{
+	unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
+	struct dest_vm_and_perm_info *dest_info;
+	struct mem_prot_info *mem_prot_info;
+	struct scm_desc desc = {0};
+	__le32 *source_vm_copy;
+	__le64 mem_prot_phy;
+	int dest_count = 1;
+	int src_count = 1;
+	__le32 *perm = {0};
+	__le32 *dest = {0};
+	__le32 *src = {0};
+	__le64 phys_src;
+	__le64 phy_dest;
+	int ret;
+	int i;
+
+	if (qproc->version != MSS_MSM8996)
+		return 0;
+
+	switch (qproc->protection_cmd) {
+		case ASSIG_ACCESS_MSA: {
+			src = (int[2]) {VMID_HLOS, 0};
+			dest = (int[2]) {VMID_MSS_MSA, 0};
+			perm = (int[2]) {PERM_READ | PERM_WRITE, 0};
+			break;
+		}
+		case REMOV_ACCESS_MSA: {
+			src = (int[2]) {VMID_MSS_MSA, 0};
+			dest = (int[2]) {VMID_HLOS, 0};
+			perm = (int[2]) {PERM_READ | PERM_WRITE | PERM_EXEC, 0};
+			break;
+		}
+		case SHARE_ACCESS_MSA: {
+			src = (int[2]) {VMID_HLOS, 0};
+			dest = (int[2]) {VMID_HLOS, VMID_MSS_MSA};
+			perm = (int[2]) {PERM_RW, PERM_RW};
+			dest_count = 2;
+			break;
+		}
+		case REMOV_SHARE_MSA: {
+			src = (int[2]) {VMID_HLOS, VMID_MSS_MSA};
+			dest = (int[2]) {VMID_HLOS, 0};
+			perm = (int[2]) {PERM_READ | PERM_WRITE | PERM_EXEC, 0};
+			src_count = 2;
+			break;
+		}
+		default: {
+			break;
+		}
+	}
+
+	source_vm_copy = dma_alloc_attrs(qproc->dev,
+				src_count*sizeof(*source_vm_copy), &phys_src,
+				GFP_KERNEL, dma_attrs);
+	if (!source_vm_copy) {
+		dev_err(qproc->dev,
+			"failed to allocate buffer to pass source vmid detail\n");
+		return -ENOMEM;
+	}
+	memcpy(source_vm_copy, src, sizeof(*source_vm_copy) * src_count);
+
+	dest_info = dma_alloc_attrs(qproc->dev,
+			dest_count*sizeof(*dest_info), &phy_dest,
+			GFP_KERNEL, dma_attrs);
+	if (!dest_info) {
+		dev_err(qproc->dev,
+			"failed to allocate buffer to pass destination vmid detail\n");
+		return -ENOMEM;
+	}
+	for (i = 0; i < dest_count; i++) {
+		dest_info[i].vm = dest[i];
+		dest_info[i].perm = perm[i];
+		dest_info[i].ctx = NULL;
+		dest_info[i].ctx_size = 0;
+	}
+
+	mem_prot_info = dma_alloc_attrs(qproc->dev,
+				sizeof(*mem_prot_info), &mem_prot_phy,
+				GFP_KERNEL, dma_attrs);
+	if (!dest_info) {
+		dev_err(qproc->dev,
+				"failed to allocate buffer to pass protected mem detail\n");
+		return -ENOMEM;
+	}
+	mem_prot_info->addr = addr;
+	mem_prot_info->size = size;
+
+	desc.args[0] = mem_prot_phy;
+	desc.args[1] = sizeof(*mem_prot_info);
+	desc.args[2] = phys_src;
+	desc.args[3] = sizeof(*source_vm_copy) * src_count;
+	desc.args[4] = phy_dest;
+	desc.args[5] = dest_count*sizeof(*dest_info);
+	desc.args[6] = 0;
+
+	ret = qcom_scm_assign_mem(&desc);
+	if (ret)
+		pr_info("%s: Failed to assign memory protection, ret = %d\n",
+			__func__, ret);
+
+	/* SCM call has returned free up buffers passed to secure domain */
+	dma_free_attrs(qproc->dev, src_count*sizeof(*source_vm_copy),
+		source_vm_copy, phys_src, dma_attrs);
+	dma_free_attrs(qproc->dev, dest_count*sizeof(*dest_info),
+		dest_info, phy_dest, dma_attrs);
+	dma_free_attrs(qproc->dev, sizeof(*mem_prot_info), mem_prot_info,
+		mem_prot_phy, dma_attrs);
+	return ret;
+}
+
 static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
 {
 	struct q6v5 *qproc = rproc->priv;
 
 	memcpy(qproc->mba_region, fw->data, fw->size);
-
 	return 0;
 }
 
@@ -446,6 +596,14 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
 
 	memcpy(ptr, fw->data, fw->size);
 
+	/* Hypervisor support to access metadata by modem */
+	qproc->protection_cmd = ASSIG_ACCESS_MSA;
+	ret = hyp_mem_access(qproc, phys, ALIGN(fw->size, SZ_4K));
+	if (ret) {
+		dev_err(qproc->dev, "Failed to assign memory, ret - %d\n", ret);
+		return -ENOMEM;
+	}
+
 	writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG);
 	writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
 
@@ -454,7 +612,11 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
 		dev_err(qproc->dev, "MPSS header authentication timed out\n");
 	else if (ret < 0)
 		dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
-
+	/* Metadata authentication done, remove modem access */
+	qproc->protection_cmd = REMOV_ACCESS_MSA;
+	ret = hyp_mem_access(qproc, phys, ALIGN(fw->size, SZ_4K));
+	if (ret)
+		dev_err(qproc->dev, "Failed to assign memory, ret - %d\n", ret);
 	dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
 
 	return ret < 0 ? ret : 0;
@@ -483,6 +645,13 @@ static int q6v5_mpss_validate(struct q6v5 *qproc, const struct firmware *fw)
 	else
 		boot_addr = fw_addr;
 
+	/* Hypervisor support to modem to access modem fw */
+	qproc->protection_cmd = SHARE_ACCESS_MSA;
+	ret = hyp_mem_access(qproc, boot_addr, qproc->mpss_size);
+	if (ret) {
+		dev_err(qproc->dev, "Failed to assign memory, ret - %d\n", ret);
+		return -ENOMEM;
+	}
 	ehdr = (struct elf32_hdr *)fw->data;
 	phdrs = (struct elf32_phdr *)(ehdr + 1);
 	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
@@ -595,6 +764,12 @@ static int q6v5_start(struct rproc *rproc)
 		goto assert_reset;
 	}
 
+	qproc->protection_cmd = ASSIG_ACCESS_MSA;
+	ret = hyp_mem_access(qproc, qproc->mba_phys, qproc->mba_size);
+	if (ret) {
+		dev_err(qproc->dev, "Failed to assign memory, ret - %d\n", ret);
+		goto assert_reset;
+	}
 	writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);
 
 	ret = q6v5proc_reset(qproc);
@@ -616,16 +791,21 @@ static int q6v5_start(struct rproc *rproc)
 
 	ret = q6v5_mpss_load(qproc);
 	if (ret)
-		goto halt_axi_ports;
+		goto reclaim_mem;
 
 	ret = wait_for_completion_timeout(&qproc->start_done,
 					  msecs_to_jiffies(5000));
 	if (ret == 0) {
 		dev_err(qproc->dev, "start timed out\n");
 		ret = -ETIMEDOUT;
-		goto halt_axi_ports;
+		goto reclaim_mem;
 	}
 
+	qproc->protection_cmd = REMOV_ACCESS_MSA;
+	ret = hyp_mem_access(qproc, qproc->mba_phys, qproc->mba_size);
+	if (ret)
+		dev_err(qproc->dev,
+			"Failed to reclaim memory, ret - %d\n", ret);
 	qproc->running = true;
 
 	q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
@@ -634,7 +814,18 @@ static int q6v5_start(struct rproc *rproc)
 				qproc->proxy_reg_count);
 	return 0;
 
+reclaim_mem:
+	qproc->protection_cmd = REMOV_SHARE_MSA;
+	ret = hyp_mem_access(qproc, qproc->mpss_phys, qproc->mpss_size);
+	if (ret)
+		dev_err(qproc->dev,
+			"Failed to reclaim memory, ret - %d\n", ret);
 halt_axi_ports:
+	qproc->protection_cmd = REMOV_ACCESS_MSA;
+	ret = hyp_mem_access(qproc, qproc->mba_phys, qproc->mba_size);
+	if (ret)
+		dev_err(qproc->dev,
+			"Failed to reclaim memory, ret - %d\n", ret);
 	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
 	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
 	q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
@@ -977,6 +1168,7 @@ static int q6v5_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_rproc;
 
+	qproc->version = desc->version;
 	ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
 	if (ret < 0)
 		goto free_rproc;
@@ -1056,6 +1248,7 @@ static int q6v5_remove(struct platform_device *pdev)
 			"mem",
 			NULL
 	},
+	.version = MSS_MSM8916,
 };
 
 static const struct rproc_hexagon_res msm8974_mss = {
@@ -1093,6 +1286,7 @@ static int q6v5_remove(struct platform_device *pdev)
 			"mem",
 			NULL
 	},
+	.version = MSS_MSM8974,
 };
 static const struct of_device_id q6v5_of_match[] = {
 	{ .compatible = "qcom,q6v5-pil", .data = &msm8916_mss},
-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

[toc] | [prev] | [next] | [standalone]


#1569589 — [PATCH v2 1/3] soc: qcom: Add scm call to protect modem mem in qcom scm driver.

FromAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>
Date2017-01-30 12:00 +0100
Subject[PATCH v2 1/3] soc: qcom: Add scm call to protect modem mem in qcom scm driver.
Message-ID<t5hQL-2Xv-21@gated-at.bofh.it>
In reply to#1569586
This patch add scm call support to make hypervisor call for protecting
memory region on armv8 arch cpu's.
This is required to bring up modem on msm8996. MSS rproc driver will
make hypervisor call for protecting and granting permission of DDR region
where MBA, MDT, FW are loaded.

Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org>
---
 drivers/firmware/qcom_scm-64.c | 17 +++++++++++++++++
 drivers/firmware/qcom_scm.c    | 14 ++++++++++++++
 drivers/firmware/qcom_scm.h    |  3 +++
 include/linux/qcom_scm.h       |  1 +
 4 files changed, 35 insertions(+)

diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index 4a0f5ea..5f00a64 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -358,3 +358,20 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
 
 	return ret ? : res.a1;
 }
+
+int __qcom_scm_assign_mem(struct device *dev, void *data)
+{
+	int ret;
+	struct qcom_scm_desc *desc = data;
+	struct arm_smccc_res res;
+
+	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 893f953ea..f476803 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -292,6 +292,20 @@ int qcom_scm_pas_shutdown(u32 peripheral)
 }
 EXPORT_SYMBOL(qcom_scm_pas_shutdown);
 
+/**
+ * qcom_scm_assign_mem() - Apply new access permission of DDR
+ * region passed via descriptor and does second stage
+ * translation of intermediate physical address.
+ * @desc: descriptor to send to hypervisor
+ *
+ * Return 0 on success.
+ */
+int qcom_scm_assign_mem(void *desc)
+{
+	return __qcom_scm_assign_mem(__scm->dev, desc);
+}
+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 3584b00..d88fd4b 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -47,6 +47,8 @@ extern int __qcom_scm_hdcp_req(struct device *dev,
 #define QCOM_SCM_PAS_SHUTDOWN_CMD	0x6
 #define QCOM_SCM_PAS_IS_SUPPORTED_CMD	0x7
 #define QCOM_SCM_PAS_MSS_RESET		0xa
+#define QCOM_SCM_SVC_MP				0xc
+#define QCOM_MEM_PROT_ASSIGN_ID		0x16
 extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral);
 extern int  __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
 		dma_addr_t metadata_phys);
@@ -55,6 +57,7 @@ extern int  __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
 extern int  __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral);
 extern int  __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral);
 extern int  __qcom_scm_pas_mss_reset(struct device *dev, bool reset);
+extern int  __qcom_scm_assign_mem(struct device *dev, void *desc);
 
 /* common error codes */
 #define QCOM_SCM_V2_EBUSY	-12
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index cc32ab8..f9ecf35 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -36,6 +36,7 @@ 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(void *desc);
 
 #define QCOM_SCM_CPU_PWR_DOWN_L2_ON	0x0
 #define QCOM_SCM_CPU_PWR_DOWN_L2_OFF	0x1
-- 
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web