Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8bf2650 authored by Isaac J. Manjarres's avatar Isaac J. Manjarres Committed by Elliot Berman
Browse files

firmware: qcom_scm: Add support to assign multiple memory regions



The secure world allows for changing the ownership of multiple
(not necessarily physically contiguous) memory regions in one
secure call. Thus, expose an interface for clients to assign more
than one memory region per secure call.

Change-Id: Ic444627daee9d735b8b039ae3965e861cdcd110a
Signed-off-by: default avatarIsaac J. Manjarres <isaacm@codeaurora.org>
Signed-off-by: default avatarElliot Berman <eberman@codeaurora.org>
parent ec51a0f5
Loading
Loading
Loading
Loading
+33 −13
Original line number Diff line number Diff line
@@ -37,19 +37,6 @@ struct qcom_scm {
	u64 dload_mode_addr;
};

struct qcom_scm_current_perm_info {
	__le32 vmid;
	__le32 perm;
	__le64 ctx;
	__le32 ctx_size;
	__le32 unused;
};

struct qcom_scm_mem_map_info {
	__le64 mem_addr;
	__le64 mem_size;
};

static struct qcom_scm *__scm;

static int qcom_scm_clk_enable(void)
@@ -428,6 +415,39 @@ int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova,
}
EXPORT_SYMBOL(qcom_scm_iommu_secure_unmap);

/**
 * qcom_scm_assign_mem_regions() - Make a secure call to reassign memory
 *				   ownership of several memory regions
 * @mem_regions:    A buffer describing the set of memory regions that need to
 *		    be reassigned
 * @mem_regions_sz: The size of the buffer describing the set of memory
 *                  regions that need to be reassigned (in bytes)
 * @srcvms:	    A buffer populated with he vmid(s) for the current set of
 *		    owners
 * @src_sz:	    The size of the src_vms buffer (in bytes)
 * @newvms:	    A buffer populated with the new owners and corresponding
 *		    permission flags.
 * @newvms_sz:	    The size of the new_vms buffer (in bytes)
 *
 * NOTE: It is up to the caller to ensure that the buffers that will be accessed
 * by the secure world are cache aligned, and have been flushed prior to
 * invoking this call.
 *
 * Return negative errno on failure, 0 on success.
 */
int qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions,
				size_t mem_regions_sz, u32 *srcvms,
				size_t src_sz,
				struct qcom_scm_current_perm_info *newvms,
				size_t newvms_sz)
{
	return __qcom_scm_assign_mem(__scm ? __scm->dev : NULL,
				     virt_to_phys(mem_regions), mem_regions_sz,
				     virt_to_phys(srcvms), src_sz,
				     virt_to_phys(newvms), newvms_sz);
}
EXPORT_SYMBOL(qcom_scm_assign_mem_regions);

/**
 * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership
 * @mem_addr: mem region whose ownership need to be reassigned
+47 −0
Original line number Diff line number Diff line
@@ -24,6 +24,19 @@ struct qcom_scm_vmperm {
	int perm;
};

struct qcom_scm_current_perm_info {
	__le32 vmid;
	__le32 perm;
	__le64 ctx;
	__le32 ctx_size;
	__le32 unused;
};

struct qcom_scm_mem_map_info {
	__le64 mem_addr;
	__le64 mem_size;
};

#define QCOM_SCM_VMID_HLOS       0x3
#define QCOM_SCM_VMID_MSS_MSA    0xF
#define QCOM_SCM_VMID_WLAN       0x18
@@ -34,6 +47,30 @@ struct qcom_scm_vmperm {
#define QCOM_SCM_PERM_RW (QCOM_SCM_PERM_READ | QCOM_SCM_PERM_WRITE)
#define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC)

static inline void qcom_scm_populate_vmperm_info(
		struct qcom_scm_current_perm_info *destvm, int vmid, int perm)
{
	if (!destvm)
		return;

	destvm->vmid = cpu_to_le32(vmid);
	destvm->perm = cpu_to_le32(perm);
	destvm->ctx = 0;
	destvm->ctx_size = 0;
}

static inline void qcom_scm_populate_mem_map_info(
				struct qcom_scm_mem_map_info *mem_to_map,
				phys_addr_t mem_addr, size_t mem_size)
{
	if (!mem_to_map)
		return;

	mem_to_map->mem_addr = cpu_to_le64(mem_addr);
	mem_to_map->mem_size = cpu_to_le64(mem_size);
}


#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);
@@ -68,6 +105,11 @@ extern int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg,
				unsigned long iova, size_t total_len);
extern int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx,
				unsigned long iova, size_t total_len);
extern int
qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions,
			    size_t mem_regions_sz, u32 *srcvms, size_t src_sz,
			    struct qcom_scm_current_perm_info *newvms,
			    size_t newvms_sz);
extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
			       unsigned int *src,
			       const struct qcom_scm_vmperm *newvm,
@@ -183,6 +225,11 @@ static inline int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr,
		unsigned long iova, size_t total_len) { return -ENODEV; }
static inline int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx,
		unsigned long iova, size_t total_len) { return -ENODEV; }
static inline int
qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions,
			    size_t mem_regions_sz, u32 *srcvms, size_t src_sz,
			    struct qcom_scm_current_perm_info *newvms,
			    size_t newvms_sz) { return -ENODEV; }
static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
				      unsigned int *src,
				      const struct qcom_scm_vmperm *newvm,