Browse Source

fix(xilinx): fix logic to read ipi response

Currently, PLM IPI command supports total 8 32-bit payloads. But existing
logic to read IPI response in TF-A is trying to read 9 32-bit payloads
(ret status + 8 ret payloads) in case of IPI_CRC_CHECK enabled which is
incorrect.

So, fix logic to read only 8 32-bit payloads (ret status + 6 ret payloads + CRC)
in case when IPI_CRC_CHECK is enabled and read 7 32-bit payloads
(ret status + 5 ret payloads + CRC) in case when IPI_CRC_CHECK is disabled.

Signed-off-by: Jay Buddhabhatti <jay.buddhabhatti@amd.com>
Change-Id: I0abca2f787cc7a66fdd5522e6bd15a9771029071
pull/2005/merge
Jay Buddhabhatti 5 months ago
parent
commit
03fa6f4250
  1. 6
      plat/xilinx/common/include/pm_common.h
  2. 4
      plat/xilinx/common/pm_service/pm_api_sys.c
  3. 39
      plat/xilinx/common/pm_service/pm_ipi.c
  4. 4
      plat/xilinx/common/pm_service/pm_svc_main.c
  5. 2
      plat/xilinx/versal/plat_psci.c
  6. 2
      plat/xilinx/versal_net/plat_psci_pm.c
  7. 2
      plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
  8. 4
      plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c

6
plat/xilinx/common/include/pm_common.h

@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -18,13 +18,15 @@
#if IPI_CRC_CHECK
#define PAYLOAD_ARG_CNT 8U
#define RET_PAYLOAD_ARG_CNT 7U
#define IPI_W0_TO_W6_SIZE 28U
#define PAYLOAD_CRC_POS 7U
#define CRC_INIT_VALUE 0x4F4EU
#define CRC_ORDER 16U
#define CRC_POLYNOM 0x8005U
#else
#define PAYLOAD_ARG_CNT 6U
#define PAYLOAD_ARG_CNT 7U
#define RET_PAYLOAD_ARG_CNT 6U
#endif
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */

4
plat/xilinx/common/pm_service/pm_api_sys.c

@ -122,7 +122,7 @@ enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
}
PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, RET_PAYLOAD_ARG_CNT);
}
/**
@ -406,7 +406,7 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
PM_FEATURE_CHECK, api_id);
return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
return pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT);
}
/**

39
plat/xilinx/common/pm_service/pm_ipi.c

@ -1,7 +1,7 @@
/*
* Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -164,15 +164,10 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
*
*/
static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
uint32_t *value, size_t count)
uint32_t value[PAYLOAD_ARG_CNT])
{
size_t i;
enum pm_ret_status ret;
#if IPI_CRC_CHECK
uint32_t *payload_ptr = value;
size_t j;
uint32_t response_payload[PAYLOAD_ARG_CNT];
#endif
uintptr_t buffer_base = proc->ipi->buffer_base +
IPI_BUFFER_TARGET_REMOTE_OFFSET +
IPI_BUFFER_RESP_OFFSET;
@ -184,27 +179,21 @@ static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
* buf-2: unused
* buf-3: unused
*/
for (i = 1; i <= count; i++) {
*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
value++;
for (i = 0; i < PAYLOAD_ARG_CNT; i++) {
value[i] = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
}
ret = mmio_read_32(buffer_base);
ret = value[0];
#if IPI_CRC_CHECK
for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
response_payload[j] = mmio_read_32(buffer_base +
(j * PAYLOAD_ARG_SIZE));
}
if (response_payload[PAYLOAD_CRC_POS] !=
calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
if (value[PAYLOAD_CRC_POS] !=
calculate_crc(value, IPI_W0_TO_W6_SIZE)) {
NOTICE("ERROR in CRC response payload value:0x%x\n",
response_payload[PAYLOAD_CRC_POS]);
value[PAYLOAD_CRC_POS]);
ret = PM_RET_ERROR_INVALID_CRC;
/* Payload data is invalid as CRC validation failed
* Clear the payload to avoid leakage of data to upper layers
*/
memset(payload_ptr, 0, count);
memset(value, 0, PAYLOAD_ARG_CNT);
}
#endif
@ -240,7 +229,7 @@ enum pm_ret_status pm_ipi_buff_read_callb(uint32_t *value, size_t count)
count = IPI_BUFFER_MAX_WORDS;
}
for (i = 0; i <= count; i++) {
for (i = 0; i < count; i++) {
*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
value++;
}
@ -282,6 +271,7 @@ enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
uint32_t *value, size_t count)
{
enum pm_ret_status ret;
uint32_t i, ret_payload[PAYLOAD_ARG_CNT] = {0U};
pm_ipi_lock_get();
@ -290,7 +280,12 @@ enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
goto unlock;
}
ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, ret_payload));
for (i = 1U; i <= count; i++) {
*value = ret_payload[i];
value++;
}
unlock:
pm_ipi_lock_release();

4
plat/xilinx/common/pm_service/pm_svc_main.c

@ -278,7 +278,7 @@ static uintptr_t eemi_for_compatibility(uint32_t api_id, uint32_t *pm_arg,
case (uint32_t)PM_FEATURE_CHECK:
{
uint32_t result[PAYLOAD_ARG_CNT] = {0U};
uint32_t result[RET_PAYLOAD_ARG_CNT] = {0U};
ret = pm_feature_check(pm_arg[0], result, security_flag);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
@ -424,7 +424,7 @@ static uintptr_t eemi_handler(uint32_t api_id, uint32_t *pm_arg,
void *handle, uint32_t security_flag)
{
enum pm_ret_status ret;
uint32_t buf[PAYLOAD_ARG_CNT] = {0};
uint32_t buf[RET_PAYLOAD_ARG_CNT] = {0};
ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4],

2
plat/xilinx/versal/plat_psci.c

@ -197,7 +197,7 @@ static void __dead2 versal_system_reset(void)
*/
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
{
uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);

2
plat/xilinx/versal_net/plat_psci_pm.c

@ -59,7 +59,7 @@ static int32_t versal_net_pwr_domain_on(u_register_t mpidr)
*/
static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
{
uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);

2
plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c

@ -919,7 +919,7 @@ static enum pm_ret_status feature_check_partial(uint32_t api_id,
enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
uint32_t *bit_mask, uint8_t len)
{
uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
uint32_t ret_payload[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t status;
/* Get API version implemented in TF-A */

4
plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c

@ -285,7 +285,7 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t pm_arg[5];
uint32_t result[PAYLOAD_ARG_CNT] = {0};
uint32_t result[RET_PAYLOAD_ARG_CNT] = {0};
uint32_t api_id;
/* Handle case where PM wasn't initialized properly */
@ -566,7 +566,7 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4]);
ret = pm_ipi_send_sync(primary_proc, payload, result,
PAYLOAD_ARG_CNT);
RET_PAYLOAD_ARG_CNT);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
(uint64_t)result[1] | ((uint64_t)result[2] << 32U));
}

Loading…
Cancel
Save