All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code
@ 2026-05-18 16:13 Torbjörn SVENSSON
  2026-05-18 16:13 ` [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu Torbjörn SVENSSON
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Torbjörn SVENSSON @ 2026-05-18 16:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Torbjörn SVENSSON

Testing an arm-none-eabi GCC toolchain using QEMU gives unpredictable
test results for some test cases. In the GCC testsuite function
check_effective_target_arm_pacbti_hw, the testsuite tries to identify
if the target supports PACBTI instructions. The test consists of:

        __attribute__ ((naked)) int
        main (void)
        {
          asm ("pac r12, lr, sp");
          asm ("mov r0, #0");
          asm ("autg r12, lr, sp");
          asm ("bx lr");
        }

Running the above code in QEMU will cause LR to get corrupted.
The reson for the corruption is that AUTG overlaps with the SMMLA
instruction, and SMMLA will write the result to Rn, that for 
`AUTG R12, LR, SP` happens to match `LR`.

The solution to the above problem is to define the following new
Cortex-M instructions in QEMU:

* AUT
* AUTG
* BXAUT
* PAC
* PACBTI
* PACG

This patch series only implements the pointer authentication code part
of PACBTI. The branch target identification part is not implemented.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
---
Torbjörn SVENSSON (3):
      target/arm/tcg: define cortex-m85 cpu
      target/arm/tcg: add PAC related instructions
      target/arm: implement v8.1-m PAC support

 target/arm/cpu-features.h  |   6 ++
 target/arm/internals.h     |   2 +
 target/arm/tcg/cpu-v7m.c   |  40 +++++++++++++
 target/arm/tcg/m_helper.c  |  17 ++++++
 target/arm/tcg/t32.decode  |  21 ++++++-
 target/arm/tcg/translate.c | 138 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 221 insertions(+), 3 deletions(-)
---
base-commit: ac6721b88df944ade0048822b2b74210f543d656
change-id: 20260518-pr-pacbti-366d7acbe1be

Best regards,
-- 
Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu
  2026-05-18 16:13 [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjörn SVENSSON
@ 2026-05-18 16:13 ` Torbjörn SVENSSON
  2026-05-27 13:21   ` Alex Bennée
  2026-05-28 10:22   ` Peter Maydell
  2026-05-18 16:14 ` [PATCH 2/3] target/arm/tcg: add PAC related instructions Torbjörn SVENSSON
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: Torbjörn SVENSSON @ 2026-05-18 16:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Torbjörn SVENSSON

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
---
 target/arm/tcg/cpu-v7m.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
index dc249ce1f1..5cfda232cd 100644
--- a/target/arm/tcg/cpu-v7m.c
+++ b/target/arm/tcg/cpu-v7m.c
@@ -237,6 +237,44 @@ static void cortex_m55_initfn(Object *obj)
     cpu->ctr = 0x8303c003;
 }
 
+static void cortex_m85_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    ARMISARegisters *isar = &cpu->isar;
+
+    set_feature(&cpu->env, ARM_FEATURE_V8);
+    set_feature(&cpu->env, ARM_FEATURE_V8_1M);
+    set_feature(&cpu->env, ARM_FEATURE_M);
+    set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
+    set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
+    cpu->midr = 0x411fd230; /* r1p0 */
+    cpu->revidr = 0;
+    cpu->pmsav7_dregion = 16;
+    cpu->sau_sregion = 8;
+    /* These are the MVFR* values for the FPU + full MVE configuration */
+    cpu->isar.mvfr0 = 0x10110221;
+    cpu->isar.mvfr1 = 0x12100211;
+    cpu->isar.mvfr2 = 0x00000040;
+    SET_IDREG(isar, ID_PFR0, 0x20000030);
+    SET_IDREG(isar, ID_PFR1, 0x00000230);
+    SET_IDREG(isar, ID_DFR0, 0x10200000);
+    SET_IDREG(isar, ID_AFR0, 0x00000000);
+    SET_IDREG(isar, ID_MMFR0, 0x00111040);
+    SET_IDREG(isar, ID_MMFR1, 0x00000000);
+    SET_IDREG(isar, ID_MMFR2, 0x01000000);
+    SET_IDREG(isar, ID_MMFR3, 0x00000011);
+    SET_IDREG(isar, ID_ISAR0, 0x01103110);
+    SET_IDREG(isar, ID_ISAR1, 0x02212000);
+    SET_IDREG(isar, ID_ISAR2, 0x20232232);
+    SET_IDREG(isar, ID_ISAR3, 0x01111131);
+    SET_IDREG(isar, ID_ISAR4, 0x01310132);
+    SET_IDREG(isar, ID_ISAR5, 0x00000000);
+    SET_IDREG(isar, ID_ISAR6, 0x00000000);
+    SET_IDREG(isar, CLIDR, 0x00000000); /* caches not implemented */
+    cpu->ctr = 0x8303c003;
+}
+
 static const TCGCPUOps arm_v7m_tcg_ops = {
     /* ARM processors have a weak memory model */
     .guest_default_memory_order = 0,
@@ -290,6 +328,8 @@ static const ARMCPUInfo arm_v7m_cpus[] = {
                              .class_init = arm_v7m_class_init },
     { .name = "cortex-m55",  .initfn = cortex_m55_initfn,
                              .class_init = arm_v7m_class_init },
+    { .name = "cortex-m85",  .initfn = cortex_m85_initfn,
+                             .class_init = arm_v7m_class_init },
 };
 
 static void arm_v7m_cpu_register_types(void)

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] target/arm/tcg: add PAC related instructions
  2026-05-18 16:13 [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjörn SVENSSON
  2026-05-18 16:13 ` [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu Torbjörn SVENSSON
@ 2026-05-18 16:14 ` Torbjörn SVENSSON
  2026-05-27 13:33   ` Alex Bennée
  2026-05-28 10:40   ` Peter Maydell
  2026-05-18 16:14 ` [PATCH 3/3] target/arm: implement v8.1-m PAC support Torbjörn SVENSSON
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: Torbjörn SVENSSON @ 2026-05-18 16:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Torbjörn SVENSSON

This commit adds the pointer authentication instructions from the Arm
v8.1-m PACBTI extension.
While the instructions are properly recognized, they are all NOPs.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
---
 target/arm/tcg/t32.decode  | 21 +++++++++++++---
 target/arm/tcg/translate.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/target/arm/tcg/t32.decode b/target/arm/tcg/t32.decode
index 49b8d0037e..a885eed101 100644
--- a/target/arm/tcg/t32.decode
+++ b/target/arm/tcg/t32.decode
@@ -263,6 +263,7 @@ BFCI             1111 0011 011 0 .... 0 ... .... ..0.....     @bfi
 @s0_rnadm        .... .... .... rn:4 ra:4 rd:4 .... rm:4      &s_rrrr s=0
 @s0_rn0dm        .... .... .... rn:4 .... rd:4 .... rm:4      &s_rrrr ra=0 s=0
 @rnadm           .... .... .... rn:4 ra:4 rd:4 .... rm:4      &rrrr
+@rna0m           .... .... .... rn:4 ra:4 .... .... rm:4      &rrrr rd=0
 @rn0dm           .... .... .... rn:4 .... rd:4 .... rm:4      &rrrr ra=0
 @rndm            .... .... .... rn:4 .... rd:4 .... rm:4      &rrr
 @rdm             .... .... .... .... .... rd:4 .... rm:4      &rr
@@ -319,9 +320,18 @@ SMLALDX          1111 1011 1100 .... .... .... 1101 ....      @rnadm
 SMLSLD           1111 1011 1101 .... .... .... 1100 ....      @rnadm
 SMLSLDX          1111 1011 1101 .... .... .... 1101 ....      @rnadm
 
-SMMLA            1111 1011 0101 .... .... .... 0000 ....      @rnadm
-SMMLAR           1111 1011 0101 .... .... .... 0001 ....      @rnadm
-SMMLS            1111 1011 0110 .... .... .... 0000 ....      @rnadm
+{
+  AUTG           1111 1011 0101 .... .... 1111 0000 ....      @rna0m
+  SMMLA          1111 1011 0101 .... .... .... 0000 ....      @rnadm
+}
+{
+  BXAUT          1111 1011 0101 .... .... 1111 0001 ....      @rna0m
+  SMMLAR         1111 1011 0101 .... .... .... 0001 ....      @rnadm
+}
+{
+  PACG           1111 1011 0110 .... 1111 .... 0000 ....      @rndm
+  SMMLS          1111 1011 0110 .... .... .... 0000 ....      @rnadm
+}
 SMMLSR           1111 1011 0110 .... .... .... 0001 ....      @rnadm
 
 SDIV             1111 1011 1001 .... 1111 .... 1111 ....      @rndm
@@ -375,6 +385,11 @@ CLZ              1111 1010 1011 ---- 1111 .... 1000 ....      @rdm
         # SEVL   1111 0011 1010 1111 1000 0000 0000 0101
 
         ESB      1111 0011 1010 1111 1000 0000 0001 0000
+
+        # v8.1-m PACBTI extention
+        AUT      1111 0011 1010 1111 1000 0000 0010 1101
+        PAC      1111 0011 1010 1111 1000 0000 0001 1101
+        PACBTI   1111 0011 1010 1111 1000 0000 0000 1101
       ]
 
       # The canonical nop ends in 0000 0000, but the whole rest
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index c744b16345..ae1351ef03 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -5012,6 +5012,68 @@ static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
     return op_smmla(s, a, true, true);
 }
 
