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
diff --git a/plat/xilinx/common/include/pm_common.h b/plat/xilinx/common/include/pm_common.h
index c0308ab..c38cdef 100644
--- a/plat/xilinx/common/include/pm_common.h
+++ b/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 */
diff --git a/plat/xilinx/common/pm_service/pm_api_sys.c b/plat/xilinx/common/pm_service/pm_api_sys.c
index 0a6e810..1499285 100644
--- a/plat/xilinx/common/pm_service/pm_api_sys.c
+++ b/plat/xilinx/common/pm_service/pm_api_sys.c
@@ -122,7 +122,7 @@
}
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 @@
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);
}
/**
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 56567dd..205877c 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/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 @@
*
*/
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 @@
* 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 @@
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 @@
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 @@
goto unlock;
}
+ ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, ret_payload));
+
- ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
+ for (i = 1U; i <= count; i++) {
+ *value = ret_payload[i];
+ value++;
+ }
unlock:
pm_ipi_lock_release();
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index 7ac0ac1..1eb0c80 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -278,7 +278,7 @@
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 @@
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],
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 4cf1ed1..74c5bf3 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -197,7 +197,7 @@
*/
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);
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index e5a5235..fb2005d 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -59,7 +59,7 @@
*/
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);
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
index 3d546b3..66f011a 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
@@ -919,7 +919,7 @@
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 */
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
index 5a6a9f8..bf17ea4 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
@@ -285,7 +285,7 @@
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 @@
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));
}