diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index fc2081c2c94d..8a1451a93ea1 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -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 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 65df08faee23..5eb2c7be417f 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -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,