Last edited one month ago

How to analyze IAC & SERC errors

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 is 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.

Info white.png Information
For now, the RISUPs and RIMUs of the RIFSC and the RISAF configurations can be dumped.


3.1. RIFSC dump[edit source]

To dump the RIFSC configuration, simply execute cat /sys/kernel/debug/stm32_firewall/rifsc in the Linux kernel shell. Example:

root@stm32mp2:~# cat /sys/kernel/debug/stm32_firewall/rifsc  

=============================================
                 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        |
...

3.2. RISAF dump[edit source]

To dump a RISAF configuration, simply execute cat /sys/kernel/debug/stm32_firewall/<appropriate RISAF>. The description of all the memory regions of the RISAF and their RIF attributes should appear. Example for a RISAF4 (controlling DDR) layout:

root@stm32mp2:~# cat /sys/kernel/debug/stm32_firewall/risaf@420d0000 

------------------------------------------------------------------------------------------------------------------------------------------------
| Region ID || Region base addr || Region end addr || Enabled || Encrypted || N/SECURE || CID PRIV-only list || CID read list || CID write list |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 1  || 0x80000000       || 0x800fffff      || ENABLED || YES       || SEC      ||                    || CID2          || CID2           |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 2  || 0x80100000       || 0x808fffff      || ENABLED ||           || NSEC     || CID2               || CID0,1,2      || CID0,1,2       |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 3  || 0x80900000       || 0x809fffff      || ENABLED || YES       || SEC      || CID0,1,2           || CID2          || CID2           |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 4  || 0x80a00000       || 0x811fffff      || ENABLED ||           || NSEC     || CID2               || CID0,1,2      || CID0,1,2       |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 5  || 0x81200000       || 0x812fffff      || ENABLED ||           || NSEC     || CID0,1,2           || CID0,1,2      || CID0,1,2       |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 6  || 0x81300000       || 0x81fbffff      || ENABLED ||           || NSEC     || CID0,1,2           || CID0,1,2      || CID0,1,2       |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 7  || 0x81fc0000       || 0x81ffffff      || ENABLED || YES       || SEC      || CID0,1,2           || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 8  || 0x82000000       || 0x83ffffff      || ENABLED || YES       || SEC      || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 9  || 0x84000000       || 0xfa7fffff      || ENABLED ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 10 || 0xfa800000       || 0xfe7fffff      || ENABLED ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 11 || 0x80000000       || 0x80000fff      ||         ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 12 || 0x80000000       || 0x80000fff      ||         ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 13 || 0xfe800000       || 0xfeffffff      || ENABLED ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 14 || 0xff000000       || 0xffffffff      || ENABLED ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 15 || 0x100000000      || 0x17fffffff     || ENABLED ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------
| Region 16 || 0x80000000       || 0x80000000      ||         ||           || NSEC     || CID0,1             || CID0,1        || CID0,1         |
------------------------------------------------------------------------------------------------------------------------------------------------

4. IAC debug[edit source]

4.1. Peripheral IAC[edit source]

Upon receiving such a 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 //Only one IAC on ID: 156
 E/TC:0   stm32_iac_itr:192 IAC exception ID: 156

Here, the trace gives the ID of the peripheral 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 is block-based (RISAB) or page-based (RISAF), some 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 a nonsecure and unprivileged read access from the CID1.

Info white.png Information
The CID causing the IAC is identified by the IACID[2:0] field of the IAESRx register

For further analysis, refer to the wiki article STM32 MPU resources.

Memories protected by RISAL (a light-version of the RISAF) do 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 to ensure it has been done.
  • Check the clock tree configuration.
  • Some clocks may not be exposed to drivers because they have been filtered by the firewall framework of each component. It may be worth to check their associated RIF configuration.

6. More troubleshooting[edit source]

  • It is possible to have several IAC/SERC events printed at the same time. The dump shows all IAC/SERC pending events. A use-case could be a sequence where interrupts are masked and several illegal accesses are made during it.
  • Panicking upon SERC and IAC events are controlled by OP-TEE CFG_STM32_PANIC_ON_IAC_EVENT and CFG_STM32_PANIC_ON_SERC_EVENT configuration switches.