On Mon, 14 Sept 2026 at 20:25, Gilles Grimaud
<[email protected]> wrote:
>
> The Armv6-M Unprivileged/Privileged Extension is optional. Cortex-M0 does
> not implement it, while Cortex-M0+ may implement it. The RP2040 Cortex-M0+
> configuration provides the extension.
>
> Add an ARM feature bit and a cortex-m0plus CPU type that enables it. Permit
> privileged writes to CONTROL.nPRIV when either the Main Extension or the
> optional privilege extension is present.
>
> Update the microbit Cortex-M0 test to verify that writes to nPRIV are
> ignored.
>
> Signed-off-by: Gilles Grimaud <[email protected]>
> ---
> target/arm/cpu.h | 1 +
> target/arm/tcg/cpu-v7m.c | 11 ++++
> target/arm/tcg/m_helper.c | 4 +-
> tests/tcg/arm/system/meson.build | 6 ++
> tests/tcg/arm/system/test-armv6m-control.S | 66 ++++++++++++++++++++++
> 5 files changed, 87 insertions(+), 1 deletion(-)
> create mode 100644 tests/tcg/arm/system/test-armv6m-control.S
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index e3f931dba2..66606b3444 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2168,6 +2168,7 @@ enum arm_features {
> ARM_FEATURE_VBAR, /* has cp15 VBAR */
> ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
> ARM_FEATURE_M_MAIN, /* M profile Main Extension */
> + ARM_FEATURE_M_UNPRIV, /* M profile Unprivileged/Privileged Extension */
> ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
> /*
> * ARM_FEATURE_BACKCOMPAT_CNTFRQ makes the CPU default cntfrq be 62.5MHz
> diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
> index 48b31d5eac..ac99c93ec3 100644
> --- a/target/arm/tcg/cpu-v7m.c
> +++ b/target/arm/tcg/cpu-v7m.c
> @@ -76,6 +76,15 @@ static void cortex_m0_initfn(Object *obj)
> SET_IDREG(isar, ID_ISAR6, 0x00000000);
> }
>
> +static void cortex_m0plus_initfn(Object *obj)
> +{
> + ARMCPU *cpu = ARM_CPU(obj);
> +
> + cortex_m0_initfn(obj);
> + set_feature(&cpu->env, ARM_FEATURE_M_UNPRIV);
> + cpu->midr = 0x410cc601;
> +}
This patch should only add the feature; it shouldn't add the M0+
CPU type as well.
> diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
> index 33c9e7c55b..f8461a4d66 100644
> --- a/target/arm/tcg/m_helper.c
> +++ b/target/arm/tcg/m_helper.c
> @@ -2775,7 +2775,9 @@ 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 &&
> + (arm_feature(env, ARM_FEATURE_M_MAIN) ||
> + arm_feature(env, ARM_FEATURE_M_UNPRIV))) {
We should make ARM_FEATURE_M_MAIN imply ARM_FEATURE_M_UNPRIV
(in arm_cpu_propagate_feature_implications()) so here we only
need to test ARM_FEATURE_M_MAIN.
> env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
> env->v7m.control[env->v7m.secure] |= val &
> R_V7M_CONTROL_NPRIV_MASK;
> }
thanks
-- PMM