ARM: qcom: Fix SCM interface for big-endian kernels
Subsystems (2)
PATCH v2 1/1 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.
---
Changes since v1:
* Rebased onto Kumar's qcom/soc branch
drivers/soc/qcom/scm-boot.c | 8 ++++---- drivers/soc/qcom/scm.c | 30 ++++++++++++++++-------------- 2 files changed, 20 insertions(+), 18 deletions(-)
drivers/soc/qcom/scm-boot.c +4 -4
@@ -27,12 +27,12 @@int scm_set_boot_addr (u32 addr,int flags) {struct { -unsigned int flags; -phys_addr_t addr; +__le32 flags; +__le32 addr; } cmd; - cmd.addr = addr; - cmd.flags = flags; + cmd.addr =cpu_to_le32 (addr); + cmd.flags =cpu_to_le32 (flags);return scm_call (SCM_SVC_BOOT ,SCM_BOOT_ADDR , &cmd,sizeof (cmd),NULL ,0 ); }
drivers/soc/qcom/scm.c +16 -14
@@ -62,11 +62,11 @@ static DEFINE_MUTEX(scm_lock);* to access the buffers in a safe manner. */ struct scm_command { -u32 len; -u32 buf_offset; -u32 resp_hdr_offset; -u32 id; -u32 buf[0 ]; +__le32 len; +__le32 buf_offset; +__le32 resp_hdr_offset; +__le32 id; +__le32 buf[0 ]; };/**
@@ -76,9 +76,9 @@ struct scm_command {* @is_complete: indicates if the command has finished processing */ struct scm_response { -u32 len; -u32 buf_offset; -u32 is_complete; +__le32 len; +__le32 buf_offset; +__le32 is_complete; };/**
@@ -96,12 +96,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)struct scm_command *cmd;size_t len =sizeof (*cmd) +sizeof (struct scm_response ) + cmd_size + resp_size; +u32 offset; cmd =kzalloc (PAGE_ALIGN (len),GFP_KERNEL );if (cmd) { - cmd->len = len; - cmd->buf_offset = offsetof(struct scm_command , buf); - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; + cmd->len =cpu_to_le32 (len); + offset = offsetof(struct scm_command , buf); + cmd->buf_offset =cpu_to_le32 (offset); + cmd->resp_hdr_offset =cpu_to_le32 (offset + cmd_size); }return cmd; }
@@ -126,7 +128,7 @@ static inline void free_scm_command(struct scm_command *cmd)static inline struct scm_response *scm_command_to_response (const struct scm_command *cmd) { -return (void *)cmd + cmd->resp_hdr_offset; +return (void *)cmd +le32_to_cpu (cmd->resp_hdr_offset); }/**
@@ -148,7 +150,7 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd)*/ static inline void *scm_get_response_buffer (const struct scm_response *rsp) { -return (void *)rsp + rsp->buf_offset; +return (void *)rsp +le32_to_cpu (rsp->buf_offset); }static int scm_remap_error (int err)
@@ -260,7 +262,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,if (!cmd)return -ENOMEM ; - cmd->id = (svc_id <<10 ) | cmd_id; + cmd->id =cpu_to_le32 ((svc_id <<10 ) | cmd_id);if (cmd_buf)memcpy (scm_get_command_buffer (cmd), cmd_buf, cmd_len);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 20 lines · Stephen Boyd
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
__le32to allow sparse to catch such problems.Signed-off-by Stephen Boyd <[email protected]>---
Changes since v1:
* Rebased onto Kumar's qcom/soc branch
drivers/soc/qcom/scm-boot.c| 8 ++++----drivers/soc/qcom/scm.c| 30 ++++++++++++++++--------------2 files changed, 20 insertions(+), 18 deletions(-)drivers/soc/qcom/scm-boot.c +0
-0
drivers/soc/qcom/scm-boot.c line 31
Quoted 7 lines
drivers/soc/qcom/scm-boot.c +2
-2@@ -27,12 +27,12 @@int scm_set_boot_addr (u32 addr,int flags) {struct { -unsigned int flags; -phys_addr_t addr; +__le32 flags; +__le32 addr;
How does this work? How can we go from phys_addr_t back to __le32 on LPAE or 64-bit systems?
Quoted 96 lines
drivers/soc/qcom/scm-boot.c +2
-2} cmd; - cmd.addr = addr; - cmd.flags = flags; + cmd.addr =cpu_to_le32 (addr); + cmd.flags =cpu_to_le32 (flags);return scm_call (SCM_SVC_BOOT ,SCM_BOOT_ADDR , &cmd,sizeof (cmd),NULL ,0 ); }drivers/soc/qcom/scm.c +13
-11@@ -62,11 +62,11 @@ static DEFINE_MUTEX(scm_lock);* to access the buffers in a safe manner. */ struct scm_command { -u32 len; -u32 buf_offset; -u32 resp_hdr_offset; -u32 id; -u32 buf[0 ]; +__le32 len; +__le32 buf_offset; +__le32 resp_hdr_offset; +__le32 id; +__le32 buf[0 ]; };/** @@ -76,9 +76,9 @@ struct scm_command {* @is_complete: indicates if the command has finished processing */ struct scm_response { -u32 len; -u32 buf_offset; -u32 is_complete; +__le32 len; +__le32 buf_offset; +__le32 is_complete; };/** @@ -96,12 +96,14 @@ static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)struct scm_command *cmd;size_t len =sizeof (*cmd) +sizeof (struct scm_response ) + cmd_size + resp_size; +u32 offset; cmd =kzalloc (PAGE_ALIGN (len),GFP_KERNEL );if (cmd) { - cmd->len = len; - cmd->buf_offset = offsetof(struct scm_command , buf); - cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; + cmd->len =cpu_to_le32 (len); + offset = offsetof(struct scm_command , buf); + cmd->buf_offset =cpu_to_le32 (offset); + cmd->resp_hdr_offset =cpu_to_le32 (offset + cmd_size); }return cmd; }@@ -126,7 +128,7 @@ static inline void free_scm_command(struct scm_command *cmd)static inline struct
scm_response*scm_command_to_response(
const structscm_command*cmd)
{drivers/soc/qcom/scm.c +1
-1-return (void *)cmd + cmd->resp_hdr_offset; +return (void *)cmd +le32_to_cpu (cmd->resp_hdr_offset);}
/**
drivers/soc/qcom/scm.c +2
-2@@ -148,7 +150,7 @@ static inline void *scm_get_command_buffer(const struct scm_command *cmd)*/ static inline void *scm_get_response_buffer (const struct scm_response *rsp) { -return (void *)rsp + rsp->buf_offset; +return (void *)rsp +le32_to_cpu (rsp->buf_offset); }static int scm_remap_error (int err)@@ -260,7 +262,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,if (!cmd)return -ENOMEM ; - cmd->id = (svc_id <<10 ) | cmd_id; + cmd->id =cpu_to_le32 ((svc_id <<10 ) | cmd_id);if (cmd_buf)memcpy (scm_get_command_buffer (cmd), cmd_buf, cmd_len);Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 18 lines · Kumar Gala
Quoted 15 lines · Stephen Boyd
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
__le32to allow sparse to catch such problems.Signed-off-by Stephen Boyd <[email protected]>---
Changes since v1:
* Rebased onto Kumar's qcom/soc branch
drivers/soc/qcom/scm-boot.c| 8 ++++----drivers/soc/qcom/scm.c| 30 ++++++++++++++++--------------2 files changed, 20 insertions(+), 18 deletions(-)
Quoted 15 lines
drivers/soc/qcom/scm-boot.c line 31
Quoted 12 lines
drivers/soc/qcom/scm-boot.c +2
-2@@ -27,12 +27,12 @@int scm_set_boot_addr (u32 addr,int flags) {struct { -unsigned int flags; -phys_addr_t addr; +__le32 flags; +__le32 addr;How does this work? How can we go from
phys_addr_tback to__le32on LPAE or 64-bit systems?
I guess I missed updating this in the patch titled "Clarify boot interface". In that patch we should have updated addr to be a u32 (or __le32 as is done here). From what I can tell by looking at the codeaurora tree this is still 32 bits wide even on 64-bit platforms.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project