diff options
author | Patryk Duda <pdk@semihalf.com> | 2021-05-27 15:04:18 +0200 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-10 09:18:37 +0000 |
commit | a2ffd0f59694e1fa57144fd22f0b32dbb9368440 (patch) | |
tree | 956cfb57716ff295536f878b946136d6bb70af6c /core/cortex-m | |
parent | fa451fa44d7f36c0073c795c9969d8e7f03fd1f3 (diff) | |
download | chrome-ec-a2ffd0f59694e1fa57144fd22f0b32dbb9368440.tar.gz |
stm32/system: Disable caches before reboot
Affected boards (only STM32H7):
- nocturne_fp (dartmonkey)
- nucleo-h743zi
This fixes problem with jumping to RW when reboot to RO was requested.
Log from reproduction on dartmonkey (only relevant parts):
--- UART initialized after reboot ---
[Image: RO, dartmonkey_v2.0.8961+9a30ce07ee]
[Reset cause: reset-pin power-on soft ap-off]
...
[1.045743 Jumping to image RW]
*** We are in RW. Jump data are initialized and contains correct
*** set of reset flags. Reset flags from backup RAM are cleared.
reset flags from chip: unknown
reset flags from jump data: reset-pin power-on soft sysjump ap-off
[1.056198 UART initialized after sysjump]
[Image: RW, dartmonkey_v2.0.8961+9a30ce07ee]
[Reset cause: reset-pin power-on soft sysjump ap-off]
...
>
> reboot ro
reboot ro
Rebooting!
*** Now we are in RO. RW saved reset cause in backup RAM (with
*** stay-in-ro). Please note that RO also finds jump data and
*** report that was sysjump!
reset flags from chip: reset-pin power-on soft ap-off stay-in-ro
reset flags from jump data: reset-pin power-on soft sysjump ap-off
[1.056198 UART initialized after sysjump]
[Image: RO, dartmonkey_v2.0.8961+9a30ce07ee]
[Reset cause: reset-pin power-on soft sysjump ap-off]
When RO is doing sysjump to RW, jump data structure is created in
jump_to_image() function. The structure contains information about
reset flags. When RW finds jump data in system_common_pre_init() magic
field of the structure is set to zero to prevent detecting sysjump
accidentally. Nevertheless, when reboot to RO is requested, RO is able
to find the structure. As a result, correct reset flags from backup RAM
are overwritten by incorrect reset flags from jump data.
This happens because we are not flushing D-cache before reboot.
All changes in RW which lives in cache (not saved in RAM) will be lost
after reboot because cache is always disabled (even if it was
previously enabled and we didn't turned it off). To enable cache we need
to invalidate it first (see cpu_enable_caches()).
Issue reproduces also with debugger connected, except situation when
watchpoint is set on jump data magic field.
BUG=b:170432597 b:188934337
BRANCH=none
TEST=Compile dartmonkey firmware and run it on eg. icetower.
In RW, issue 'reboot ro'. Make sure that jump to RO is not
performed.
TEST=Run flash_write_protect hardware unit test on icetower board
using `./test/run_device_tests.py --board dartmonkey \
--tests flash_write_protect`
Make sure that after reboot to RO, 'stay-in-ro' reset cause is
printed
Signed-off-by: Patryk Duda <pdk@semihalf.com>
Change-Id: If56153a1a3ac7ae05700eac9ca60e398cf35f182
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2922145
Reviewed-by: Craig Hesling <hesling@chromium.org>
Diffstat (limited to 'core/cortex-m')
-rw-r--r-- | core/cortex-m/cpu.c | 6 | ||||
-rw-r--r-- | core/cortex-m/cpu.h | 2 |
2 files changed, 5 insertions, 3 deletions
diff --git a/core/cortex-m/cpu.c b/core/cortex-m/cpu.c index 96ac96a016..7c31892c18 100644 --- a/core/cortex-m/cpu.c +++ b/core/cortex-m/cpu.c @@ -50,16 +50,16 @@ void cpu_enable_caches(void) } } -static void cpu_sysjump_cache(void) +void cpu_disable_caches(void) { /* * Disable the I-cache and the D-cache - * The I-cache will be invalidated after the sysjump if needed + * The I-cache will be invalidated after the reboot/sysjump if needed * (e.g after a flash update). */ cpu_clean_invalidate_dcache(); CPU_NVIC_CCR &= ~(CPU_NVIC_CCR_ICACHE | CPU_NVIC_CCR_DCACHE); asm volatile("dsb; isb"); } -DECLARE_HOOK(HOOK_SYSJUMP, cpu_sysjump_cache, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_SYSJUMP, cpu_disable_caches, HOOK_PRIO_LAST); #endif /* CONFIG_ARMV7M_CACHE */ diff --git a/core/cortex-m/cpu.h b/core/cortex-m/cpu.h index 5f7dd02801..0b03302bfc 100644 --- a/core/cortex-m/cpu.h +++ b/core/cortex-m/cpu.h @@ -74,6 +74,8 @@ enum { void cpu_init(void); /* Enable the CPU I-cache and D-cache if they are not already enabled */ void cpu_enable_caches(void); +/* Disable the CPU I-cache and D-cache */ +void cpu_disable_caches(void); /* Invalidate the D-cache */ void cpu_invalidate_dcache(void); /* Clean and Invalidate the D-cache to the Point of Coherency */ |