How to analyze IAC & SERC errors

Revision as of 15:16, 16 October 2023 by Registered User
Applicable for STM32MP25x lines

1. Article purpose[edit source]

This article aims to provide tips to analyze and debug:

  • IAC events
  • SERC events

Prerequisites:

2. What happened?[edit source]

Receiving an IAC interrupt is _always_ caused by an insufficient access right. It can be caused by a CID, secure level or/and privilege filtering.

Receiving an SERC interrupt is _either_ caused by:

  • Access to a hardware block under reset.
  • Access to a hardware block that is not clocked.

3. RIF configuration dump in Linux kernel[edit source]

Most of the RIF configuration is available in read for all worlds.
To facilitate its debugging: Debugfs entries in /sys/kernel/debug/stm32_firewall/ are available to dump the RIF configuration.
Note: For now, only the dump for the RISUPs and RIMUs of the RIFSC is available.

To dump the configuration RIFSC, simply execute cat /sys/kernel/debug/stm32_firewall/rifsc in the Linux Kernel shell. An output similar to this one with the values corresponding to the current RIF configuration should appear:

=============================================
                 RIFSC dump
=============================================

=============================================
                 RISUP dump
=============================================

| Peripheral name || Firewall ID || N/SECURE || N/PRIVILEGED || CID filtering || Semaphore mode || SCID ||   SEMWL |
| TIM1            || 0           || NSEC     || NPRIV        || disabled      || disabled       || 0    || 0x0     |
| TIM2            || 1           || NSEC     || NPRIV        || disabled      || disabled       || 0    || 0x0     |
| TIM3            || 2           || NSEC     || NPRIV        || disabled      || disabled       || 0    || 0x0     |
| TIM4            || 3           || NSEC     || NPRIV        || disabled      || disabled       || 0    || 0x0     |
| TIM5            || 4           || NSEC     || NPRIV        || disabled      || disabled       || 0    || 0x0     |
...

=============================================
                  RIMU dump
=============================================
| Master name || CIDSEL || MCID || N/SECURE || N/PRIVILEGED |
| ETR         || CIDSEL || 1    || NSEC     || NPRIV        |
| SDMMC1      ||        || 0    || NSEC     || NPRIV        |
| SDMMC2      ||        || 0    || NSEC     || NPRIV        |
...

4. IAC debug[edit source]

4.1. Peripheral IAC[edit source]

Upon receiving such signal when accessing a peripheral, the platform will panic and output a trace similar to this one:

 E/TC:0   stm32_iac_itr:188 IAC exceptions [159:128]: 0x10000000 //Corresponds to ID: 156
 E/TC:0   stm32_iac_itr:192 IAC exception ID: 156

Here, the trace gives the ID of the hardware block onto which the IAC occurred (ID: 156).
One should either: dump the RIFSC configuration in the Linux kernel shell or lookup in the RIFSC chapter (Index of RIF peripheral table) of the STM32MP2x STM32 MPU reference manuals to identify which hardware block it corresponds to.

4.2. Memory IAC[edit source]

When an IAC occurs on a memory, whether it's block-based(RISAB) or page-based(RISAF), different information is displayed (in hexadecimal):

 DUMPING DATA FOR risaf@420d0000
 E/TC:0   stm32_risaf_dump_erroneous_data:212 =====================================================
 E/TC:0   stm32_risaf_dump_erroneous_data:213 Status register (IAESR0): 0x1
 E/TC:0   stm32_risaf_dump_erroneous_data:221 -----------------------------------------------------
 E/TC:0   stm32_risaf_dump_erroneous_data:222 Faulty address (IADDR0): 0x82000000
 E/TC:0   stm32_risaf_dump_erroneous_data:230 =====================================================
 E/TC:0   Panic at core/arch/arm/plat-stm32mp2/main.c:196 <access_violation_action>


Here, the faulty address that was attempted to be accessed is dumped along with the RISAF_IAESRx register that allows to identify which CID, with which secure/privilege level tried to access in read/write mode this address.

0x1 means that the illegal access on 0x82000000 was made from the CID1, non-secure and unprivileged world.

RISAL protected memories is a light-version of the RISAF and does not benefit of such feature.

4.3. What to do?[edit source]

After identifying from which hardware block the IAC was generated, either:

  • The RIF configuration of the block is correct and it is the access on the block that is not.
  • The RIF configuration of the block is incorrect and should be modified to allow the access.

The RIF configuration is set by OP-TEE

5. SERC debug[edit source]

The SERC also generates a bus error. Therefore, a bus error and a SERC interrupt are generated at the same time.

E/TC:0   stm32_serc_itr:174 SERC exceptions [127:96]: 0x40000
E/TC:0   stm32_serc_itr:179 SERC exception ID: 114

The ID printed corresponds to the hardware block on which the access was refused. The ID can be found in the SERF resources mapping table of the SERC chapter of the STM32 MPU reference manuals. One can also dump the RIFSC configuration in the Linux kernel shell as they share the IDs.

5.1. What to do?[edit source]

After identifying from which hardware block the SERC was generated:

  • Check the sequence that enables the clock
  • Check the clock tree configuration

6. More troubleshooting[edit source]

  • It is possible to have several IAC/SERC events printed at the same time. The dump will show all IAC/SERC pending events. A use-case could be a sequence where interrupts are masked and several illegal accesses are made during it.