From fb44e7f642d4e7f6203ea7d2beb32a81cec592be Mon Sep 17 00:00:00 2001 From: Deepansh Rastogi Date: Thu, 28 Jul 2022 00:47:23 +0530 Subject: [PATCH] remoteproc: helios: using SMCInvoke instead of Qseecom framework Migrate kernel client for Helios PIL TA usecase from legacy Qseecom framework to pure SMCInvoke transport mechanism. Change-Id: I717e717c6ee59bde973153f229fc277c92293a4b Signed-off-by: Deepansh Rastogi --- drivers/remoteproc/qcom_rproc_helios.c | 334 +++++++++++++++----- drivers/soc/qcom/helios_app_smc_interface.h | 84 +++++ 2 files changed, 333 insertions(+), 85 deletions(-) create mode 100644 drivers/soc/qcom/helios_app_smc_interface.h diff --git a/drivers/remoteproc/qcom_rproc_helios.c b/drivers/remoteproc/qcom_rproc_helios.c index 4414f48592a69..0eefc3fe453b9 100644 --- a/drivers/remoteproc/qcom_rproc_helios.c +++ b/drivers/remoteproc/qcom_rproc_helios.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "../soc/qcom/helioscom.h" @@ -33,13 +35,23 @@ #include "qcom_pil_info.h" #include "remoteproc_internal.h" -#define SECURE_APP "heliosapp" +#include "../soc/qcom/helios_app_smc_interface.h" + +#include +#include +#include +#include +#include +#include +#include #define RESULT_SUCCESS 0 #define RESULT_FAILURE -1 -/* Helios Ramdump Size 3100 KB */ -#define HELIOS_RAMDUMP_SZ (0x307000) +/* Helios Ramdump Size 4 MB */ +#define HELIOS_RAMDUMP_SZ SZ_4M + +uint32_t helios_app_uid = 286; /* tzapp command list.*/ enum helios_tz_commands { @@ -153,31 +165,6 @@ static void helios_crash_handler(void *handle, void *priv) rproc_report_crash(helios_rproc, RPROC_FATAL_ERROR); } -/** - * get_cmd_rsp_buffers() - Function sets cmd & rsp buffer pointers and - * aligns buffer lengths - * @handle: index of qseecom_handle - * @cmd: req buffer - set to qseecom_handle.sbuf - * @cmd_len: ptr to req buffer len - * @rsp: rsp buffer - set to qseecom_handle.sbuf + offset - * @rsp_len: ptr to rsp buffer len - * - * Return: Success always . - */ -static int get_cmd_rsp_buffers(struct qseecom_handle *handle, void **cmd, - uint32_t *cmd_len, void **rsp, uint32_t *rsp_len) -{ - *cmd = handle->sbuf; - if (*cmd_len & QSEECOM_ALIGN_MASK) - *cmd_len = QSEECOM_ALIGN(*cmd_len); - - *rsp = handle->sbuf + *cmd_len; - if (*rsp_len & QSEECOM_ALIGN_MASK) - *rsp_len = QSEECOM_ALIGN(*rsp_len); - - return 0; -} - /** * load_helios_tzapp() - Called to load TZ app. * @pbd: struct containing private data. @@ -186,23 +173,122 @@ static int get_cmd_rsp_buffers(struct qseecom_handle *handle, void **cmd, */ static int load_helios_tzapp(struct qcom_helios *pbd) { - int rc; - - /* return success if already loaded */ - if (pbd->qseecom_handle && !pbd->app_status) - return 0; + int rc = 0; + uint8_t *buffer = NULL; + struct qtee_shm shm = {0}; + size_t size = 0; + char *app_name = "heliosapp"; + struct Object client_env = {NULL, NULL}; + struct Object app_client = {NULL, NULL}; + struct Object app_loader = {NULL, NULL}; + struct Object app_controller_obj = {NULL, NULL}; + + pbd->app_status = RESULT_FAILURE; /* Load the APP */ pr_debug("Start loading of secure app\n"); - rc = qseecom_start_app(&pbd->qseecom_handle, SECURE_APP, SZ_4K); - if (rc < 0) { - dev_err(pbd->dev, " TZ app load failure\n"); - pbd->app_status = RESULT_FAILURE; - return -EIO; + rc = get_client_env_object(&client_env); + if (rc) { + client_env.invoke = NULL; + client_env.context = NULL; + dev_err(pbd->dev, " get client env object failure\n"); + rc = -EIO; + goto end; } + + rc = IClientEnv_open(client_env, CAppLoader_UID, &app_loader); + if (rc) { + app_loader.invoke = NULL; + app_loader.context = NULL; + dev_err(pbd->dev, " IClientEnv_open failure\n"); + rc = -EIO; + goto end; + } + + buffer = firmware_request_from_smcinvoke(app_name, &size, &shm); + if (buffer == NULL) { + dev_err(pbd->dev, "firmware_request_from_smcinvoke failure\n"); + rc = -EINVAL; + goto end; + } + + rc = IAppLoader_loadFromBuffer(app_loader, (const void *)buffer, size, + &app_controller_obj); + if (rc) { + app_controller_obj.invoke = NULL; + app_controller_obj.context = NULL; + dev_err(pbd->dev, " IAppLoader_loadFromBuffer failure\n"); + rc = -EIO; + goto end; + } + + rc = IClientEnv_open(client_env, CAppClient_UID, &app_client); + if (rc) { + app_client.invoke = NULL; + app_client.context = NULL; + dev_err(pbd->dev, " CAppClient_UID failure\n"); + rc = -EIO; + goto end; + } + pbd->app_status = RESULT_SUCCESS; - pr_debug("App loaded\n"); - return 0; +end: + Object_ASSIGN_NULL(app_controller_obj); + Object_ASSIGN_NULL(app_loader); + Object_ASSIGN_NULL(client_env); + Object_ASSIGN_NULL(app_client); + return rc; +} + +static int32_t get_helios_app_object(struct Object *helios_app_obj) +{ + int32_t ret = 0; + const char *app_name = "heliosapp"; + struct Object remote_obj = {NULL, NULL}; + struct Object client_env = {NULL, NULL}; + struct Object app_client = {NULL, NULL}; + + ret = get_client_env_object(&client_env); + if (ret) { + client_env.invoke = NULL; + client_env.context = NULL; + pr_err(" get client env object failure:[%d]\n", ret); + ret = -EIO; + goto end; + } + + ret = IClientEnv_open(client_env, CAppClient_UID, &app_client); + if (ret) { + app_client.invoke = NULL; + app_client.context = NULL; + pr_err(" CAppClient_UID failure:[%d]\n", ret); + ret = -EIO; + goto end; + } + + ret = IAppClient_getAppObject(app_client, app_name, strlen(app_name), &remote_obj); + if (ret) { + pr_err("IAppClient_getAppObject failure:[%d]\n", ret); + remote_obj.invoke = NULL; + remote_obj.context = NULL; + ret = -EIO; + goto end; + } + + ret = IOpener_open(remote_obj, helios_app_uid, helios_app_obj); + if (ret) { + pr_err("IOpener_open failure: ret:[%d]\n", ret); + helios_app_obj->invoke = NULL; + helios_app_obj->context = NULL; + ret = -EIO; + goto end; + } + +end: + Object_ASSIGN_NULL(remote_obj); + Object_ASSIGN_NULL(client_env); + Object_ASSIGN_NULL(app_client); + return ret; } /** @@ -215,32 +301,62 @@ static int load_helios_tzapp(struct qcom_helios *pbd) static long helios_tzapp_comm(struct qcom_helios *pbd, struct tzapp_helios_req *req) { - struct tzapp_helios_req *helios_tz_req; - struct tzapp_helios_rsp *helios_tz_rsp; - int rc, req_len, rsp_len; - - /* Fill command structure */ - req_len = sizeof(struct tzapp_helios_req); - rsp_len = sizeof(struct tzapp_helios_rsp); - rc = get_cmd_rsp_buffers(pbd->qseecom_handle, - (void **)&helios_tz_req, &req_len, - (void **)&helios_tz_rsp, &rsp_len); - if (rc) - goto end; + int32_t ret = 0; + struct Object helios_app_obj = {NULL, NULL}; + size_t rsp_len = 0; - helios_tz_req->tzapp_helios_cmd = req->tzapp_helios_cmd; - helios_tz_req->address_fw = req->address_fw; - helios_tz_req->size_fw = req->size_fw; + pr_debug("command id = %d\n", req->tzapp_helios_cmd); + ret = get_helios_app_object(&helios_app_obj); + if (ret) { + dev_err(pbd->dev, " Failed to get helios TA context\n"); + goto end; + } - rc = qseecom_send_command(pbd->qseecom_handle, - (void *)helios_tz_req, req_len, (void *)helios_tz_rsp, rsp_len); - if (rc || helios_tz_rsp->status) - pbd->cmd_status = helios_tz_rsp->status; - else - pbd->cmd_status = 0; + switch (req->tzapp_helios_cmd) { + + case HELIOS_RPROC_AUTH_MDT: + pbd->cmd_status = helios_app_load_meta_data( + helios_app_obj, + (void *)req, + sizeof(struct tzapp_helios_req)); + + break; + + case HELIOS_RPROC_IMAGE_LOAD: + pbd->cmd_status = helios_app_transfer_and_authenticate_fw( + helios_app_obj, + (void *)req, + sizeof(struct tzapp_helios_req)); + break; + + case HELIOS_RPROC_RAMDUMP: + pbd->cmd_status = helios_app_collect_ramdump( + helios_app_obj, + (void *)req, + sizeof(struct tzapp_helios_req), + &rsp_len); + break; + + case HELIOS_RPROC_RESTART: + pbd->cmd_status = helios_app_force_restart(helios_app_obj); + break; + + case HELIOS_RPROC_SHUTDOWN: + pbd->cmd_status = helios_app_shutdown(helios_app_obj); + break; + + case HELIOS_RPROC_POWERDOWN: + pbd->cmd_status = helios_app_force_power_down(helios_app_obj); + break; + + default: + pr_debug("Invalid command\n"); + break; + } end: - return rc; + Object_ASSIGN_NULL(helios_app_obj); + return ret; } /** @@ -349,7 +465,7 @@ static int helios_prepare(struct rproc *rproc) int ret = 0; init_completion(&helios->err_ready); - if (!helios->qseecom_handle) { + if (helios->app_status != RESULT_SUCCESS) { ret = load_helios_tzapp(helios); if (ret) { dev_err(helios->dev, @@ -357,8 +473,9 @@ static int helios_prepare(struct rproc *rproc) __func__); return ret; } - helios->is_ready = true; } + helios->is_ready = true; + pr_debug("heliosapp loaded\n"); return ret; } @@ -608,7 +725,26 @@ static void helios_coredump(struct rproc *rproc) start_addr, DMA_ATTR_SKIP_ZEROING); } -static int helios_shutdown(struct rproc *rproc) +static int helios_force_powerdown(struct qcom_helios *helios) +{ + int ret; + struct tzapp_helios_req helios_tz_req; + + pr_debug("Force powerdown helios\n"); + helios_tz_req.tzapp_helios_cmd = HELIOS_RPROC_POWERDOWN; + helios_tz_req.address_fw = 0; + helios_tz_req.size_fw = 0; + ret = helios_tzapp_comm(helios, &helios_tz_req); + if (ret || helios->cmd_status) { + dev_err(helios->dev, "%s: Helios Power Down failed\n", __func__); + return helios->cmd_status; + } + + pr_debug("Helios is powered down.\n"); + return ret; +} + +static int helios_force_restart(struct rproc *rproc) { struct qcom_helios *helios = (struct qcom_helios *)rproc->priv; struct tzapp_helios_req helios_tz_req; @@ -626,31 +762,54 @@ static int helios_shutdown(struct rproc *rproc) pr_info("A2H response is received! Collect ramdump now!\n"); helios_coredump(rproc); } else { - /* Helios is not responding. So forcing S3 reset to power down Helios n Yoda + /* Helios is not responding. So forcing S3 reset to power down Helios + * and Yoda. It should be powered on in Start Sequence. + */ + pr_debug("Helios is not responding. Powerdown helios\n"); + ret = helios_force_powerdown(helios); + if (ret) { + dev_err(helios->dev, "%s: Helios Power Down failed\n", __func__); + return ret; + } + } + + pr_debug("Helios Restart is success!\n"); + return ret; +} + +static int helios_shutdown(struct rproc *rproc) +{ + struct qcom_helios *helios = rproc->priv; + struct tzapp_helios_req helios_tz_req; + int ret; + + helios_tz_req.tzapp_helios_cmd = HELIOS_RPROC_SHUTDOWN; + helios_tz_req.address_fw = 0; + helios_tz_req.size_fw = 0; + + ret = helios_tzapp_comm(helios, &helios_tz_req); + if (ret || helios->cmd_status) { + /* Helios is not responding. So forcing S3 reset to power down Helios. * It should be powered on in Start Sequence. - * If Helios not responding, we need to Helios SSR or Aurora+Helios power cycle */ - pr_debug("Powerdown helios\n"); - helios_tz_req.tzapp_helios_cmd = HELIOS_RPROC_POWERDOWN; - helios_tz_req.address_fw = 0; - helios_tz_req.size_fw = 0; - ret = helios_tzapp_comm(helios, &helios_tz_req); - if (ret || helios->cmd_status) { + pr_debug("Helios is not responding. Powerdown helios\n"); + ret = helios_force_powerdown(helios); + if (ret) { dev_err(helios->dev, "%s: Helios Power Down failed\n", __func__); - return helios->cmd_status; + return ret; } - pr_debug("Helios is powered down.\n"); } + pr_debug("Helios Shutdown is success!\n"); return ret; } /** * helios_stop() - Called by stop operation of remoteproc framework - * Triggers a watchdog bite in helios to start ramdump collection + * It can help to force restart or shutdown Helios based on recovery option. * @rproc: struct containing private helios data. * - * Return: always success + * Return: success or TA response error code */ static int helios_stop(struct rproc *rproc) { @@ -659,14 +818,18 @@ static int helios_stop(struct rproc *rproc) /* In case of crash, STOP operation is dummy */ if (rproc->state == RPROC_CRASHED) { - pr_err("Helios is crashed!. No need to do anything here! Collect ramdump directly.\n"); + pr_err("Helios is crashed! Skip stop and collect ramdump directly.\n"); return ret; } - if (helios->is_ready) - ret = helios_shutdown(rproc); + if (helios->is_ready) { + if (rproc->recovery_disabled) + ret = helios_shutdown(rproc); + else + ret = helios_force_restart(rproc); + } - pr_info("Helios Shutdown is success\n"); + pr_info("Helios Stop is %s\n", ret ? "failed" : "success"); return ret; } @@ -688,16 +851,16 @@ static int helios_reboot_notify(struct notifier_block *nb, unsigned long action, if (action != SYS_RESTART) return NOTIFY_OK; - pr_debug("System is going for reboot!. Powerdown helios.\n"); - helios_tz_req.tzapp_helios_cmd = HELIOS_RPROC_POWERDOWN; + pr_debug("System is going for reboot!. Shutdown helios.\n"); + helios_tz_req.tzapp_helios_cmd = HELIOS_RPROC_SHUTDOWN; helios_tz_req.address_fw = 0; helios_tz_req.size_fw = 0; ret = helios_tzapp_comm(helios, &helios_tz_req); if (ret || helios->cmd_status) { - dev_err(helios->dev, "%s: Helios Power Down failed\n", __func__); + dev_err(helios->dev, "%s: Helios Shutdown failed\n", __func__); return helios->cmd_status; } - pr_debug("Helios is powered down.\n"); + pr_debug("Helios is Shutdown successfully.\n"); return NOTIFY_OK; } @@ -733,6 +896,7 @@ static int rproc_helios_driver_probe(struct platform_device *pdev) helios->ssr_name = ssr_name; helios->firmware_name = fw_name; helios->dev = &pdev->dev; + helios->app_status = RESULT_FAILURE; rproc->dump_conf = RPROC_COREDUMP_ENABLED; rproc->recovery_disabled = true; rproc->auto_boot = false; diff --git a/drivers/soc/qcom/helios_app_smc_interface.h b/drivers/soc/qcom/helios_app_smc_interface.h new file mode 100644 index 0000000000000..8b78fd9035220 --- /dev/null +++ b/drivers/soc/qcom/helios_app_smc_interface.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +enum heliosapp_op { + LOAD_META_DATA, + TRANSFER_AND_AUTHENTICATE_FW, + COLLECT_RAMDUMP, + FORCE_RESTART, + SHUTDOWN, + FORCE_POWER_DOWN +}; + +static inline int32_t +helios_app_release(struct Object self) +{ + return Object_invoke(self, Object_OP_release, 0, 0); +} + +static inline int32_t +helios_app_retain(struct Object self) +{ + return Object_invoke(self, Object_OP_retain, 0, 0); +} + +static inline int32_t +helios_app_load_meta_data(struct Object self, const void *metadata_ptr, + size_t metadata_len) +{ + union ObjectArg arg[1] = {{{0, 0}}}; + + arg[0].bi = (struct ObjectBufIn) { metadata_ptr, metadata_len * 1 }; + + return Object_invoke(self, LOAD_META_DATA, arg, + ObjectCounts_pack(1, 0, 0, 0)); +} + +static inline int32_t +helios_app_transfer_and_authenticate_fw(struct Object self, + const void *firmware_ptr, size_t firmware_len) +{ + union ObjectArg arg[1] = {{{0, 0}}}; + + arg[0].bi = (struct ObjectBufIn) { firmware_ptr, firmware_len * 1 }; + + return Object_invoke(self, TRANSFER_AND_AUTHENTICATE_FW, arg, + ObjectCounts_pack(1, 0, 0, 0)); +} + +static inline int32_t +helios_app_collect_ramdump(struct Object self, void *ramdump_ptr, + size_t ramdump_len, size_t *ramdump_lenout) +{ + int32_t result; + union ObjectArg arg[1] = {{{0, 0}}}; + + arg[0].b = (struct ObjectBuf) { ramdump_ptr, ramdump_len * 1 }; + + result = Object_invoke(self, COLLECT_RAMDUMP, arg, + ObjectCounts_pack(0, 1, 0, 0)); + + *ramdump_lenout = arg[0].b.size / 1; + + return result; +} + +static inline int32_t +helios_app_force_restart(struct Object self) +{ + return Object_invoke(self, FORCE_RESTART, 0, 0); +} + +static inline int32_t +helios_app_shutdown(struct Object self) +{ + return Object_invoke(self, SHUTDOWN, 0, 0); +} + +static inline int32_t +helios_app_force_power_down(struct Object self) +{ + return Object_invoke(self, FORCE_POWER_DOWN, 0, 0); +}