Hello,
I am currently developing TF-M on the RDV3R1 S/W platform, and I would like to report a potential issue observed during runtime with the integrity_checker_compute_value() function in BL2.
Problem Description:
Inside the integrity_checker_compute_value() function, the iccva register is set to the address of either the value or temp_val variable, as shown in the example below.
enum integrity_checker_error_t integrity_checker_compute_value(struct integrity_checker_dev_t *dev,
enum integrity_checker_mode_t mode,
const uint32_t *data, size_t size,
uint32_t *value, size_t value_size,
size_t *value_len)
{
volatile uint32_t __ALIGNED(INTEGRITY_CHECKER_REQUIRED_ALIGNMENT)
temp_val[INTEGRITY_CHECKER_OUTPUT_SIZE_SHA256 / sizeof(uint32_t)] = {0};
volatile uint32_t *value_ptr = value;
struct _integrity_checker_reg_map_t* p_integrity_checker =
(struct _integrity_checker_reg_map_t*)dev->cfg->base;
enum integrity_checker_error_t err;
uint32_t iccval = 0;
err = check_mode_is_supported(dev, mode, true);
if (err != INTEGRITY_CHECKER_ERROR_NONE) {
return err;
}
if (value_size < mode_sizes[mode]) {
FATAL_ERR(INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_BUFFER_TOO_SMALL);
return INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_BUFFER_TOO_SMALL;
}
if (((uintptr_t)data % INTEGRITY_CHECKER_REQUIRED_ALIGNMENT) != 0) {
FATAL_ERR(INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_INVALID_ALIGNMENT);
return INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_INVALID_ALIGNMENT;
}
if ((size % INTEGRITY_CHECKER_REQUIRED_ALIGNMENT) != 0) {
FATAL_ERR(INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_INVALID_LENGTH);
return INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_INVALID_LENGTH;
}
if (((uintptr_t)value % INTEGRITY_CHECKER_REQUIRED_ALIGNMENT) != 0) {
value_ptr = temp_val;
}
init_integrity_checker(dev, &iccval);
/* Set algorithm */
iccval |= (mode & 0b111) << 1;
/* Set to compute mode */
iccval |= 1 << 4;
/* Configure input data. Size is in words */
p_integrity_checker->icda = remap_addr(dev, (uintptr_t)data);
p_integrity_checker->icdl = size / INTEGRITY_CHECKER_REQUIRED_ALIGNMENT;
/* Set output address */
p_integrity_checker->iccva = remap_addr(dev, (uintptr_t)value_ptr);
/* Start integrity checker */
iccval |= 1;
p_integrity_checker->icc = iccval;
/* Poll for any interrupts */
while(!p_integrity_checker->icis) {}
/* Check for any unusual error interrupts */
if (p_integrity_checker->icis & (~0b11)) {
FATAL_ERR(INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_OPERATION_FAILED);
return INTEGRITY_CHECKER_ERROR_COMPUTE_VALUE_OPERATION_FAILED;
}
if (value_ptr != value) {
for (int idx = 0; idx < mode_sizes[mode] / sizeof(uint32_t); idx++) {
value[idx] = value_ptr[idx];
}
}
if (value_len != NULL) {
*value_len = mode_sizes[mode];
}
return INTEGRITY_CHECKER_ERROR_NONE;
}
static void init_integrity_checker(struct integrity_checker_dev_t *dev,
uint32_t *iccval)
{
struct _integrity_checker_reg_map_t* p_integrity_checker =
(struct _integrity_checker_reg_map_t*)dev->cfg->base;
/* Set MatchTriggerDisable, as it is mandatory. */
*iccval |= 1 << 5;
/* Set EncompvalOut so the integrity checker writes the value pointer in
* compute mode.
*/
*iccval |= 1 << 6;
*iccval |= (IC_APROT_SECURE_PRIVILEGED & 0b11) << 7;
*iccval |= (IC_APROT_SECURE_PRIVILEGED & 0b11) << 9;
/* Disable all alarms */
p_integrity_checker->icae = 0;
/* Enable and clear all interrupts */
p_integrity_checker->icie = 0xFF;
p_integrity_checker->icic = 0xFF;
}
The issue arises because the memory areas pointed to by value and temp_val are cacheable (e.g., located in the vm0 memory region, which is configured as cacheable).
As a result, even though the integrity checker writes the output data to the physical address of value or temp_val, the CPU cache is not updated, and this leads to stale data being read later in software, resulting in runtime errors.
Expected Behavior:
Ideally, the memory region used for integrity checker output should either be:
Non-cacheable, or
Explicitly synchronized (e.g., cache invalidated or cleaned) after the integrity checker operation.
Could you please confirm whether this is a known issue, and advise on the recommended way to handle integrity checker outputs with respect to cache settings?
Thank you.
JK Park