+static bool trans_PAC(DisasContext *s, arg_empty *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+
+    /* Handle as if PACBTI is disabled. */
+    return true;
+}
+
+static bool trans_PACBTI(DisasContext *s, arg_empty *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+
+    /* todo: reset EPSR.B to 0 */
+
+    /* Handle as if PACBTI is disabled. */
+    return true;
+}
+
+static bool trans_PACG(DisasContext *s, arg_rrr *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+
+    /* Handle as if PACBTI is disabled. */
+    return true;
+}
+
+static bool trans_BXAUT(DisasContext *s, arg_rrrr *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+
+    /* Handle as if PACBTI is disabled. */
+    return true;
+}
+
+static bool trans_AUT(DisasContext *s, arg_empty *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+
+    /* Handle as if PACBTI is disabled. */
+    return true;
+}
+
+static bool trans_AUTG(DisasContext *s, arg_rrrr *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+
+    /* Handle as if PACBTI is disabled. */
+    return true;
+}
+
 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
 {
     TCGv_i32 t1, t2;

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] target/arm: implement v8.1-m PAC support
  2026-05-18 16:13 [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjörn SVENSSON
  2026-05-18 16:13 ` [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu Torbjörn SVENSSON
  2026-05-18 16:14 ` [PATCH 2/3] target/arm/tcg: add PAC related instructions Torbjörn SVENSSON
@ 2026-05-18 16:14 ` Torbjörn SVENSSON
  2026-05-27 13:55   ` Alex Bennée
  2026-05-28 10:43   ` Peter Maydell
  2026-05-27  7:36 ` [PING] [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjorn SVENSSON
  2026-05-28 10:50 ` Peter Maydell
  4 siblings, 2 replies; 14+ messages in thread
From: Torbjörn SVENSSON @ 2026-05-18 16:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Torbjörn SVENSSON

The algorithm used for hashing is a simple XOR between the pointer
and the modifier using the "implementation defined" scheme.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
---
 target/arm/cpu-features.h  |  6 +++
 target/arm/internals.h     |  2 +
 target/arm/tcg/cpu-v7m.c   |  2 +-
 target/arm/tcg/m_helper.c  | 17 ++++++++
 target/arm/tcg/translate.c | 98 ++++++++++++++++++++++++++++++++++++++++------
 5 files changed, 113 insertions(+), 12 deletions(-)

diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 4e44245a8b..60bd7a0765 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -114,6 +114,7 @@ FIELD(ID_ISAR5, AES, 4, 4)
 FIELD(ID_ISAR5, SHA1, 8, 4)
 FIELD(ID_ISAR5, SHA2, 12, 4)
 FIELD(ID_ISAR5, CRC32, 16, 4)
+FIELD(ID_ISAR5, PACBTI, 20, 4)
 FIELD(ID_ISAR5, RDM, 24, 4)
 FIELD(ID_ISAR5, VCMA, 28, 4)
 
@@ -583,6 +584,11 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
     return FIELD_EX32_IDREG(id, ID_PFR1, SECURITY) >= 3;
 }
 
+static inline bool isar_feature_aa32_m_pacbti(const ARMISARegisters *id)
+{
+    return FIELD_EX32_IDREG(id, ID_ISAR5, PACBTI) != 0;
+}
+
 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
 {
     /* Sadly this is encoded differently for A-profile and M-profile */
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 00830b1724..cbb0a1d8fc 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -90,6 +90,8 @@ FIELD(V7M_CONTROL, NPRIV, 0, 1)
 FIELD(V7M_CONTROL, SPSEL, 1, 1)
 FIELD(V7M_CONTROL, FPCA, 2, 1)
 FIELD(V7M_CONTROL, SFPA, 3, 1)
+FIELD(V7M_CONTROL, PAC_EN, 6, 1)
+FIELD(V7M_CONTROL, UPAC_EN, 7, 1)
 
 /* Bit definitions for v7M exception return payload */
 FIELD(V7M_EXCRET, ES, 0, 1)
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
index 5cfda232cd..3beb2b23fa 100644
--- a/target/arm/tcg/cpu-v7m.c
+++ b/target/arm/tcg/cpu-v7m.c
@@ -269,7 +269,7 @@ static void cortex_m85_initfn(Object *obj)
     SET_IDREG(isar, ID_ISAR2, 0x20232232);
     SET_IDREG(isar, ID_ISAR3, 0x01111131);
     SET_IDREG(isar, ID_ISAR4, 0x01310132);
-    SET_IDREG(isar, ID_ISAR5, 0x00000000);
+    SET_IDREG(isar, ID_ISAR5, 0x00200000); /* PACBTI=implementation defined */
     SET_IDREG(isar, ID_ISAR6, 0x00000000);
     SET_IDREG(isar, CLIDR, 0x00000000); /* caches not implemented */
     cpu->ctr = 0x8303c003;
diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
index f2059ed8b0..1160fe8d87 100644
--- a/target/arm/tcg/m_helper.c
+++ b/target/arm/tcg/m_helper.c
@@ -2658,6 +2658,15 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
                 env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
                 env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
             }
+
+            /* Only update PAC_EN / UPAC_EN if PACBTI is implemented. */
+            if (cpu_isar_feature(aa32_m_pacbti, env_archcpu(env))) {
+                uint32_t enable_mask =
+                    R_V7M_CONTROL_PAC_EN_MASK | R_V7M_CONTROL_UPAC_EN_MASK;
+                env->v7m.control[M_REG_NS] &= ~enable_mask;
+                env->v7m.control[M_REG_NS] |= val & enable_mask;
+            }
+
             return;
         case 0x98: /* SP_NS */
         {
@@ -2784,6 +2793,14 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
                 env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
             }
         }
+
+        /* Only update PAC_EN / UPAC_EN if PACBTI is implemented. */
+        if (cpu_isar_feature(aa32_m_pacbti, env_archcpu(env))) {
+            uint32_t enable_mask =
+                R_V7M_CONTROL_PAC_EN_MASK | R_V7M_CONTROL_UPAC_EN_MASK;
+            env->v7m.control[env->v7m.secure] &= ~enable_mask;
+            env->v7m.control[env->v7m.secure] |= val & enable_mask;
+        }
         break;
     default:
     bad_reg:
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index ae1351ef03..e13119b33b 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -5012,26 +5012,80 @@ static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
     return op_smmla(s, a, true, true);
 }
 
+static void arm_gen_test_pac_enabled(DisasContext *s, TCGLabel *label)
+{
+    int bank = s->v8m_secure ? M_REG_S : M_REG_NS;
+    int mask = IS_USER(s)
+        ?  R_V7M_CONTROL_UPAC_EN_MASK
+        : R_V7M_CONTROL_PAC_EN_MASK;
+    TCGv_i32 temp = load_cpu_field(v7m.control[bank]);
+    tcg_gen_brcondi_i32(TCG_COND_TSTEQ, temp, mask, label);
+}
+
+static TCGv_i32 op_create_pac_hash(DisasContext *s, int rn, int rm)
+{
+    TCGv_i32 res = tcg_temp_new_i32();
+    TCGv_i64 ext_ptr = tcg_temp_new_i64();
+    TCGv_i64 modifier = tcg_temp_new_i64();
+    TCGv_i64 temp = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(ext_ptr, load_reg(s, rn));
+    tcg_gen_extu_i32_i64(modifier, load_reg(s, rm));
+
+    /*
+     * This a very simple implementation that just xor the two
+     * inputs. The goal is not to replicate any of the predefined
+     * hashing functions, but use a simple check.
+     */
+    tcg_gen_xor_i64(temp, ext_ptr, modifier);
+
+    /* Return the lower word */
+    tcg_gen_extrl_i64_i32(res, temp);
+    return res;
+}
+
+static bool op_pacg(DisasContext *s, arg_rrr *a)
+{
+    TCGv_i32 temp;
+    TCGLabel *done = gen_new_label();
+
+    arm_gen_test_pac_enabled(s, done);
+
+    temp = op_create_pac_hash(s, a->rn, a->rm);
+    store_reg(s, a->rd, temp);
+
+    gen_set_label(done);
+    return true;
+}
+
 static bool trans_PAC(DisasContext *s, arg_empty *a)
 {
+    arg_rrr arg;
+
     if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
         return false;
     }
 
-    /* Handle as if PACBTI is disabled. */
-    return true;
+    arg.rd = 0xc; /* R12 */
+    arg.rn = 0xe; /* LR */
+    arg.rm = 0xd; /* SP */
+    return op_pacg(s, &arg);
 }
 
 static bool trans_PACBTI(DisasContext *s, arg_empty *a)
 {
+    arg_rrr arg;
+
     if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
         return false;
     }
 
     /* todo: reset EPSR.B to 0 */
 
-    /* Handle as if PACBTI is disabled. */
-    return true;
+    arg.rd = 0xc; /* R12 */
+    arg.rn = 0xe; /* LR */
+    arg.rm = 0xd; /* SP */
+    return op_pacg(s, &arg);
 }
 
 static bool trans_PACG(DisasContext *s, arg_rrr *a)
@@ -5040,7 +5094,26 @@ static bool trans_PACG(DisasContext *s, arg_rrr *a)
         return false;
     }
 
-    /* Handle as if PACBTI is disabled. */
+    return op_pacg(s, a);
+}
+
+static bool op_autg(DisasContext *s, arg_rrrr *a, int set_pc_from_reg)
+{
+    TCGv_i32 expected_pac_hash, actual_pac_hash;
+    TCGLabel *done = gen_new_label();
+    TCGLabel *fail = delay_exception(s, EXCP_INVSTATE, syn_uncategorized());
+
+    arm_gen_test_pac_enabled(s, done);
+
+    expected_pac_hash = load_reg(s, a->ra);
+    actual_pac_hash = op_create_pac_hash(s, a->rn, a->rm);
+    tcg_gen_brcond_i32(TCG_COND_NE, expected_pac_hash, actual_pac_hash, fail);
+
+    gen_set_label(done);
+    if (set_pc_from_reg >= 0) {
+        gen_bx_excret(s, load_reg(s, set_pc_from_reg));
+    }
+
     return true;
 }
 
@@ -5050,18 +5123,22 @@ static bool trans_BXAUT(DisasContext *s, arg_rrrr *a)
         return false;
     }
 
-    /* Handle as if PACBTI is disabled. */
-    return true;
+    return op_autg(s, a, a->rn);
 }
 
 static bool trans_AUT(DisasContext *s, arg_empty *a)
 {
+    arg_rrrr arg;
+
     if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
         return false;
     }
 
-    /* Handle as if PACBTI is disabled. */
-    return true;
+    arg.rd = 0; /* unused */
+    arg.ra = 0xc; /* R12 */
+    arg.rn = 0xe; /* LR */
+    arg.rm = 0xd; /* SP */
+    return op_autg(s, &arg, -1);
 }
 
 static bool trans_AUTG(DisasContext *s, arg_rrrr *a)
@@ -5070,8 +5147,7 @@ static bool trans_AUTG(DisasContext *s, arg_rrrr *a)
         return false;
     }
 
-    /* Handle as if PACBTI is disabled. */
-    return true;
+    return op_autg(s, a, -1);
 }
 
 static bool op_div(DisasContext *s, arg_rrr *a, bool u)

-- 
2.43.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PING] [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code
  2026-05-18 16:13 [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjörn SVENSSON
                   ` (2 preceding siblings ...)
  2026-05-18 16:14 ` [PATCH 3/3] target/arm: implement v8.1-m PAC support Torbjörn SVENSSON
@ 2026-05-27  7:36 ` Torbjorn SVENSSON
  2026-05-27 12:58   ` Alex Bennée
  2026-05-28 10:50 ` Peter Maydell
  4 siblings, 1 reply; 14+ messages in thread
From: Torbjorn SVENSSON @ 2026-05-27  7:36 UTC (permalink / raw)
  To: qemu-devel, qemu-arm; +Cc: Peter Maydell, Richard Henderson

Gentle ping! :)

There is apparently also a ticket for this work (that I did not see before I sent the patches): https://linaro.atlassian.net/browse/QEMU-444


On 2026-05-18 18:13, Torbjörn SVENSSON wrote:
> Testing an arm-none-eabi GCC toolchain using QEMU gives unpredictable
> test results for some test cases. In the GCC testsuite function
> check_effective_target_arm_pacbti_hw, the testsuite tries to identify
> if the target supports PACBTI instructions. The test consists of:
> 
>          __attribute__ ((naked)) int
>          main (void)
>          {
>            asm ("pac r12, lr, sp");
>            asm ("mov r0, #0");
>            asm ("autg r12, lr, sp");
>            asm ("bx lr");
>          }
> 
> Running the above code in QEMU will cause LR to get corrupted.
> The reson for the corruption is that AUTG overlaps with the SMMLA
> instruction, and SMMLA will write the result to Rn, that for
> `AUTG R12, LR, SP` happens to match `LR`.

The above statement is not entirely true.
SMMLA is writing the result to Rd and that happens to match PC, not Rn and LR.
Sorry for the confusion this might have caused.

Kind regards,
Torbjörn

> The solution to the above problem is to define the following new
> Cortex-M instructions in QEMU:
> 
> * AUT
> * AUTG
> * BXAUT
> * PAC
> * PACBTI
> * PACG
> 
> This patch series only implements the pointer authentication code part
> of PACBTI. The branch target identification part is not implemented.
> 
> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
> ---
> Torbjörn SVENSSON (3):
>        target/arm/tcg: define cortex-m85 cpu
>        target/arm/tcg: add PAC related instructions
>        target/arm: implement v8.1-m PAC support
> 
>   target/arm/cpu-features.h  |   6 ++
>   target/arm/internals.h     |   2 +
>   target/arm/tcg/cpu-v7m.c   |  40 +++++++++++++
>   target/arm/tcg/m_helper.c  |  17 ++++++
>   target/arm/tcg/t32.decode  |  21 ++++++-
>   target/arm/tcg/translate.c | 138 +++++++++++++++++++++++++++++++++++++++++++++
>   6 files changed, 221 insertions(+), 3 deletions(-)
> ---
> base-commit: ac6721b88df944ade0048822b2b74210f543d656
> change-id: 20260518-pr-pacbti-366d7acbe1be
> 
> Best regards,



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PING] [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code
  2026-05-27  7:36 ` [PING] [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjorn SVENSSON
@ 2026-05-27 12:58   ` Alex Bennée
  0 siblings, 0 replies; 14+ messages in thread
From: Alex Bennée @ 2026-05-27 12:58 UTC (permalink / raw)
  To: Torbjorn SVENSSON; +Cc: qemu-devel, qemu-arm, Peter Maydell, Richard Henderson

Torbjorn SVENSSON <torbjorn.svensson@foss.st.com> writes:

> Gentle ping! :)
>
> There is apparently also a ticket for this work (that I did not see before I sent the patches): https://linaro.atlassian.net/browse/QEMU-444
>

