diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2015-01-21 14:21:15 -0500 |
---|---|---|
committer | Kumar Gala <galak@codeaurora.org> | 2015-01-23 11:19:33 -0500 |
commit | 7279db9287f226fbb3f349c3244f8dc4b783e645 (patch) | |
tree | 8054966b9f2447adce0e3a1ffcd0595806b02fef /arch/arm | |
parent | 65b4ab65538e0da8e03e05d137001f10c78273d0 (diff) |
ARM: qcom: Fix SCM interface for big-endian kernels
The secure environment only runs in little-endian mode, so any
buffers shared with the secure environment should have their
contents converted to little-endian. We also mark such elements
with __le32 to allow sparse to catch such problems.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-qcom/scm-boot.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-qcom/scm.c | 30 |
2 files changed, 20 insertions, 18 deletions
diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c index f2fa32834631..e8ff7beb6218 100644 --- a/arch/arm/mach-qcom/scm-boot.c +++ b/arch/arm/mach-qcom/scm-boot.c | |||
@@ -27,12 +27,12 @@ | |||
27 | int scm_set_boot_addr(u32 addr, int flags) | 27 | int scm_set_boot_addr(u32 addr, int flags) |
28 | { | 28 | { |
29 | struct { | 29 | struct { |
30 | unsigned int flags; | 30 | __le32 flags; |
31 | u32 addr; | 31 | __le32 addr; |
32 | } cmd; | 32 | } cmd; |
33 | 33 | ||
34 | cmd.addr = addr; | 34 | cmd.addr = cpu_to_le32(addr); |
35 | cmd.flags = flags; | 35 | cmd.flags = cpu_to_le32(flags); |
36 | return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, | 36 | return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, |
37 | &cmd, sizeof(cmd), NULL, 0); | 37 | &cmd, sizeof(cmd), NULL, 0); |
38 | } | 38 | } |
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c index a77349d34e78..1d9cf18c7091 100644 --- a/arch/arm/mach-qcom/scm.c +++ b/arch/arm/mach-qcom/scm.c | |||
@@ -61,11 +61,11 @@ static DEFINE_MUTEX(scm_lock); | |||
61 | * to access the buffers in a safe manner. | 61 | * to access the buffers in a safe manner. |
62 | */ | 62 | */ |
63 | struct scm_command { | 63 | struct scm_command { |
64 | u32 len; | 64 | __le32 len; |
65 | u32 buf_offset; | 65 | __le32 buf_offset; |
66 | u32 resp_hdr_offset; | 66 | __le32 resp_hdr_offset; |
67 | u32 id; | 67 | __le32 id; |
68 | u32 buf[0]; | 68 | __le32 buf[0]; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | /** | 71 | /** |
@@ -75,9 +75,9 @@ struct scm_command { | |||
75 | * @is_complete: indicates if the command has finished processing | 75 | * @is_complete: indicates if the command has finished processing |
76 | */ | 76 | */ |
77 | struct scm_response { | 77 | struct scm_response { |
78 | u32 len; | 78 | __le32 len; |
79 | u32 buf_offset; | 79 | __le32 buf_offset; |
80 | u32 is_complete; | 80 | __le32 is_complete; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /** | 83 | /** |
@@ -95,12 +95,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size) | |||
95 | struct scm_command *cmd; | 95 | struct scm_command *cmd; |
96 | size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + | 96 | size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + |
97 | resp_size; | 97 | resp_size; |
98 | u32 offset; | ||
98 | 99 | ||
99 | cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); | 100 | cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); |
100 | if (cmd) { | 101 | if (cmd) { |
101 | cmd->len = len; | 102 | cmd->len = cpu_to_le32(len); |
102 | cmd->buf_offset = offsetof(struct scm_command, buf); | 103 | offset = offsetof(struct scm_command, buf); |
103 | cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; | 104 | cmd->buf_offset = cpu_to_le32(offset); |
105 | cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size); | ||
104 | } | 106 | } |
105 | return cmd; | 107 | return cmd; |
106 | } | 108 | } |
@@ -125,7 +127,7 @@ static inline void free_scm_command(struct scm_command *cmd) | |||
125 | static inline struct scm_response *scm_command_to_response( | 127 | static inline struct scm_response *scm_command_to_response( |
126 | const struct scm_command *cmd) | 128 | const struct scm_command *cmd) |
127 | { | 129 | { |
128 | return (void *)cmd + cmd->resp_hdr_offset; | 130 | return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset); |
129 | } | 131 | } |
130 | 132 | ||
131 | /** | 133 | /** |
@@ -147,7 +149,7 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd) | |||
147 | */ | 149 | */ |
148 | static inline void *scm_get_response_buffer(const struct scm_response *rsp) | 150 | static inline void *scm_get_response_buffer(const struct scm_response *rsp) |
149 | { | 151 | { |
150 | return (void *)rsp + rsp->buf_offset; | 152 | return (void *)rsp + le32_to_cpu(rsp->buf_offset); |
151 | } | 153 | } |
152 | 154 | ||
153 | static int scm_remap_error(int err) | 155 | static int scm_remap_error(int err) |
@@ -259,7 +261,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, | |||
259 | if (!cmd) | 261 | if (!cmd) |
260 | return -ENOMEM; | 262 | return -ENOMEM; |
261 | 263 | ||
262 | cmd->id = (svc_id << 10) | cmd_id; | 264 | cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); |
263 | if (cmd_buf) | 265 | if (cmd_buf) |
264 | memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); | 266 | memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); |
265 | 267 | ||