// SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved. * Copyright (C) 2015 Linaro Ltd.
*/
/** * struct arm_smccc_args * @args: The array of values used in registers in smc instruction
*/ struct arm_smccc_args { unsignedlong args[8];
};
/** * struct scm_legacy_command - one SCM command buffer * @len: total available memory for command and response * @buf_offset: start of command buffer * @resp_hdr_offset: start of response buffer * @id: command to be executed * @buf: buffer returned from scm_legacy_get_command_buffer() * * An SCM command is laid out in memory as follows: * * ------------------- <--- struct scm_legacy_command * | command header | * ------------------- <--- scm_legacy_get_command_buffer() * | command buffer | * ------------------- <--- struct scm_legacy_response and * | response header | scm_legacy_command_to_response() * ------------------- <--- scm_legacy_get_response_buffer() * | response buffer | * ------------------- * * There can be arbitrary padding between the headers and buffers so * you should always use the appropriate scm_legacy_get_*_buffer() routines * to access the buffers in a safe manner.
*/ struct scm_legacy_command {
__le32 len;
__le32 buf_offset;
__le32 resp_hdr_offset;
__le32 id;
__le32 buf[];
};
/** * struct scm_legacy_response - one SCM response buffer * @len: total available memory for response * @buf_offset: start of response data relative to start of scm_legacy_response * @is_complete: indicates if the command has finished processing
*/ struct scm_legacy_response {
__le32 len;
__le32 buf_offset;
__le32 is_complete;
};
/** * scm_legacy_command_to_response() - Get a pointer to a scm_legacy_response * @cmd: command * * Returns a pointer to a response for a command.
*/ staticinlinestruct scm_legacy_response *scm_legacy_command_to_response( conststruct scm_legacy_command *cmd)
{ return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
}
/** * scm_legacy_get_command_buffer() - Get a pointer to a command buffer * @cmd: command * * Returns a pointer to the command buffer of a command.
*/ staticinlinevoid *scm_legacy_get_command_buffer( conststruct scm_legacy_command *cmd)
{ return (void *)cmd->buf;
}
/** * scm_legacy_get_response_buffer() - Get a pointer to a response buffer * @rsp: response * * Returns a pointer to a response buffer of a response.
*/ staticinlinevoid *scm_legacy_get_response_buffer( conststruct scm_legacy_response *rsp)
{ return (void *)rsp + le32_to_cpu(rsp->buf_offset);
}
/** * scm_legacy_call() - Sends a command to the SCM and waits for the command to * finish processing. * @dev: device * @desc: descriptor structure containing arguments and return values * @res: results from SMC call * * A note on cache maintenance: * Note that any buffers that are expected to be accessed by the secure world * must be flushed before invoking qcom_scm_call and invalidated in the cache * immediately after qcom_scm_call returns. Cache maintenance on the command * and response buffers is taken care of by qcom_scm_call; however, callers are * responsible for any other cached buffers passed over to the secure world.
*/ int scm_legacy_call(struct device *dev, conststruct qcom_scm_desc *desc, struct qcom_scm_res *res)
{
u8 arglen = desc->arginfo & 0xf; int ret = 0, context_id; unsignedint i; struct scm_legacy_command *cmd; struct scm_legacy_response *rsp; struct arm_smccc_args smc = {0}; struct arm_smccc_res smc_res; const size_t cmd_len = arglen * sizeof(__le32); const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof(__le32);
size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;
dma_addr_t cmd_phys;
__le32 *arg_buf; const __le32 *res_buf;
cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL); if (!cmd) return -ENOMEM;
mutex_lock(&qcom_scm_lock);
__scm_legacy_do(&smc, &smc_res); if (smc_res.a0)
ret = qcom_scm_remap_error(smc_res.a0);
mutex_unlock(&qcom_scm_lock); if (ret) goto out;
do {
dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len, sizeof(*rsp), DMA_FROM_DEVICE);
} while (!rsp->is_complete);
/** * scm_legacy_call_atomic() - Send an atomic SCM command with up to 5 arguments * and 3 return values * @unused: device, legacy argument, not used, can be NULL * @desc: SCM call descriptor containing arguments * @res: SCM call return values * * This shall only be used with commands that are guaranteed to be * uninterruptable, atomic and SMP safe.
*/ int scm_legacy_call_atomic(struct device *unused, conststruct qcom_scm_desc *desc, struct qcom_scm_res *res)
{ int context_id; struct arm_smccc_res smc_res;
size_t arglen = desc->arginfo & 0xf;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.