The Linaro tickets are public (because we work directly upstream)
although the existence of a ticket should not imply that we plan to work
on it. We create tickets for most of the Arm CPU features so we can
track dependencies, what is left to do and when others have patches that
need review.

Our actual planned roadmap can be seen here: https://linaro.atlassian.net/wiki/spaces/QEMU/overview

>
> On 2026-05-18 18:13, Torbjörn SVENSSON wrote:
>> Testing an arm-none-eabi GCC toolchain using QEMU gives unpredictable
>> test results for some test cases. In the GCC testsuite function
>> check_effective_target_arm_pacbti_hw, the testsuite tries to identify
>> if the target supports PACBTI instructions. The test consists of:
>>          __attribute__ ((naked)) int
>>          main (void)
>>          {
>>            asm ("pac r12, lr, sp");
>>            asm ("mov r0, #0");
>>            asm ("autg r12, lr, sp");
>>            asm ("bx lr");
>>          }
>> Running the above code in QEMU will cause LR to get corrupted.
>> The reson for the corruption is that AUTG overlaps with the SMMLA
>> instruction, and SMMLA will write the result to Rn, that for
>> `AUTG R12, LR, SP` happens to match `LR`.
>
> The above statement is not entirely true.
> SMMLA is writing the result to Rd and that happens to match PC, not Rn and LR.
> Sorry for the confusion this might have caused.
>
> Kind regards,
> Torbjörn
>
>> The solution to the above problem is to define the following new
>> Cortex-M instructions in QEMU:
>> * AUT
>> * AUTG
>> * BXAUT
>> * PAC
>> * PACBTI
>> * PACG
>> This patch series only implements the pointer authentication code
>> part
>> of PACBTI. The branch target identification part is not implemented.
>> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
>> ---
>> Torbjörn SVENSSON (3):
>>        target/arm/tcg: define cortex-m85 cpu
>>        target/arm/tcg: add PAC related instructions
>>        target/arm: implement v8.1-m PAC support
>>   target/arm/cpu-features.h  |   6 ++
>>   target/arm/internals.h     |   2 +
>>   target/arm/tcg/cpu-v7m.c   |  40 +++++++++++++
>>   target/arm/tcg/m_helper.c  |  17 ++++++
>>   target/arm/tcg/t32.decode  |  21 ++++++-
>>   target/arm/tcg/translate.c | 138 +++++++++++++++++++++++++++++++++++++++++++++
>>   6 files changed, 221 insertions(+), 3 deletions(-)
>> ---
>> base-commit: ac6721b88df944ade0048822b2b74210f543d656
>> change-id: 20260518-pr-pacbti-366d7acbe1be
>> Best regards,

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu
  2026-05-18 16:13 ` [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu Torbjörn SVENSSON
@ 2026-05-27 13:21   ` Alex Bennée
  2026-05-28 10:22   ` Peter Maydell
  1 sibling, 0 replies; 14+ messages in thread
From: Alex Bennée @ 2026-05-27 13:21 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, Peter Maydell, qemu-arm

Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> writes:

Can you mention the TRM in the commit:

  https://developer.arm.com/documentation/101924/0100/

> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
> ---
>  target/arm/tcg/cpu-v7m.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
>
> diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
> index dc249ce1f1..5cfda232cd 100644
> --- a/target/arm/tcg/cpu-v7m.c
> +++ b/target/arm/tcg/cpu-v7m.c
> @@ -237,6 +237,44 @@ static void cortex_m55_initfn(Object *obj)
>      cpu->ctr = 0x8303c003;
>  }
>  
> +static void cortex_m85_initfn(Object *obj)
> +{
> +    ARMCPU *cpu = ARM_CPU(obj);
> +    ARMISARegisters *isar = &cpu->isar;
> +
> +    set_feature(&cpu->env, ARM_FEATURE_V8);
> +    set_feature(&cpu->env, ARM_FEATURE_V8_1M);
> +    set_feature(&cpu->env, ARM_FEATURE_M);
> +    set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
> +    set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
> +    set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
> +    cpu->midr = 0x411fd230; /* r1p0 */
> +    cpu->revidr = 0;
> +    cpu->pmsav7_dregion = 16;
> +    cpu->sau_sregion = 8;
> +    /* These are the MVFR* values for the FPU + full MVE configuration */
> +    cpu->isar.mvfr0 = 0x10110221;
> +    cpu->isar.mvfr1 = 0x12100211;
> +    cpu->isar.mvfr2 = 0x00000040;
> +    SET_IDREG(isar, ID_PFR0, 0x20000030);
> +    SET_IDREG(isar, ID_PFR1, 0x00000230);
> +    SET_IDREG(isar, ID_DFR0, 0x10200000);
> +    SET_IDREG(isar, ID_AFR0, 0x00000000);
> +    SET_IDREG(isar, ID_MMFR0, 0x00111040);
> +    SET_IDREG(isar, ID_MMFR1, 0x00000000);
> +    SET_IDREG(isar, ID_MMFR2, 0x01000000);
> +    SET_IDREG(isar, ID_MMFR3, 0x00000011);
> +    SET_IDREG(isar, ID_ISAR0, 0x01103110);
> +    SET_IDREG(isar, ID_ISAR1, 0x02212000);
> +    SET_IDREG(isar, ID_ISAR2, 0x20232232);
> +    SET_IDREG(isar, ID_ISAR3, 0x01111131);
> +    SET_IDREG(isar, ID_ISAR4, 0x01310132);
> +    SET_IDREG(isar, ID_ISAR5, 0x00000000);

The TRM specifies this as 0x00100000 and you set this to in 3/3 to:

  SET_IDREG(isar, ID_ISAR5, 0x00200000); /* PACBTI=implementation defined */

which isn't one of the available config options. We'd rather not present
a CPU that can't exist.

With that said for A-profile we do offer the control knob of
pauth-impdef (which is the default for -cpu max). We could add similar
logic to aarch64_cpu_pauth_finalize to cpu32 to allow the user to
actively tune their emulation speed.

> +    SET_IDREG(isar, ID_ISAR6, 0x00000000);
> +    SET_IDREG(isar, CLIDR, 0x00000000); /* caches not implemented */
> +    cpu->ctr = 0x8303c003;
> +}
> +
>  static const TCGCPUOps arm_v7m_tcg_ops = {
>      /* ARM processors have a weak memory model */
>      .guest_default_memory_order = 0,
> @@ -290,6 +328,8 @@ static const ARMCPUInfo arm_v7m_cpus[] = {
>                               .class_init = arm_v7m_class_init },
>      { .name = "cortex-m55",  .initfn = cortex_m55_initfn,
>                               .class_init = arm_v7m_class_init },
> +    { .name = "cortex-m85",  .initfn = cortex_m85_initfn,
> +                             .class_init = arm_v7m_class_init },
>  };
>  
>  static void arm_v7m_cpu_register_types(void)

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] target/arm/tcg: add PAC related instructions
  2026-05-18 16:14 ` [PATCH 2/3] target/arm/tcg: add PAC related instructions Torbjörn SVENSSON
