This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC][PATCH v2, ARM 5/8] ARMv8-M Security Extension's cmse_nonsecure_entry: clear registers


On 29/01/16 17:07, Andre Vieira (lists) wrote:
> On 26/12/15 01:54, Thomas Preud'homme wrote:
>> [Sending on behalf of Andre Vieira]
>>
>> Hello,
>>
>> This patch extends support for the ARMv8-M Security Extensions
>> 'cmse_nonsecure_entry' attribute to safeguard against leak of
>> information through unbanked registers.
>>
>> When returning from a nonsecure entry function we clear all
>> caller-saved registers that are not used to pass return values, by
>> writing either the LR, in case of general purpose registers, or the
>> value 0, in case of FP registers. We use the LR to write to APSR and
>> FPSCR too. We currently only support 32 FP registers as in we only
>> clear D0-D7.
>> We currently do not support entry functions that pass arguments or
>> return variables on the stack and we diagnose this. This patch relies
>> on the existing code to make sure callee-saved registers used in
>> cmse_nonsecure_entry functions are saved and restored thus retaining
>> their nonsecure mode value, this should be happening already as it is
>> required by AAPCS.
>>
>>
>> *** gcc/ChangeLog ***
>> 2015-10-27  Andre Vieira        <andre.simoesdiasvieira@arm.com>
>>              Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>          * gcc/config/arm/arm.c (output_return_instruction): Clear
>>            registers.
>>            (thumb2_expand_return): Likewise.
>>            (thumb1_expand_epilogue): Likewise.
>>            (arm_expand_epilogue): Likewise.
>>            (cmse_nonsecure_entry_clear_before_return): New.
>>          * gcc/config/arm/arm.h (TARGET_DSP_ADD): New macro define.
>>          * gcc/config/arm/thumb1.md (*epilogue_insns): Change length
>> attribute.
>>          * gcc/config/arm/thumb2.md (*thumb2_return): Likewise.
>>
>> *** gcc/testsuite/ChangeLog ***
>> 2015-10-27  Andre Vieira        <andre.simoesdiasvieira@arm.com>
>>              Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>          * gcc.target/arm/cmse/cmse.exp: Test different multilibs
>> separate.
>>          * gcc.target/arm/cmse/baseline/cmse-2.c: Test that registers
>> are cleared.
>>          * gcc.target/arm/cmse/mainline/soft/cmse-5.c: New.
>>          * gcc.target/arm/cmse/mainline/hard/cmse-5.c: New.
>>          * gcc.target/arm/cmse/mainline/hard-sp/cmse-5.c: New.
>>          * gcc.target/arm/cmse/mainline/softfp/cmse-5.c: New.
>>          * gcc.target/arm/cmse/mainline/softfp-sp/cmse-5.c: New.
>>
>>
>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>> index
>> f12e3c93bbe24b10ed8eee6687161826773ef649..b06e0586a3da50f57645bda13629bc4dbd3d53b7
>> 100644
>> --- a/gcc/config/arm/arm.h
>> +++ b/gcc/config/arm/arm.h
>> @@ -230,6 +230,9 @@ extern void
>> (*arm_lang_output_object_attributes_hook)(void);
>>   /* Integer SIMD instructions, and extend-accumulate instructions.  */
>>   #define TARGET_INT_SIMD \
>>     (TARGET_32BIT && arm_arch6 && (arm_arch_notm || arm_arch7em))
>> +/* Parallel addition and subtraction instructions.  */
>> +#define TARGET_DSP_ADD \
>> +  (TARGET_ARM_ARCH >= 6 && (arm_arch_notm || arm_arch7em))
>>
>>   /* Should MOVW/MOVT be used in preference to a constant pool.  */
>>   #define TARGET_USE_MOVT \
>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>> index
>> e530b772e3cc053c16421a2a2861d815d53ebb01..0700478ca38307f35d0cb01f83ea182802ba28fa
>> 100644
>> --- a/gcc/config/arm/arm.c
>> +++ b/gcc/config/arm/arm.c
>> @@ -19755,6 +19755,24 @@ output_return_instruction (rtx operand, bool
>> really_return, bool reverse,
>>       default:
>>         if (IS_CMSE_ENTRY (func_type))
>>           {
>> +          char flags[12] = "APSR_nzcvq";
>> +          /* Check if we have to clear the 'GE bits' which is only
>> used if
>> +         parallel add and subtraction instructions are available.  */
>> +          if (TARGET_DSP_ADD)
>> +        {
>> +          /* If so also clear the ge flags.  */
>> +          flags[10] = 'g';
>> +          flags[11] = '\0';
>> +        }
>> +          snprintf (instr, sizeof (instr),  "msr%s\t%s, %%|lr",
>> conditional,
>> +            flags);
>> +          output_asm_insn (instr, & operand);
>> +          if (TARGET_HARD_FLOAT && TARGET_VFP)
>> +        {
>> +          snprintf (instr, sizeof (instr), "vmsr%s\tfpscr, %%|lr",
>> +                conditional);
>> +          output_asm_insn (instr, & operand);
>> +        }
>>             snprintf (instr, sizeof (instr), "bxns%s\t%%|lr",
>> conditional);
>>           }
>>         /* Use bx if it's available.  */
>> @@ -23999,6 +24017,17 @@ thumb_pop (FILE *f, unsigned long mask)
>>   static void
>>   thumb1_cmse_nonsecure_entry_return (FILE *f, int
>> reg_containing_return_addr)
>>   {
>> +  char flags[12] = "APSR_nzcvq";
>> +  /* Check if we have to clear the 'GE bits' which is only used if
>> +     parallel add and subtraction instructions are available.  */
>> +  if (TARGET_DSP_ADD)
>> +    {
>> +      flags[10] = 'g';
>> +      flags[11] = '\0';
>> +    }
>> +  asm_fprintf (f, "\tmsr\t%s, %r\n", flags, reg_containing_return_addr);
>> +  if (TARGET_HARD_FLOAT && TARGET_VFP)
>> +    asm_fprintf (f, "\tvmsr\tfpscr, %r\n", reg_containing_return_addr);
>>     asm_fprintf (f, "\tbxns\t%r\n", reg_containing_return_addr);
>>   }
>>
>> @@ -25140,6 +25169,139 @@ thumb1_expand_prologue (void)
>>       cfun->machine->lr_save_eliminated = 0;
>>   }
>>
>> +/* Clear caller saved registers not used to pass return values and
>> leaked
>> +   condition flags before exiting a cmse_nonsecure_entry function.  */
>> +
>> +void
>> +cmse_nonsecure_entry_clear_before_return (void)
>> +{
>> +  uint64_t to_clear_mask;
>> +  int regno, maxregno = IP_REGNUM;
>> +  tree result_type;
>> +  rtx result_rtl;
>> +
>> +  to_clear_mask = (1LL << (NUM_ARG_REGS)) - 1;
>> +  to_clear_mask |= (1LL << IP_REGNUM);
>> +  /* If we are not dealing with -mfloat-abi=softfp we will need to
>> clear VFP
>> +     registers.  We also check TARGET_VFP to make sure these are
>> present.  */
>> +  if (TARGET_HARD_FLOAT && TARGET_VFP)
>> +    {
>> +      uint64_t float_mask = (1LL << (D7_VFP_REGNUM + 1)) - 1;
>> +      float_mask &= ~((1LL << FIRST_VFP_REGNUM) - 1);
>> +      to_clear_mask |= float_mask;
>> +      maxregno = LAST_VFP_REGNUM;
>> +    }
>> +
>> +  /* If the user has defined registers to be caller saved, these are
>> no longer
>> +     restored by the function before returning and must thus be
>> cleared for
>> +     security purposes.  */
>> +  for (regno = NUM_ARG_REGS; regno < LAST_VFP_REGNUM; regno++)
>> +    {
>> +      /* We leave registers traditionally used to pass arguments
>> untouched,
>> +     since if these should not be made callee-saved by the user.  */
>> +      if (regno >= FIRST_VFP_REGNUM && regno <= D7_VFP_REGNUM)
>> +    continue;
>> +      if (regno >= IP_REGNUM && regno <= PC_REGNUM)
>> +    continue;
>> +      if (call_used_regs[regno])
>> +    to_clear_mask |= (1LL << regno);
>> +    }
>> +
>> +  /* Make sure we do not clear the registers used to pass the result
>> in.  */
>> +  result_type = TREE_TYPE (DECL_RESULT (current_function_decl));
>> +  if (!VOID_TYPE_P (result_type))
>> +    {
>> +      rtx reg;
>> +
>> +      result_rtl = arm_function_value (result_type,
>> current_function_decl, 0);
>> +
>> +      /* No need to check that we return in registers, because we don't
>> +     support returning on stack yet.  */
>> +      switch (GET_MODE (result_rtl))
>> +    {
>> +    case BLKmode:
>> +      /* We are dealing with a return in multiple VFP registers.  */
>> +      {
>> +        int i;
>> +        /* This should really only occur when dealing with an hard float
>> +           abi.  */
>> +        gcc_assert (TARGET_HARD_FLOAT_ABI && TARGET_VFP);
>> +
>> +        for (i = 0; i < XVECLEN (result_rtl, 0); i++)
>> +          {
>> +        reg = XEXP (XVECEXP (result_rtl, 0, i), 0);
>> +        gcc_assert (REG_P (reg));
>> +        /* If we are dealing with DF mode, make sure you don't clear
>> +           either registers it addresses.  */
>> +        if (GET_MODE (reg) == DFmode)
>> +          to_clear_mask &= ~(1LL << (REGNO (reg) + 1));
>> +        to_clear_mask &= ~(1LL << REGNO (reg));
>> +          }
>> +      }
>> +      break;
>> +    case DImode:
>> +      to_clear_mask &= ~2; /* Don't clear r0 and r1.  */
>> +    case SImode:
>> +      to_clear_mask &= ~1; /* Don't clear r0.  */
>> +      break;
>> +    case DFmode:
>> +      /* If we have -mfloat-abi=hard, do not clear registers used to
>> pass
>> +         return value.  */
>> +      if (TARGET_HARD_FLOAT_ABI && TARGET_VFP)
>> +        /* Don't clear s0 and s1.  */
>> +        to_clear_mask &= ~(1LL << (FIRST_VFP_REGNUM + 1));
>> +      else
>> +        to_clear_mask &= ~2; /* Don't clear r0, r1.  */
>> +    case SFmode:
>> +      /* If we have -mfloat-abi=hard, do not clear registers used to
>> pass
>> +         return value.  */
>> +      if (TARGET_HARD_FLOAT_ABI && TARGET_VFP)
>> +        /* Don't clear s0.  */
>> +        to_clear_mask &= ~(1LL << FIRST_VFP_REGNUM);
>> +      else
>> +        to_clear_mask &= ~1; /* Don't clear r0.  */
>> +      break;
>> +    default:
>> +      /* We are missing a mode, though AAPCS says we may only return in
>> +         r0 and r1, s0-d15/d0-d7 so something went wrong here.  */
>> +      gcc_unreachable ();
>> +      break;
>> +    }
>> +    }
>> +
>> +    for (regno = 0; regno <= maxregno; regno++)
>> +      {
>> +    if (!(to_clear_mask & (1LL << regno)))
>> +      continue;
>> +
>> +    /* If regno is a vfp register, even and its successor is also to
>> +       be cleared, use vmov.  */
>> +    if (IS_VFP_REGNUM (regno))
>> +      {
>> +        if (TARGET_VFP_DOUBLE
>> +        && VFP_REGNO_OK_FOR_DOUBLE (regno)
>> +        && to_clear_mask & (1LL << (regno + 1)))
>> +          {
>> +        emit_move_insn (gen_rtx_REG (DFmode, regno++),
>> +                CONST1_RTX (DFmode));
>> +        emit_use (gen_rtx_REG (DFmode, regno));
>> +          }
>> +        else
>> +          {
>> +        emit_move_insn (gen_rtx_REG (SFmode, regno),
>> +                CONST1_RTX (SFmode));
>> +        emit_use (gen_rtx_REG (SFmode, regno));
>> +          }
>> +      }
>> +    else
>> +      {
>> +        emit_move_insn (gen_rtx_REG (SImode, regno),
>> +                gen_rtx_REG (SImode, LR_REGNUM));
>> +        emit_use (gen_rtx_REG (SImode, regno));
>> +      }
>> +      }
>> +}
>> +
>>   /* Generate pattern *pop_multiple_with_stack_update_and_return if
>> single
>>      POP instruction can be generated.  LR should be replaced by PC.  All
>>      the checks required are already done by  USE_RETURN_INSN ().  Hence,
>> @@ -25189,6 +25351,8 @@ thumb2_expand_return (bool simple_return)
>>       }
>>     else
>>       {
>> +      if (IS_CMSE_ENTRY (arm_current_func_type ()))
>> +    cmse_nonsecure_entry_clear_before_return ();
>>         emit_jump_insn (simple_return_rtx);
>>       }
>>   }
>> @@ -25247,6 +25411,10 @@ thumb1_expand_epilogue (void)
>>
>>     if (! df_regs_ever_live_p (LR_REGNUM))
>>       emit_use (gen_rtx_REG (SImode, LR_REGNUM));
>> +
>> +  /* Clear all caller-saved regs that are not used to return.  */
>> +  if (IS_CMSE_ENTRY (arm_current_func_type ()))
>> +    cmse_nonsecure_entry_clear_before_return ();
>>   }
>>
>>   /* Epilogue code for APCS frame.  */
>> @@ -25681,6 +25849,14 @@ arm_expand_epilogue (bool really_return)
>>                      stack_pointer_rtx, stack_pointer_rtx);
>>       }
>>
>> +    /* Clear all caller-saved regs that are not used to return.  */
>> +    if (IS_CMSE_ENTRY (arm_current_func_type ()))
>> +      {
>> +    /* CMSE_ENTRY always returns!  */
>> +    gcc_assert (really_return);
>> +    cmse_nonsecure_entry_clear_before_return ();
>> +      }
>> +
>>     if (!really_return)
>>       return;
>>
>> diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
>> index
>> d2a0420a2e9c71bb954d134fb88a86d694cf786d..cdcf397b0cab0ea7f246ad830ad28b07fed71d8b
>> 100644
>> --- a/gcc/config/arm/thumb1.md
>> +++ b/gcc/config/arm/thumb1.md
>> @@ -1757,8 +1757,15 @@
>>     "*
>>       return thumb1_unexpanded_epilogue ();
>>     "
>> -  ; Length is absolute worst case
>> -  [(set_attr "length" "44")
>> +  ; Length is absolute worst case, when using CMSE and if this is an
>> entry
>> +  ; function an extra 4 (msr) to 8 (vmsr) extra might be added.
>> +  [(set (attr "length")
>> +    (if_then_else
>> +     (match_test "IS_CMSE_ENTRY (arm_current_func_type ())")
>> +     (if_then_else (match_test "TARGET_HARD_FLOAT && TARGET_VFP")
>> +      (const_int 52)
>> +      (const_int 48))
>> +     (const_int 44)))
>>      (set_attr "type" "block")
>>      ;; We don't clobber the conditions, but the potential length of this
>>      ;; operation is sufficient to make conditionalizing the sequence
>> diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
>> index
>> a724752a39cf2862c68a53ef28a239de2ae1ed96..0c07df91fe8844a7e7437ef5b7f00f74815d63f4
>> 100644
>> --- a/gcc/config/arm/thumb2.md
>> +++ b/gcc/config/arm/thumb2.md
>> @@ -1106,7 +1106,15 @@
>>     "TARGET_THUMB2"
>>     "* return output_return_instruction (const_true_rtx, true, false,
>> true);"
>>     [(set_attr "type" "branch")
>> -   (set_attr "length" "4")]
>> +  ; If this is a return from a cmse_nonsecure_entry function then
>> code will be
>> +  ; added to clear the APSR and potentially the FPSCR if VFP is
>> available, so
>> +  ; we adapt the length accordingly.
>> +   (set (attr "length")
>> +    (if_then_else (match_test "IS_CMSE_ENTRY (arm_current_func_type
>> ())")
>> +     (if_then_else (match_test "TARGET_HARD_FLOAT && TARGET_VFP")
>> +      (const_int 12)
>> +      (const_int 8))
>> +     (const_int 4)))]
>>   )
>>
>>   (define_insn_and_split "thumb2_eh_return"
>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-2.c
>> b/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-2.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..7cef73372fd5f5be080bdfe30999694564deaa9a
>>
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-2.c
>> @@ -0,0 +1,18 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target arm_arch_v8m_base_ok } */
>> +/* { dg-add-options arm_arch_v8m_base } */
>> +/* { dg-options "-mcmse" }  */
>> +
>> +extern float bar (void);
>> +
>> +float __attribute__ ((cmse_nonsecure_entry))
>> +foo (void)
>> +{
>> +  return bar ();
>> +}
>> +/* { dg-final { scan-assembler "mov\tr1, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr2, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr3, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tip, lr" } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, r1" } } */
>> +/* { dg-final { scan-assembler "bxns\tr1" } } */
>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse.exp
>> b/gcc/testsuite/gcc.target/arm/cmse/cmse.exp
>> index
>> 6d4bfec1d12bc575218e0b8c33559d0a4da9ec70..592349ad07257f8074f9443a599ae08c36136a80
>> 100644
>> --- a/gcc/testsuite/gcc.target/arm/cmse/cmse.exp
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse.exp
>> @@ -38,6 +38,26 @@ set LTO_TORTURE_OPTIONS ""
>>   gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] \
>>       "" $DEFAULT_CFLAGS
>>
>> +if {[check_effective_target_arm_arch_v8m_base_ok]} then {
>> +    # Baseline only
>> +    gcc-dg-runtest [lsort [glob $srcdir/$subdir/baseline/*.c]] \
>> +        "" $DEFAULT_CFLAGS
>> +}
>> +
>> +if {[check_effective_target_arm_arch_v8m_main_ok]} then {
>> +    # Mainline -mfloat-abi=soft
>> +    gcc-dg-runtest [lsort [glob $srcdir/$subdir/mainline/soft/*.c]] \
>> +        "-mfloat-abi=soft" $DEFAULT_CFLAGS
>> +    gcc-dg-runtest [lsort [glob $srcdir/$subdir/mainline/softfp/*.c]] \
>> +        "" $DEFAULT_CFLAGS
>> +    gcc-dg-runtest [lsort [glob
>> $srcdir/$subdir/mainline/softfp-sp/*.c]] \
>> +        "" $DEFAULT_CFLAGS
>> +    gcc-dg-runtest [lsort [glob $srcdir/$subdir/mainline/hard/*.c]] \
>> +        "" $DEFAULT_CFLAGS
>> +    gcc-dg-runtest [lsort [glob $srcdir/$subdir/mainline/hard-sp/*.c]] \
>> +        "" $DEFAULT_CFLAGS
>> +}
>> +
>>   set LTO_TORTURE_OPTIONS ${saved-lto_torture_options}
>>   set dg-do-what-default ${saved-dg-do-what-default}
>>
>> diff --git
>> a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-5.c
>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-5.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..ab607aa1b7210acc7983bfb401e95117eb8c0d17
>>
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-5.c
>> @@ -0,0 +1,37 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target arm_arch_v8m_main_ok } */
>> +/* { dg-add-options arm_arch_v8m_main } */
>> +/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp"
>> {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
>> +/* { dg-skip-if "Skip these if testing double precision" {*-*-*}
>> {"-mfpu=fpv[4-5]-d16"} {""} } */
>> +/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-sp-d16" }  */
>> +
>> +extern float bar (void);
>> +
>> +float __attribute__ ((cmse_nonsecure_entry))
>> +foo (void)
>> +{
>> +  return bar ();
>> +}
>> +/* { dg-final { scan-assembler "mov\tr0, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr1, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr2, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr3, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tip, lr" } } */
>> +/* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts3, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts4, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts5, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts6, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts7, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts8, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts9, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts10, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts11, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts12, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts13, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts14, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts15, #1\.0" } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target {
>> arm_arch_v8m_main_ok && { ! arm_dsp } } } } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target {
>> arm_arch_v8m_main_ok && arm_dsp } } } } */
>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-5.c
>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-5.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..5ed7e1d6404b8f17d630895eb06df5921a1a965f
>>
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-5.c
>> @@ -0,0 +1,30 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target arm_arch_v8m_main_ok } */
>> +/* { dg-add-options arm_arch_v8m_main } */
>> +/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp"
>> {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
>> +/* { dg-skip-if "Skip these if testing single precision" {*-*-*}
>> {"-mfpu=*-sp-*"} {""} } */
>> +/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-d16" }  */
>> +
>> +extern float bar (void);
>> +
>> +float __attribute__ ((cmse_nonsecure_entry))
>> +foo (void)
>> +{
>> +  return bar ();
>> +}
>> +/* { dg-final { scan-assembler "mov\tr0, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr1, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr2, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr3, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tip, lr" } } */
>> +/* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td3, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td4, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td5, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td6, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td7, #1\.0" } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target {
>> arm_arch_v8m_main_ok && { ! arm_dsp } } } } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target {
>> arm_arch_v8m_main_ok && arm_dsp } } } } */
>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-5.c
>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-5.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..d24683f52eba11df5b41eef0e5a8e365fb206fe8
>>
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-5.c
>> @@ -0,0 +1,22 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target arm_arch_v8m_main_ok } */
>> +/* { dg-add-options arm_arch_v8m_main } */
>> +/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp"
>> {*-*-*} {"-mfloat-abi=hard" -mfloat-abi=softfp } {""} } */
>> +/* { dg-options "-mcmse -mfloat-abi=soft" }  */
>> +
>> +extern float bar (void);
>> +
>> +float __attribute__ ((cmse_nonsecure_entry))
>> +foo (void)
>> +{
>> +  return bar ();
>> +}
>> +
>> +/* { dg-final { scan-assembler "mov\tr1, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr2, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr3, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tip, lr" } } */
>> +/* { dg-final { scan-assembler-not "vmov" } } */
>> +/* { dg-final { scan-assembler-not "vmsr" } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target {
>> arm_arch_v8m_main_ok && { ! arm_dsp } } } } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target {
>> arm_arch_v8m_main_ok && arm_dsp } } } } */
>> diff --git
>> a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-5.c
>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-5.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..c22775ace8361729c36130422475522fbaca05b5
>>
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-5.c
>> @@ -0,0 +1,39 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target arm_arch_v8m_main_ok } */
>> +/* { dg-add-options arm_arch_v8m_main } */
>> +/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp"
>> {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
>> +/* { dg-skip-if "Skip these if testing double precision" {*-*-*}
>> {"-mfpu=fpv[4-5]-d16"} {""} } */
>> +/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-sp-d16" }  */
>> +
>> +extern float bar (void);
>> +
>> +float __attribute__ ((cmse_nonsecure_entry))
>> +foo (void)
>> +{
>> +  return bar ();
>> +}
>> +/* { dg-final { scan-assembler "__acle_se_foo:" } } */
>> +/* { dg-final { scan-assembler-not "mov\tr0, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr1, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr2, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr3, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tip, lr" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts0, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts3, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts4, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts5, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts6, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts7, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts8, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts9, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts10, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts11, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts12, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts13, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts14, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f32\ts15, #1\.0" } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target {
>> arm_arch_v8m_main_ok && { ! arm_dsp } } } } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target {
>> arm_arch_v8m_main_ok && arm_dsp } } } } */
>> +/* { dg-final { scan-assembler "bxns" } } */
>> diff --git
>> a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-5.c
>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-5.c
>> new file mode 100644
>> index
>> 0000000000000000000000000000000000000000..28b05c391081bd42407b4e56a1e84daa549fa06e
>>
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-5.c
>> @@ -0,0 +1,31 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target arm_arch_v8m_main_ok } */
>> +/* { dg-add-options arm_arch_v8m_main } */
>> +/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp"
>> {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
>> +/* { dg-skip-if "Skip these if testing single precision" {*-*-*}
>> {"-mfpu=*-sp-*"} {""} } */
>> +/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-d16" }  */
>> +
>> +extern float bar (void);
>> +
>> +float __attribute__ ((cmse_nonsecure_entry))
>> +foo (void)
>> +{
>> +  return bar ();
>> +}
>> +/* { dg-final { scan-assembler "__acle_se_foo:" } } */
>> +/* { dg-final { scan-assembler-not "mov\tr0, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr1, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr2, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tr3, lr" } } */
>> +/* { dg-final { scan-assembler "mov\tip, lr" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td0, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td3, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td4, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td5, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td6, #1\.0" } } */
>> +/* { dg-final { scan-assembler "vmov\.f64\td7, #1\.0" } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target {
>> arm_arch_v8m_main_ok && { ! arm_dsp } } } } } */
>> +/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target {
>> arm_arch_v8m_main_ok && arm_dsp } } } } */
>> +/* { dg-final { scan-assembler "bxns" } } */
>>
>> We welcome any comments.
>>
>> Cheers,
>>
>> Andre
>>
> Ping.
> 
Hi there,

