diff options
author | Vikram Mulukutla <markivx@codeaurora.org> | 2014-08-04 21:31:45 -0400 |
---|---|---|
committer | Kumar Gala <galak@codeaurora.org> | 2015-01-19 12:53:32 -0500 |
commit | 404b5a97f5a2a718bb0feccc3712b1ab88f073d5 (patch) | |
tree | 71750e563e24cef9437e2095d1cbaaf36c4c37a7 /arch/arm/mach-qcom | |
parent | 30cbb0c01bc98a2372966b8c5ac0ce1421cd933c (diff) |
ARM: qcom: scm: Flush the command buffer only instead of the entire cache
scm_call flushes the entire cache before calling into the secure world.
This is both a performance penalty as well as insufficient on SMP systems
where the CPUs possess a write-back L1 cache. Flush only the command and
response buffers instead, moving the responsibility of flushing any other
cached buffer (being passed to the secure world) to callers.
Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-qcom')
-rw-r--r-- | arch/arm/mach-qcom/scm.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index c08786ebf116..ec37b037e69c 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c | |||
@@ -196,12 +196,12 @@ static int __scm_call(const struct scm_command *cmd) | |||
196 | u32 cmd_addr = virt_to_phys(cmd); | 196 | u32 cmd_addr = virt_to_phys(cmd); |
197 | 197 | ||
198 | /* | 198 | /* |
199 | * Flush the entire cache here so callers don't have to remember | 199 | * Flush the command buffer so that the secure world sees |
200 | * to flush the cache when passing physical addresses to the secure | 200 | * the correct data. |
201 | * side in the buffer. | ||
202 | */ | 201 | */ |
203 | flush_cache_all(); | 202 | __cpuc_flush_dcache_area((void *)cmd, cmd->len); |
204 | outer_flush_all(); | 203 | outer_flush_range(cmd_addr, cmd_addr + cmd->len); |
204 | |||
205 | ret = smc(cmd_addr); | 205 | ret = smc(cmd_addr); |
206 | if (ret < 0) | 206 | if (ret < 0) |
207 | ret = scm_remap_error(ret); | 207 | ret = scm_remap_error(ret); |
@@ -238,6 +238,13 @@ static void scm_inv_range(unsigned long start, unsigned long end) | |||
238 | * @resp_len: length of the response buffer | 238 | * @resp_len: length of the response buffer |
239 | * | 239 | * |
240 | * Sends a command to the SCM and waits for the command to finish processing. | 240 | * Sends a command to the SCM and waits for the command to finish processing. |
241 | * | ||
242 | * A note on cache maintenance: | ||
243 | * Note that any buffers that are expected to be accessed by the secure world | ||
244 | * must be flushed before invoking scm_call and invalidated in the cache | ||
245 | * immediately after scm_call returns. Cache maintenance on the command and | ||
246 | * response buffers is taken care of by scm_call; however, callers are | ||
247 | * responsible for any other cached buffers passed over to the secure world. | ||
241 | */ | 248 | */ |
242 | int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, | 249 | int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, |
243 | void *resp_buf, size_t resp_len) | 250 | void *resp_buf, size_t resp_len) |