On Sun, 6 Sept 2026 at 20:44, Gilles Grimaud
<[email protected]> wrote:
>
> Armv6-M implements CONTROL.nPRIV even though it does not implement the Main
> Extension. The M-profile MSR helper currently gates writes to nPRIV on
> ARM_FEATURE_M_MAIN, preventing Cortex-M0 CPUs from entering unprivileged
> Thread mode.
>
> Allow privileged code to write nPRIV on every M-profile CPU. The translator
> already ends the translation block and rebuilds the execution flags after
> an M-profile MSR, so this does not require explicit TLB maintenance.
>
> Add a check-tcg test using the generic microbit machine. It verifies entry
> into unprivileged Thread mode, that unprivileged code cannot clear nPRIV,
> and that an exception handler can restore privileged Thread mode.
>
> Signed-off-by: Gilles Grimaud <[email protected]>
> ---
>  target/arm/tcg/m_helper.c                  |  2 +-
>  tests/tcg/arm/system/meson.build           |  6 ++
>  tests/tcg/arm/system/test-armv6m-control.S | 85 ++++++++++++++++++++++
>  3 files changed, 92 insertions(+), 1 deletion(-)
>  create mode 100644 tests/tcg/arm/system/test-armv6m-control.S
>
> diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
> index 33c9e7c55b..0cd51c52ba 100644
> --- a/target/arm/tcg/m_helper.c
> +++ b/target/arm/tcg/m_helper.c
> @@ -2775,7 +2775,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t 
> maskreg, uint32_t val)
>                             !arm_v7m_is_handler_mode(env))) {
>              write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 
> 0);
>          }
> -        if (cur_el > 0 && arm_feature(env, ARM_FEATURE_M_MAIN)) {
> +        if (cur_el > 0) {
>              env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
>              env->v7m.control[env->v7m.secure] |= val & 
> R_V7M_CONTROL_NPRIV_MASK;
>          }

For v6M, whether you can write to CONTROL.nPRIV depends on whether the
CPU implements the "Unprivileged/Privileged Extension". In v8M, if
the Main Extension is not present then this is IMPDEF.

In particular, the Cortex-M0 TRM says it doesn't have that
extension, and that's the one v6M CPU we currently model.
On Cortex-M0+ it is a configurable option.

We don't model any v8M CPUs without the Main extension, so we
don't need to adjust anything there. (As it happens, I think
the Cortex-M23 is the only v8M Baseline CPU, and it chooses to
implement allowing nPRIV to be written.)

I think we probably need to model this with a new ARM_FEATURE_ bit,
so we can make Cortex-M0 and Cortex-M0+ behave differently.

thanks
-- PMM

Reply via email to