Skip to content

Commit

Permalink
esp32: mpi: add workaround for data corruption issue observed with ID…
Browse files Browse the repository at this point in the history
…F 5.x toolchain

This fix adds a workaround to disable compiler optimization flag "-ftree-loop-distribute-patterns"
for `mpi_to_mem_block` routine. It was observed that compiler with release configuration was falling
back to `memset` call from ROM library causing an issue in correctly zero initializing MPI peripheral
block.

Please see following linked issue for more discussion and context on this issue.

Closes #8710
Closes #9371
Closes #9256
Closes IDFGH-7102
Closes IDFGH-7842
Closes IDFGH-7714
Closes IDFCI-1452
Closes IDF-6029
  • Loading branch information
mahavirj committed Oct 21, 2022
1 parent 6c8f659 commit dc34d49
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
27 changes: 26 additions & 1 deletion components/mbedtls/port/esp32/bignum.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ void esp_mpi_interrupt_clear( void )
these additional words will be zeroed in the memory buffer.
*/
static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t hw_words)

/* Please see detailed note inside the function body below.
* Relevant: https://github.com/espressif/esp-idf/issues/8710 and IDF-6029
*/
static inline void __attribute__((optimize("-fno-tree-loop-distribute-patterns")))
mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t hw_words)
{
uint32_t *pbase = (uint32_t *)mem_base;
uint32_t copy_words = MIN(hw_words, mpi->MBEDTLS_PRIVATE(n));
Expand All @@ -81,6 +86,26 @@ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, s
for (uint32_t i = copy_words; i < hw_words; i++) {
pbase[i] = 0;
}

#if _INTERNAL_DEBUG_PURPOSE
/*
* With Xtensa GCC 11.2.0 (from ESP-IDF v5.x), it was observed that above zero initialization
* loop gets optimized to `memset` call from the ROM library. This was causing an issue that
* specific write (store) operation to the MPI peripheral block was getting lost erroneously.
* Following data re-verify loop could catch it during runtime.
*
* As a workaround, we are disabling loop distribute patterns for this function and hence
* compiler does not enforce usage of `memset` (or `memcpy`) calls for this routine. It
* appears that `-ftree-loop-distribute-patterns` was enabled with O2/Os starting from
* GCC-10.x. It is quite possible that there is some issue with DPORT write with sequence of
* store instructions as generated by `memset` call, but for now this should serve as good
* interim workaround without any impact on the performance.
*
* Please see IDF-6029 for more details.
*/

//for (uint32_t i = copy_words; i < hw_words; i++) { assert(pbase[i] == 0); }
#endif
}

/* Read mbedTLS MPI bignum back from hardware memory block.
Expand Down
7 changes: 7 additions & 0 deletions components/mbedtls/port/esp_bignum.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,13 @@ static int mpi_mult_mpi_failover_mod_mult( mbedtls_mpi *Z, const mbedtls_mpi *X,
esp_mpi_read_result_hw_op(Z, hw_words);

Z->MBEDTLS_PRIVATE(s) = X->MBEDTLS_PRIVATE(s) * Y->MBEDTLS_PRIVATE(s);
/*
* If this condition fails then most likely hardware peripheral
* has produced an incorrect result for MPI operation. This can
* happen if data fed to the peripheral register was incorrect.
* Relevant: https://github.com/espressif/esp-idf/issues/8710#issuecomment-1249178698
*/
assert(mpi_words(Z) == z_words);
cleanup:
esp_mpi_disable_hardware_hw_op();
return ret;
Expand Down

0 comments on commit dc34d49

Please sign in to comment.