@ 2026-05-27 13:33   ` Alex Bennée
  2026-05-28 10:40   ` Peter Maydell
  1 sibling, 0 replies; 14+ messages in thread
From: Alex Bennée @ 2026-05-27 13:33 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, Peter Maydell, qemu-arm

Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> writes:

> This commit adds the pointer authentication instructions from the Arm
> v8.1-m PACBTI extension.
> While the instructions are properly recognized, they are all NOPs.
>
> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
> ---
>  target/arm/tcg/t32.decode  | 21 +++++++++++++---
>  target/arm/tcg/translate.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 80 insertions(+), 3 deletions(-)
>
> diff --git a/target/arm/tcg/t32.decode b/target/arm/tcg/t32.decode
> index 49b8d0037e..a885eed101 100644
> --- a/target/arm/tcg/t32.decode
> +++ b/target/arm/tcg/t32.decode
> @@ -263,6 +263,7 @@ BFCI             1111 0011 011 0 .... 0 ... .... ..0.....     @bfi
>  @s0_rnadm        .... .... .... rn:4 ra:4 rd:4 .... rm:4      &s_rrrr s=0
>  @s0_rn0dm        .... .... .... rn:4 .... rd:4 .... rm:4      &s_rrrr ra=0 s=0
>  @rnadm           .... .... .... rn:4 ra:4 rd:4 .... rm:4      &rrrr
> +@rna0m           .... .... .... rn:4 ra:4 .... .... rm:4      &rrrr rd=0
>  @rn0dm           .... .... .... rn:4 .... rd:4 .... rm:4      &rrrr ra=0
>  @rndm            .... .... .... rn:4 .... rd:4 .... rm:4      &rrr
>  @rdm             .... .... .... .... .... rd:4 .... rm:4      &rr
> @@ -319,9 +320,18 @@ SMLALDX          1111 1011 1100 .... .... .... 1101 ....      @rnadm
>  SMLSLD           1111 1011 1101 .... .... .... 1100 ....      @rnadm
>  SMLSLDX          1111 1011 1101 .... .... .... 1101 ....      @rnadm
>  
> -SMMLA            1111 1011 0101 .... .... .... 0000 ....      @rnadm
> -SMMLAR           1111 1011 0101 .... .... .... 0001 ....      @rnadm
> -SMMLS            1111 1011 0110 .... .... .... 0000 ....      @rnadm
> +{
> +  AUTG           1111 1011 0101 .... .... 1111 0000 ....      @rna0m
> +  SMMLA          1111 1011 0101 .... .... .... 0000 ....      @rnadm
> +}
> +{
> +  BXAUT          1111 1011 0101 .... .... 1111 0001 ....      @rna0m
> +  SMMLAR         1111 1011 0101 .... .... .... 0001 ....      @rnadm
> +}
> +{
> +  PACG           1111 1011 0110 .... 1111 .... 0000 ....      @rndm
> +  SMMLS          1111 1011 0110 .... .... .... 0000 ....      @rnadm
> +}
>  SMMLSR           1111 1011 0110 .... .... .... 0001 ....      @rnadm
>  
>  SDIV             1111 1011 1001 .... 1111 .... 1111 ....      @rndm
> @@ -375,6 +385,11 @@ CLZ              1111 1010 1011 ---- 1111 .... 1000 ....      @rdm
>          # SEVL   1111 0011 1010 1111 1000 0000 0000 0101
>  
>          ESB      1111 0011 1010 1111 1000 0000 0001 0000
> +
> +        # v8.1-m PACBTI extention
> +        AUT      1111 0011 1010 1111 1000 0000 0010 1101
> +        PAC      1111 0011 1010 1111 1000 0000 0001 1101
> +        PACBTI   1111 0011 1010 1111 1000 0000 0000 1101
>        ]
>  
>        # The canonical nop ends in 0000 0000, but the whole rest
> diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
> index c744b16345..ae1351ef03 100644
> --- a/target/arm/tcg/translate.c
> +++ b/target/arm/tcg/translate.c
> @@ -5012,6 +5012,68 @@ static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
>      return op_smmla(s, a, true, true);
>  }
>  
> +static bool trans_PAC(DisasContext *s, arg_empty *a)
> +{
> +    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
> +        return false;
> +    }

