Skip to content

Commit

Permalink
pw_cpu_exception_cortex_m: Fix cpu exception handler on armv8m
Browse files Browse the repository at this point in the history
- restore msplim and psplim in the exception entry
- mark the entry with PW_NO_PROLOGUE
- ensure the correct captured_state is checked in BeginBaseFaultTest

Tested with clang and gcc with and without -Oz

Fixes: b/323215726

Change-Id: I9e5c49eabcf361dd99702e5868c10fd8173b79aa
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/231372
Reviewed-by: Armando Montanez <[email protected]>
Presubmit-Verified: CQ Bot Account <[email protected]>
Lint: Lint 🤖 <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
Pigweed-Auto-Submit: Dave Roth <[email protected]>
  • Loading branch information
davexroth authored and CQ Bot Account committed Aug 22, 2024
1 parent 9175df7 commit 06e763c
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 11 deletions.
5 changes: 0 additions & 5 deletions pw_cpu_exception_cortex_m/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,6 @@ pw_cc_test(
"@platforms//cpu:armv6-m": ["exception_entry_test_armv6m.cc"],
"//conditions:default": ["exception_entry_test.cc"],
}),
# TODO: https://pwbug.dev/323215726 - Broken on Cortex-M33.
target_compatible_with = select({
"@platforms//cpu:armv8-m": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
deps = [
":config",
":cpu_exception",
Expand Down
15 changes: 13 additions & 2 deletions pw_cpu_exception_cortex_m/entry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#include "pw_preprocessor/compiler.h"

// TODO(pwbug/311): Deprecated naming.
PW_EXTERN_C PW_NO_PROLOGUE __attribute__((alias("pw_cpu_exception_Entry"))) void
PW_EXTERN_C PW_NO_PROLOGUE __attribute__((alias("pw_cpu_exception_Entry")))
__attribute__((nothrow)) void
pw_CpuExceptionEntry(void);

namespace pw::cpu_exception::cortex_m {
Expand Down Expand Up @@ -194,9 +195,13 @@ PW_USED void pw_PackageAndHandleCpuException(
// Captures faulting CPU state on the main stack (MSP), then calls the exception
// handlers.
// This function should be called immediately after an exception.
void pw_cpu_exception_Entry(void) {
PW_USED PW_NO_PROLOGUE void pw_cpu_exception_Entry() {
asm volatile(
// clang-format off

// Enable unified syntax for Thumb and Thumb2.
" .syntax unified \n"

// If PSP was in use at the time of exception, it's possible the CPU
// wasn't able to push CPU state. To be safe, this first captures scratch
// registers before moving forward.
Expand Down Expand Up @@ -271,7 +276,13 @@ void pw_cpu_exception_Entry(void) {
" mov r0, r4 \n"

// Restore special registers.
#if _PW_ARCH_ARM_V7M || _PW_ARCH_ARM_V7EM
" ldm r0!, {r1-r4} \n"
#elif _PW_ARCH_ARM_V8M_MAINLINE || _PW_ARCH_ARM_V8_1M_MAINLINE
" ldm r0!, {r1-r6} \n"
" msr msplim, r5 \n"
" msr psplim, r6 \n"
#endif // defined(PW_CPU_EXCEPTION_CORTEX_M_ARMV7M)
" mov lr, r1 \n"
" msr control, r4 \n"

Expand Down
2 changes: 1 addition & 1 deletion pw_cpu_exception_cortex_m/entry_armv6m.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ PW_USED void pw_PackageAndHandleCpuException(
// Captures faulting CPU state on the main stack (MSP), then calls the exception
// handlers.
// This function should be called immediately after an exception.
PW_USED void pw_cpu_exception_Entry() {
PW_USED PW_NO_PROLOGUE void pw_cpu_exception_Entry() {
asm volatile(
// clang-format off

Expand Down
8 changes: 5 additions & 3 deletions pw_cpu_exception_cortex_m/exception_entry_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ constexpr uint32_t kUsageFaultEnableMask = 0x1 << 18;
constexpr uint32_t kFpuEnableMask = (0xFu << 20);

// Memory mapped registers. (ARMv7-M Section B3.2.2, Table B3-4)
volatile uint32_t& cortex_m_vtor =
*reinterpret_cast<volatile uint32_t*>(0xE000ED08u);
volatile uint32_t& cortex_m_ccr =
*reinterpret_cast<volatile uint32_t*>(0xE000ED14u);
volatile uint32_t& cortex_m_cpacr =
Expand Down Expand Up @@ -137,7 +135,11 @@ void BeginBaseFaultTest() {
);

// Check that the stack align bit was not set.
EXPECT_EQ(captured_state.base.psr & kPsrExtraStackAlignBit, 0u);
// When testing nested exceptions, the nested exception is at index 0, with
// this first exception stored at index 1 as it's handled second.
EXPECT_EQ(
captured_states[exceptions_handled - 1].base.psr & kPsrExtraStackAlignBit,
0u);
}

// Populate the device's registers with testable values, then trigger exception.
Expand Down

0 comments on commit 06e763c

Please sign in to comment.