Hi Andre,

Thanks for the review!
Please see my questions below.

On 2024-06-10 12:37, Andre Vieira (lists) wrote:
Hi Torbjorn,

Thanks for this, I have some comments below.

On 07/06/2024 09:56, Torbjörn SVENSSON wrote:
Properly handle zero and sign extension for Armv8-M.baseline as
Cortex-M23 can have the security extension active.
Currently, there is a internal compiler error on Cortex-M23 for the
epilog processing of sign extension.

This patch addresses the following CVE-2024-0151 for Armv8-M.baseline.

gcc/ChangeLog:

    PR target/115253
    * config/arm/arm.cc (cmse_nonsecure_call_inline_register_clear):
    Sign extend for Thumb1.
    (thumb1_expand_prologue): Add zero/sign extend.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svens...@foss.st.com>
Co-authored-by: Yvan ROUX <yvan.r...@foss.st.com>
---
  gcc/config/arm/arm.cc | 68 ++++++++++++++++++++++++++++++++++++++-----
  1 file changed, 60 insertions(+), 8 deletions(-)

diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index ea0c963a4d6..d1bb173c135 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -19220,17 +19220,23 @@ cmse_nonsecure_call_inline_register_clear (void)
            || TREE_CODE (ret_type) == BOOLEAN_TYPE)
            && known_lt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 4))
          {
-          machine_mode ret_mode = TYPE_MODE (ret_type);
+          rtx ret_mode = gen_rtx_REG (TYPE_MODE (ret_type), R0_REGNUM);
+          rtx si_mode = gen_rtx_REG (SImode, R0_REGNUM);

I'd rename ret_mode and si_mode to ret_reg and si_reg, so its clear they are registers and not actually mode types.

Okay, will be changed before push and/or a V3 of the patches.

            rtx extend;
            if (TYPE_UNSIGNED (ret_type))
-        extend = gen_rtx_ZERO_EXTEND (SImode,
-                          gen_rtx_REG (ret_mode, R0_REGNUM));
+        extend = gen_rtx_SET (si_mode, gen_rtx_ZERO_EXTEND (SImode,
+                                    ret_mode));
+          else if (TARGET_THUMB1)
+        {
+          if (known_lt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 2))
+            extend = gen_thumb1_extendqisi2 (si_mode, ret_mode);
+          else
+            extend = gen_thumb1_extendhisi2 (si_mode, ret_mode);
+        }
            else
-        extend = gen_rtx_SIGN_EXTEND (SImode,
-                          gen_rtx_REG (ret_mode, R0_REGNUM));
-          emit_insn_after (gen_rtx_SET (gen_rtx_REG (SImode, R0_REGNUM),
-                         extend), insn);
-
+        extend = gen_rtx_SET (si_mode, gen_rtx_SIGN_EXTEND (SImode,
+                                    ret_mode));
+          emit_insn_after (extend, insn);
          }

Using gen_rtx_SIGN_EXTEND should work for both, the reason it doesn't is because of some weird code in thumb1_extendhisi2, which I'm actually gonna look at removing, but I don't think we should block this fix as we'd want to backport it ASAP.

But for clearness we should re-order this code so it's clear we only need it for that specific case.
Can you maybe do:
if (TYPE_UNSIGNED ..)
{
}
else
{
   /*  Signed-extension is a special case because of thumb1_extendhisi2.  */
    if (TARGET_THUMB1
        && known_gt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 2))
      {
         //call the gen_thumb1_extendhisi2
      }
     else
      {
         // use gen_RTX_SIGN_EXTEND
      }
}

So, you talk about gen_thumb1_extendhisi2, but there is also gen_thumb1_extendqisi2. Will it actually be cleaner if the block is indented one level? The comment can be added in the "if (TARGET_THUMB1)" block regardless to indicate that gen_rtx_SIGN_EXTEND can't be used.

@@ -27250,6 +27256,52 @@ thumb1_expand_prologue (void)
    live_regs_mask = offsets->saved_regs_mask;
    lr_needs_saving = live_regs_mask & (1 << LR_REGNUM);
+  /* The AAPCS requires the callee to widen integral types narrower
+     than 32 bits to the full width of the register; but when handling
+     calls to non-secure space, we cannot trust the callee to have
+     correctly done so.  So forcibly re-widen the result here.  */
+  if (IS_CMSE_ENTRY (func_type))
+    {
+      function_args_iterator args_iter;
+      CUMULATIVE_ARGS args_so_far_v;
+      cumulative_args_t args_so_far;
+      bool first_param = true;
+      tree arg_type;
+      tree fndecl = current_function_decl;
+      tree fntype = TREE_TYPE (fndecl);
+      arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl);
+      args_so_far = pack_cumulative_args (&args_so_far_v);
+      FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
+    {
+      rtx arg_rtx;
+
+      if (VOID_TYPE_P (arg_type))
+        break;
+
+      function_arg_info arg (arg_type, /*named=*/true);
+      if (!first_param)
+        /* We should advance after processing the argument and pass
+           the argument we're advancing past.  */
+        arm_function_arg_advance (args_so_far, arg);
+      first_param = false;
+      arg_rtx = arm_function_arg (args_so_far, arg);
+      gcc_assert (REG_P (arg_rtx));
+      if ((TREE_CODE (arg_type) == INTEGER_TYPE
+          || TREE_CODE (arg_type) == ENUMERAL_TYPE
+          || TREE_CODE (arg_type) == BOOLEAN_TYPE)
+          && known_lt (GET_MODE_SIZE (GET_MODE (arg_rtx)), 4))
+        {
+          rtx res_reg = gen_rtx_REG (SImode, REGNO (arg_rtx));
+          if (TYPE_UNSIGNED (arg_type))
+        emit_set_insn (res_reg, gen_rtx_ZERO_EXTEND (SImode, arg_rtx));
+          else if (known_lt (GET_MODE_SIZE (GET_MODE (arg_rtx)), 2))
+        emit_insn (gen_thumb1_extendqisi2 (res_reg, arg_rtx));
+          else
+        emit_insn (gen_thumb1_extendhisi2 (res_reg, arg_rtx));
For consistency I'd probably do the same as above here:

if TYPE_UNSIGNED
else
   {
     special-case thumb1_extendhisi2
   }
+        }
+    }
+    }
+
    /* Extract a mask of the ones we can give to the Thumb's push instruction.  */
    l_mask = live_regs_mask & 0x40ff;
    /* Then count how many other high registers will need to be pushed.  */

The rest LGTM, but I am not a maintainer You'll need an OK from Richard E.

In the meantime I'll test a patch to simplify thumb1_extendhisi2.

Whit the patch you have in mind, will it be possible to call gen_rtx_SIGN_EXTEND for THUMB1 too? Or do we need to keep calling thumb1_extendhisi2 and thumb1_extendqisi2?

Kind regards,
Torbjörn

Reply via email to