These are the wrong feature tests. I would bring the
isar_feature_aa32_m_pacbti from 3/3 into this patch and invert the logic
in the same way the a64 does:

    if (dc_isar_feature(aa32_m_pacbti, s)) {
        /* treat as NOP for now */
        return true;
    }
    return false;

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] target/arm: implement v8.1-m PAC support
  2026-05-18 16:14 ` [PATCH 3/3] target/arm: implement v8.1-m PAC support Torbjörn SVENSSON
@ 2026-05-27 13:55   ` Alex Bennée
  2026-05-27 16:38     ` Peter Maydell
  2026-05-28 10:43   ` Peter Maydell
  1 sibling, 1 reply; 14+ messages in thread
From: Alex Bennée @ 2026-05-27 13:55 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, Peter Maydell, qemu-arm

Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> writes:

> The algorithm used for hashing is a simple XOR between the pointer
> and the modifier using the "implementation defined" scheme.
>
> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
> ---
>  target/arm/cpu-features.h  |  6 +++
>  target/arm/internals.h     |  2 +
>  target/arm/tcg/cpu-v7m.c   |  2 +-
>  target/arm/tcg/m_helper.c  | 17 ++++++++
>  target/arm/tcg/translate.c | 98 ++++++++++++++++++++++++++++++++++++++++------
>  5 files changed, 113 insertions(+), 12 deletions(-)
>
> diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
> index 4e44245a8b..60bd7a0765 100644
> --- a/target/arm/cpu-features.h
> +++ b/target/arm/cpu-features.h
> @@ -114,6 +114,7 @@ FIELD(ID_ISAR5, AES, 4, 4)
>  FIELD(ID_ISAR5, SHA1, 8, 4)
>  FIELD(ID_ISAR5, SHA2, 12, 4)
>  FIELD(ID_ISAR5, CRC32, 16, 4)
> +FIELD(ID_ISAR5, PACBTI, 20, 4)
>  FIELD(ID_ISAR5, RDM, 24, 4)
>  FIELD(ID_ISAR5, VCMA, 28, 4)
>  
> @@ -583,6 +584,11 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
>      return FIELD_EX32_IDREG(id, ID_PFR1, SECURITY) >= 3;
>  }
>  
> +static inline bool isar_feature_aa32_m_pacbti(const ARMISARegisters *id)
> +{
> +    return FIELD_EX32_IDREG(id, ID_ISAR5, PACBTI) != 0;
> +}

