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