Loading drivers/soc/qcom/scm.c +44 −25 Original line number Diff line number Diff line /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2018, 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 Loading Loading @@ -357,28 +357,7 @@ static int allocate_extra_arg_buffer(struct scm_desc *desc, gfp_t flags) return 0; } /** * scm_call2() - Invoke a syscall in the secure world * @fn_id: The function ID for this syscall * @desc: Descriptor structure containing arguments and return values * * Sends a command to the SCM and waits for the command to finish processing. * This should *only* be called in pre-emptible context. * * A note on cache maintenance: * Note that any buffers that are expected to be accessed by the secure world * must be flushed before invoking scm_call and invalidated in the cache * immediately after scm_call returns. An important point that must be noted * is that on ARMV8 architectures, invalidation actually also causes a dirty * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of * paramount importance that the buffer be flushed before invoking scm_call2, * even if you don't care about the contents of that buffer. * * Note that cache maintenance on the argument buffer (desc->args) is taken care * of by scm_call2; however, callers are responsible for any other cached * buffers passed over to the secure world. */ int scm_call2(u32 fn_id, struct scm_desc *desc) static int __scm_call2(u32 fn_id, struct scm_desc *desc, bool retry) { int arglen = desc->arginfo & 0xf; int ret, retry_count = 0; Loading Loading @@ -419,13 +398,15 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) mutex_unlock(&scm_lmh_lock); mutex_unlock(&scm_lock); if (!retry) goto out; if (ret == SCM_V2_EBUSY) msleep(SCM_EBUSY_WAIT_MS); if (retry_count == 33) pr_warn("scm: secure world has been busy for 1 second!\n"); } while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); out: trace_scm_call_end(desc); if (ret < 0) pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", Loading @@ -437,8 +418,46 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) return scm_remap_error(ret); return 0; } /** * scm_call2() - Invoke a syscall in the secure world * @fn_id: The function ID for this syscall * @desc: Descriptor structure containing arguments and return values * * Sends a command to the SCM and waits for the command to finish processing. * This should *only* be called in pre-emptible context. * * A note on cache maintenance: * Note that any buffers that are expected to be accessed by the secure world * must be flushed before invoking scm_call and invalidated in the cache * immediately after scm_call returns. An important point that must be noted * is that on ARMV8 architectures, invalidation actually also causes a dirty * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of * paramount importance that the buffer be flushed before invoking scm_call2, * even if you don't care about the contents of that buffer. * * Note that cache maintenance on the argument buffer (desc->args) is taken care * of by scm_call2; however, callers are responsible for any other cached * buffers passed over to the secure world. */ int scm_call2(u32 fn_id, struct scm_desc *desc) { return __scm_call2(fn_id, desc, true); } EXPORT_SYMBOL(scm_call2); /** * scm_call2_noretry() - Invoke a syscall in the secure world * * Similar to scm_call2 except that there is no retry mechanism * implemented. */ int scm_call2_noretry(u32 fn_id, struct scm_desc *desc) { return __scm_call2(fn_id, desc, false); } EXPORT_SYMBOL(scm_call2_noretry); /** * scm_call2_atomic() - Invoke a syscall in the secure world * Loading include/soc/qcom/scm.h +7 −1 Original line number Diff line number Diff line /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2018, 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 Loading Loading @@ -98,6 +98,7 @@ struct scm_desc { #define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) extern int scm_call2(u32 cmd_id, struct scm_desc *desc); extern int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc); extern int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc); extern u32 scm_get_version(void); extern int scm_is_call_available(u32 svc_id, u32 cmd_id); Loading @@ -114,6 +115,11 @@ static inline int scm_call2(u32 cmd_id, struct scm_desc *desc) return 0; } static inline int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc) { return 0; } static inline int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc) { return 0; Loading Loading
drivers/soc/qcom/scm.c +44 −25 Original line number Diff line number Diff line /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2018, 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 Loading Loading @@ -357,28 +357,7 @@ static int allocate_extra_arg_buffer(struct scm_desc *desc, gfp_t flags) return 0; } /** * scm_call2() - Invoke a syscall in the secure world * @fn_id: The function ID for this syscall * @desc: Descriptor structure containing arguments and return values * * Sends a command to the SCM and waits for the command to finish processing. * This should *only* be called in pre-emptible context. * * A note on cache maintenance: * Note that any buffers that are expected to be accessed by the secure world * must be flushed before invoking scm_call and invalidated in the cache * immediately after scm_call returns. An important point that must be noted * is that on ARMV8 architectures, invalidation actually also causes a dirty * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of * paramount importance that the buffer be flushed before invoking scm_call2, * even if you don't care about the contents of that buffer. * * Note that cache maintenance on the argument buffer (desc->args) is taken care * of by scm_call2; however, callers are responsible for any other cached * buffers passed over to the secure world. */ int scm_call2(u32 fn_id, struct scm_desc *desc) static int __scm_call2(u32 fn_id, struct scm_desc *desc, bool retry) { int arglen = desc->arginfo & 0xf; int ret, retry_count = 0; Loading Loading @@ -419,13 +398,15 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) mutex_unlock(&scm_lmh_lock); mutex_unlock(&scm_lock); if (!retry) goto out; if (ret == SCM_V2_EBUSY) msleep(SCM_EBUSY_WAIT_MS); if (retry_count == 33) pr_warn("scm: secure world has been busy for 1 second!\n"); } while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); out: trace_scm_call_end(desc); if (ret < 0) pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", Loading @@ -437,8 +418,46 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) return scm_remap_error(ret); return 0; } /** * scm_call2() - Invoke a syscall in the secure world * @fn_id: The function ID for this syscall * @desc: Descriptor structure containing arguments and return values * * Sends a command to the SCM and waits for the command to finish processing. * This should *only* be called in pre-emptible context. * * A note on cache maintenance: * Note that any buffers that are expected to be accessed by the secure world * must be flushed before invoking scm_call and invalidated in the cache * immediately after scm_call returns. An important point that must be noted * is that on ARMV8 architectures, invalidation actually also causes a dirty * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of * paramount importance that the buffer be flushed before invoking scm_call2, * even if you don't care about the contents of that buffer. * * Note that cache maintenance on the argument buffer (desc->args) is taken care * of by scm_call2; however, callers are responsible for any other cached * buffers passed over to the secure world. */ int scm_call2(u32 fn_id, struct scm_desc *desc) { return __scm_call2(fn_id, desc, true); } EXPORT_SYMBOL(scm_call2); /** * scm_call2_noretry() - Invoke a syscall in the secure world * * Similar to scm_call2 except that there is no retry mechanism * implemented. */ int scm_call2_noretry(u32 fn_id, struct scm_desc *desc) { return __scm_call2(fn_id, desc, false); } EXPORT_SYMBOL(scm_call2_noretry); /** * scm_call2_atomic() - Invoke a syscall in the secure world * Loading
include/soc/qcom/scm.h +7 −1 Original line number Diff line number Diff line /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2010-2018, 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 Loading Loading @@ -98,6 +98,7 @@ struct scm_desc { #define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) extern int scm_call2(u32 cmd_id, struct scm_desc *desc); extern int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc); extern int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc); extern u32 scm_get_version(void); extern int scm_is_call_available(u32 svc_id, u32 cmd_id); Loading @@ -114,6 +115,11 @@ static inline int scm_call2(u32 cmd_id, struct scm_desc *desc) return 0; } static inline int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc) { return 0; } static inline int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc) { return 0; Loading