See isar_feature_aa64_pauth and friends.

> +
>  static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
>  {
>      /* Sadly this is encoded differently for A-profile and M-profile */
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 00830b1724..cbb0a1d8fc 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -90,6 +90,8 @@ FIELD(V7M_CONTROL, NPRIV, 0, 1)
>  FIELD(V7M_CONTROL, SPSEL, 1, 1)
>  FIELD(V7M_CONTROL, FPCA, 2, 1)
>  FIELD(V7M_CONTROL, SFPA, 3, 1)
> +FIELD(V7M_CONTROL, PAC_EN, 6, 1)
> +FIELD(V7M_CONTROL, UPAC_EN, 7, 1)

Hmm my copy of the v7m Arm ARM doesn't include these bits...

But I can see it online:

  https://developer.arm.com/documentation/109576/0100/Pointer-Authentication-Code/Enabling-pointer-authentication?lang=en

>  
>  /* Bit definitions for v7M exception return payload */
>  FIELD(V7M_EXCRET, ES, 0, 1)
> diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
> index 5cfda232cd..3beb2b23fa 100644
> --- a/target/arm/tcg/cpu-v7m.c
> +++ b/target/arm/tcg/cpu-v7m.c
> @@ -269,7 +269,7 @@ static void cortex_m85_initfn(Object *obj)
>      SET_IDREG(isar, ID_ISAR2, 0x20232232);
>      SET_IDREG(isar, ID_ISAR3, 0x01111131);
>      SET_IDREG(isar, ID_ISAR4, 0x01310132);
> -    SET_IDREG(isar, ID_ISAR5, 0x00000000);
> +    SET_IDREG(isar, ID_ISAR5, 0x00200000); /* PACBTI=implementation defined */
>      SET_IDREG(isar, ID_ISAR6, 0x00000000);
>      SET_IDREG(isar, CLIDR, 0x00000000); /* caches not implemented */
>      cpu->ctr = 0x8303c003;
> diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
> index f2059ed8b0..1160fe8d87 100644
> --- a/target/arm/tcg/m_helper.c
> +++ b/target/arm/tcg/m_helper.c
> @@ -2658,6 +2658,15 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
>                  env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
>                  env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
>              }
> +
> +            /* Only update PAC_EN / UPAC_EN if PACBTI is implemented. */
> +            if (cpu_isar_feature(aa32_m_pacbti, env_archcpu(env))) {
> +                uint32_t enable_mask =
> +                    R_V7M_CONTROL_PAC_EN_MASK | R_V7M_CONTROL_UPAC_EN_MASK;
> +                env->v7m.control[M_REG_NS] &= ~enable_mask;
> +                env->v7m.control[M_REG_NS] |= val & enable_mask;

Hmm I was going to suggest looking at FIELD_DP32 but it looks like this
is following the existing style.

> +            }
> +
>              return;
>          case 0x98: /* SP_NS */
>          {
> @@ -2784,6 +2793,14 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
>                  env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
>              }
>          }
> +
> +        /* Only update PAC_EN / UPAC_EN if PACBTI is implemented. */
> +        if (cpu_isar_feature(aa32_m_pacbti, env_archcpu(env))) {
> +            uint32_t enable_mask =
> +                R_V7M_CONTROL_PAC_EN_MASK | R_V7M_CONTROL_UPAC_EN_MASK;
> +            env->v7m.control[env->v7m.secure] &= ~enable_mask;
> +            env->v7m.control[env->v7m.secure] |= val & enable_mask;
> +        }
>          break;
>      default:
>      bad_reg:
> diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
> index ae1351ef03..e13119b33b 100644
> --- a/target/arm/tcg/translate.c
> +++ b/target/arm/tcg/translate.c
> @@ -5012,26 +5012,80 @@ static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
>      return op_smmla(s, a, true, true);
>  }
>  
> +static void arm_gen_test_pac_enabled(DisasContext *s, TCGLabel *label)
> +{
> +    int bank = s->v8m_secure ? M_REG_S : M_REG_NS;
> +    int mask = IS_USER(s)
> +        ?  R_V7M_CONTROL_UPAC_EN_MASK
> +        : R_V7M_CONTROL_PAC_EN_MASK;
> +    TCGv_i32 temp = load_cpu_field(v7m.control[bank]);
> +    tcg_gen_brcondi_i32(TCG_COND_TSTEQ, temp, mask, label);
> +}
> +
> +static TCGv_i32 op_create_pac_hash(DisasContext *s, int rn, int rm)
> +{
> +    TCGv_i32 res = tcg_temp_new_i32();
> +    TCGv_i64 ext_ptr = tcg_temp_new_i64();
> +    TCGv_i64 modifier = tcg_temp_new_i64();
> +    TCGv_i64 temp = tcg_temp_new_i64();
> +
> +    tcg_gen_extu_i32_i64(ext_ptr, load_reg(s, rn));
> +    tcg_gen_extu_i32_i64(modifier, load_reg(s, rm));
> +
> +    /*
> +     * This a very simple implementation that just xor the two
> +     * inputs. The goal is not to replicate any of the predefined
> +     * hashing functions, but use a simple check.
> +     */
> +    tcg_gen_xor_i64(temp, ext_ptr, modifier);
> +
> +    /* Return the lower word */
> +    tcg_gen_extrl_i64_i32(res, temp);
> +    return res;

Is it really needed here? Could you not create an equivalent of
pauth_computepac for m-profile and use the architected helpers or
fall-back to the xxhash impl?

Is does mean a helper call but it would keep more in common with the
A-profile code.

> +}
> +
> +static bool op_pacg(DisasContext *s, arg_rrr *a)
> +{
> +    TCGv_i32 temp;
> +    TCGLabel *done = gen_new_label();
> +
> +    arm_gen_test_pac_enabled(s, done);
> +
> +    temp = op_create_pac_hash(s, a->rn, a->rm);
> +    store_reg(s, a->rd, temp);
> +
> +    gen_set_label(done);
> +    return true;
> +}
> +
>  static bool trans_PAC(DisasContext *s, arg_empty *a)
>  {
> +    arg_rrr arg;
> +
>      if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
>          return false;
>      }
>  
> -    /* Handle as if PACBTI is disabled. */
> -    return true;
> +    arg.rd = 0xc; /* R12 */
> +    arg.rn = 0xe; /* LR */
> +    arg.rm = 0xd; /* SP */
> +    return op_pacg(s, &arg);
>  }
>  
>  static bool trans_PACBTI(DisasContext *s, arg_empty *a)
>  {
> +    arg_rrr arg;
> +
>      if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
>          return false;
>      }
>  
>      /* todo: reset EPSR.B to 0 */
>  
> -    /* Handle as if PACBTI is disabled. */
> -    return true;
> +    arg.rd = 0xc; /* R12 */
> +    arg.rn = 0xe; /* LR */
> +    arg.rm = 0xd; /* SP */
> +    return op_pacg(s, &arg);
>  }
>  
>  static bool trans_PACG(DisasContext *s, arg_rrr *a)
> @@ -5040,7 +5094,26 @@ static bool trans_PACG(DisasContext *s, arg_rrr *a)
>          return false;
>      }
>  
> -    /* Handle as if PACBTI is disabled. */
> +    return op_pacg(s, a);
> +}
> +
> +static bool op_autg(DisasContext *s, arg_rrrr *a, int set_pc_from_reg)
> +{
> +    TCGv_i32 expected_pac_hash, actual_pac_hash;
> +    TCGLabel *done = gen_new_label();
> +    TCGLabel *fail = delay_exception(s, EXCP_INVSTATE, syn_uncategorized());
> +
> +    arm_gen_test_pac_enabled(s, done);
> +
> +    expected_pac_hash = load_reg(s, a->ra);
> +    actual_pac_hash = op_create_pac_hash(s, a->rn, a->rm);
> +    tcg_gen_brcond_i32(TCG_COND_NE, expected_pac_hash, actual_pac_hash, fail);
> +
> +    gen_set_label(done);
> +    if (set_pc_from_reg >= 0) {
> +        gen_bx_excret(s, load_reg(s, set_pc_from_reg));
> +    }
> +
>      return true;
>  }
>  
> @@ -5050,18 +5123,22 @@ static bool trans_BXAUT(DisasContext *s, arg_rrrr *a)
>          return false;
>      }
>  
> -    /* Handle as if PACBTI is disabled. */
> -    return true;
> +    return op_autg(s, a, a->rn);
>  }
>  
>  static bool trans_AUT(DisasContext *s, arg_empty *a)
>  {
> +    arg_rrrr arg;
> +
>      if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
>          return false;
>      }
>  
> -    /* Handle as if PACBTI is disabled. */
> -    return true;
> +    arg.rd = 0; /* unused */
> +    arg.ra = 0xc; /* R12 */
> +    arg.rn = 0xe; /* LR */
> +    arg.rm = 0xd; /* SP */
> +    return op_autg(s, &arg, -1);
>  }
>  
>  static bool trans_AUTG(DisasContext *s, arg_rrrr *a)
> @@ -5070,8 +5147,7 @@ static bool trans_AUTG(DisasContext *s, arg_rrrr *a)
>          return false;
>      }
>  
> -    /* Handle as if PACBTI is disabled. */
> -    return true;
> +    return op_autg(s, a, -1);
>  }
>  
>  static bool op_div(DisasContext *s, arg_rrr *a, bool u)

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] target/arm: implement v8.1-m PAC support
  2026-05-27 13:55   ` Alex Bennée
@ 2026-05-27 16:38     ` Peter Maydell
  0 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-05-27 16:38 UTC (permalink / raw)
  To: Alex Bennée; +Cc: Torbjörn SVENSSON, qemu-devel, qemu-arm