This is an updated version of the previous patch to clear the unused
bits when returning a compound type. As per the ABI these have undefined
values and thus may leak security sensitive information.

Any comments?

Cheers,
Andre

*** ChangeLog ***
2016-03-29  Andre Vieira        <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * gcc/config/arm/arm.c (output_return_instruction): Clear
          registers.
          (thumb2_expand_return): Likewise.
          (thumb1_expand_epilogue): Likewise.
          (arm_expand_epilogue): Likewise.
          (cmse_nonsecure_entry_clear_before_return): New.
        * gcc/config/arm/thumb1.md (*epilogue_insns): Change length
attribute.
        * gcc/config/arm/thumb2.md (*thumb2_return): Likewise.

*** gcc/testsuite/ChangeLog ***
2016-03-29  Andre Vieira        <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * gcc.target/arm/cmse/cmse.exp: Test different multilibs separate.
        * gcc.target/arm/cmse/struct-1.c: New.
        * gcc.target/arm/cmse/bitfield-1.c: New.
        * gcc.target/arm/cmse/bitfield-2.c: New.
        * gcc.target/arm/cmse/bitfield-3.c: New.
        * gcc.target/arm/cmse/baseline/cmse-2.c: Test that registers are
cleared.
        * gcc.target/arm/cmse/mainline/soft/cmse-5.c: New.
        * gcc.target/arm/cmse/mainline/hard/cmse-5.c: New.
        * gcc.target/arm/cmse/mainline/hard-sp/cmse-5.c: New.
        * gcc.target/arm/cmse/mainline/softfp/cmse-5.c: New.
        * gcc.target/arm/cmse/mainline/softfp-sp/cmse-5.c: New.

Attachment: diff
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]