On Wed, 27 May 2026 at 14:55, Alex Bennée <alex.bennee@linaro.org> wrote:
>
> Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> writes:
>
> > The algorithm used for hashing is a simple XOR between the pointer
> > and the modifier using the "implementation defined" scheme.
> >
> > Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>

> > @@ -90,6 +90,8 @@ FIELD(V7M_CONTROL, NPRIV, 0, 1)
> >  FIELD(V7M_CONTROL, SPSEL, 1, 1)
> >  FIELD(V7M_CONTROL, FPCA, 2, 1)
> >  FIELD(V7M_CONTROL, SFPA, 3, 1)
> > +FIELD(V7M_CONTROL, PAC_EN, 6, 1)
> > +FIELD(V7M_CONTROL, UPAC_EN, 7, 1)
>
> Hmm my copy of the v7m Arm ARM doesn't include these bits...

If you're looking at the v7M Arm ARM that's the wrong one.
You want the v8M Arm ARM; most recent rev is DDI0553 B.z.
https://developer.arm.com/documentation/ddi0553/latest/

-- PMM


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu
  2026-05-18 16:13 ` [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu Torbjörn SVENSSON
  2026-05-27 13:21   ` Alex Bennée
@ 2026-05-28 10:22   ` Peter Maydell
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-05-28 10:22 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, qemu-arm

On Mon, 18 May 2026 at 17:16, Torbjörn SVENSSON
<torbjorn.svensson@foss.st.com> wrote:
>
> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
> ---
>  target/arm/tcg/cpu-v7m.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)

This patch should go last in the series -- first add
all the new features the CPU needs, and only then add
the new CPU, so there isn't a window where the user can
select the new CPU type but it isn't completely implemented yet.

> diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
> index dc249ce1f1..5cfda232cd 100644
> --- a/target/arm/tcg/cpu-v7m.c
> +++ b/target/arm/tcg/cpu-v7m.c
> @@ -237,6 +237,44 @@ static void cortex_m55_initfn(Object *obj)
>      cpu->ctr = 0x8303c003;
>  }
>
> +static void cortex_m85_initfn(Object *obj)
> +{
> +    ARMCPU *cpu = ARM_CPU(obj);
> +    ARMISARegisters *isar = &cpu->isar;
> +
> +    set_feature(&cpu->env, ARM_FEATURE_V8);
> +    set_feature(&cpu->env, ARM_FEATURE_V8_1M);
> +    set_feature(&cpu->env, ARM_FEATURE_M);
> +    set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
> +    set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
> +    set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
> +    cpu->midr = 0x411fd230; /* r1p0 */

The most recent release is r1p1, so we might as well model that:
0x411fd231.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] target/arm/tcg: add PAC related instructions
  2026-05-18 16:14 ` [PATCH 2/3] target/arm/tcg: add PAC related instructions Torbjörn SVENSSON
  2026-05-27 13:33   ` Alex Bennée
@ 2026-05-28 10:40   ` Peter Maydell
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-05-28 10:40 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, qemu-arm

On Mon, 18 May 2026 at 17:16, Torbjörn SVENSSON
<torbjorn.svensson@foss.st.com> wrote:
>
> This commit adds the pointer authentication instructions from the Arm
> v8.1-m PACBTI extension.
> While the instructions are properly recognized, they are all NOPs.
>
> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>

I think it's worth mentioning in the commit message that we previously
decoded these as SMMLA, and that changing what we do is OK because
for v7A and v8A these SMMLA etc encodings say that Rd == 0b1111 is
UNPREDICTABLE.

> ---
>  target/arm/tcg/t32.decode  | 21 +++++++++++++---
>  target/arm/tcg/translate.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 80 insertions(+), 3 deletions(-)
>
> diff --git a/target/arm/tcg/t32.decode b/target/arm/tcg/t32.decode
> index 49b8d0037e..a885eed101 100644
> --- a/target/arm/tcg/t32.decode
> +++ b/target/arm/tcg/t32.decode
> @@ -263,6 +263,7 @@ BFCI             1111 0011 011 0 .... 0 ... .... ..0.....     @bfi
>  @s0_rnadm        .... .... .... rn:4 ra:4 rd:4 .... rm:4      &s_rrrr s=0
>  @s0_rn0dm        .... .... .... rn:4 .... rd:4 .... rm:4      &s_rrrr ra=0 s=0
>  @rnadm           .... .... .... rn:4 ra:4 rd:4 .... rm:4      &rrrr
> +@rna0m           .... .... .... rn:4 ra:4 .... .... rm:4      &rrrr rd=0
>  @rn0dm           .... .... .... rn:4 .... rd:4 .... rm:4      &rrrr ra=0
>  @rndm            .... .... .... rn:4 .... rd:4 .... rm:4      &rrr
>  @rdm             .... .... .... .... .... rd:4 .... rm:4      &rr
> @@ -319,9 +320,18 @@ SMLALDX          1111 1011 1100 .... .... .... 1101 ....      @rnadm
>  SMLSLD           1111 1011 1101 .... .... .... 1100 ....      @rnadm
>  SMLSLDX          1111 1011 1101 .... .... .... 1101 ....      @rnadm
>
> -SMMLA            1111 1011 0101 .... .... .... 0000 ....      @rnadm
> -SMMLAR           1111 1011 0101 .... .... .... 0001 ....      @rnadm
> -SMMLS            1111 1011 0110 .... .... .... 0000 ....      @rnadm
> +{
> +  AUTG           1111 1011 0101 .... .... 1111 0000 ....      @rna0m
> +  SMMLA          1111 1011 0101 .... .... .... 0000 ....      @rnadm
> +}
> +{
> +  BXAUT          1111 1011 0101 .... .... 1111 0001 ....      @rna0m
> +  SMMLAR         1111 1011 0101 .... .... .... 0001 ....      @rnadm
> +}
> +{
> +  PACG           1111 1011 0110 .... 1111 .... 0000 ....      @rndm
> +  SMMLS          1111 1011 0110 .... .... .... 0000 ....      @rnadm
> +}
>  SMMLSR           1111 1011 0110 .... .... .... 0001 ....      @rnadm
>
>  SDIV             1111 1011 1001 .... 1111 .... 1111 ....      @rndm
> @@ -375,6 +385,11 @@ CLZ              1111 1010 1011 ---- 1111 .... 1000 ....      @rdm
>          # SEVL   1111 0011 1010 1111 1000 0000 0000 0101
>
>          ESB      1111 0011 1010 1111 1000 0000 0001 0000
> +
> +        # v8.1-m PACBTI extention
> +        AUT      1111 0011 1010 1111 1000 0000 0010 1101
> +        PAC      1111 0011 1010 1111 1000 0000 0001 1101
> +        PACBTI   1111 0011 1010 1111 1000 0000 0000 1101
>        ]
>
>        # The canonical nop ends in 0000 0000, but the whole rest
> diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
> index c744b16345..ae1351ef03 100644
> --- a/target/arm/tcg/translate.c
> +++ b/target/arm/tcg/translate.c
> @@ -5012,6 +5012,68 @@ static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
>      return op_smmla(s, a, true, true);
>  }
>
> +static bool trans_PAC(DisasContext *s, arg_empty *a)
> +{
> +    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
> +        return false;
> +    }
> +
> +    /* Handle as if PACBTI is disabled. */
> +    return true;
> +}

I think the patchset would be clearer if we implemented
the insns (in whatever combinations make sense) in the same
patches as we add their decode, rather than adding decode
only in one patch and then implementation later.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] target/arm: implement v8.1-m PAC support
  2026-05-18 16:14 ` [PATCH 3/3] target/arm: implement v8.1-m PAC support Torbjörn SVENSSON
  2026-05-27 13:55   ` Alex Bennée
@ 2026-05-28 10:43   ` Peter Maydell
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-05-28 10:43 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, qemu-arm

On Mon, 18 May 2026 at 17:16, Torbjörn SVENSSON
<torbjorn.svensson@foss.st.com> wrote:
>
> The algorithm used for hashing is a simple XOR between the pointer
> and the modifier using the "implementation defined" scheme.
>
> Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
> ---
>  target/arm/cpu-features.h  |  6 +++
>  target/arm/internals.h     |  2 +
>  target/arm/tcg/cpu-v7m.c   |  2 +-
>  target/arm/tcg/m_helper.c  | 17 ++++++++
>  target/arm/tcg/translate.c | 98 ++++++++++++++++++++++++++++++++++++++++------
>  5 files changed, 113 insertions(+), 12 deletions(-)
>

>  static bool trans_PAC(DisasContext *s, arg_empty *a)
>  {
> +    arg_rrr arg;
> +
>      if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
>          return false;
>      }
>
> -    /* Handle as if PACBTI is disabled. */
> -    return true;
> +    arg.rd = 0xc; /* R12 */
> +    arg.rn = 0xe; /* LR */
> +    arg.rm = 0xd; /* SP */

Generally it's better to do this kind of thing in the decode
file rather than the trans function, so that this function
get s passed an arg_rrr with the right values filled in
rather than having to synthesize them.

> +    return op_pacg(s, &arg);
>  }

thanks
-- PMM


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code
  2026-05-18 16:13 [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjörn SVENSSON
                   ` (3 preceding siblings ...)
  2026-05-27  7:36 ` [PING] [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjorn SVENSSON
@ 2026-05-28 10:50 ` Peter Maydell
  4 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2026-05-28 10:50 UTC (permalink / raw)
  To: Torbjörn SVENSSON; +Cc: qemu-devel, qemu-arm

On Mon, 18 May 2026 at 17:16, Torbjörn SVENSSON
<torbjorn.svensson@foss.st.com> wrote:
>
> Testing an arm-none-eabi GCC toolchain using QEMU gives unpredictable
> test results for some test cases. In the GCC testsuite function
> check_effective_target_arm_pacbti_hw, the testsuite tries to identify
> if the target supports PACBTI instructions. The test consists of:
>
>         __attribute__ ((naked)) int
>         main (void)
>         {
>           asm ("pac r12, lr, sp");
>           asm ("mov r0, #0");
>           asm ("autg r12, lr, sp");
>           asm ("bx lr");
>         }
>
> Running the above code in QEMU will cause LR to get corrupted.
> The reson for the corruption is that AUTG overlaps with the SMMLA
> instruction, and SMMLA will write the result to Rn, that for
> `AUTG R12, LR, SP` happens to match `LR`.

If the test case is expecting to be able to run on any M-profile
CPU, this is a bug in the test case. The AUTG instruction is
specified as being UNPREDICTABLE if the DSP extension is implemented
and the PACBTI extension is not (and to UNDEF if neither extension
is implemented).

(We could consider making the QEMU behaviour for these
UNPREDICTABLE cases in SMMLA etc be "UNDEF" rather than
"write to the PC/LR"; we choose to handle this kind of
UNPREDICTABLE decode that way for other insns already.)

> The solution to the above problem is to define the following new
> Cortex-M instructions in QEMU:
>
> * AUT
> * AUTG
> * BXAUT
> * PAC
> * PACBTI
> * PACG
>
> This patch series only implements the pointer authentication code part
> of PACBTI. The branch target identification part is not implemented.

I think that overall we need the full PACBTI implemented -- we
can't advertise it in the CPU ID registers but only implement
part of it, or only implement it for user-mode and not for
system mode.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-05-28 10:51 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18 16:13 [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjörn SVENSSON
2026-05-18 16:13 ` [PATCH 1/3] target/arm/tcg: define cortex-m85 cpu Torbjörn SVENSSON
2026-05-27 13:21   ` Alex Bennée
2026-05-28 10:22   ` Peter Maydell
2026-05-18 16:14 ` [PATCH 2/3] target/arm/tcg: add PAC related instructions Torbjörn SVENSSON
2026-05-27 13:33   ` Alex Bennée
2026-05-28 10:40   ` Peter Maydell
2026-05-18 16:14 ` [PATCH 3/3] target/arm: implement v8.1-m PAC support Torbjörn SVENSSON
2026-05-27 13:55   ` Alex Bennée
2026-05-27 16:38     ` Peter Maydell
2026-05-28 10:43   ` Peter Maydell
2026-05-27  7:36 ` [PING] [PATCH 0/3] target/arm: add support for Cortex-M pointer authentication code Torbjorn SVENSSON
2026-05-27 12:58   ` Alex Bennée
2026-05-28 10:50 ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.