diff mbox

[arm-embedded,committed,2/7] Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute

Message ID 58455008.9090607@arm.com
State New
Headers show

Commit Message

Andre Vieira (lists) Dec. 5, 2016, 11:31 a.m. UTC
On 27/10/16 11:19, Kyrill Tkachov wrote:
> 
> On 27/10/16 10:54, Andre Vieira (lists) wrote:
>> On 26/10/16 17:28, Kyrill Tkachov wrote:
>>> On 26/10/16 17:28, Andre Vieira (lists) wrote:
>>>> On 26/10/16 10:33, Kyrill Tkachov wrote:
>>>>> +static tree
>>>>> +arm_handle_cmse_nonsecure_entry (tree *node, tree name,
>>>>> +                 tree /* args */,
>>>>> +                 int /* flags */,
>>>>> +                 bool *no_add_attrs)
>>>>> +{
>>>>> +  tree fndecl;
>>>>> +
>>>>> +  if (!use_cmse)
>>>>> +    {
>>>>> +      *no_add_attrs = true;
>>>>> +      return NULL_TREE;
>>>>> +    }
>>>>>
>>>>> Do you also want to warn the user here that the attribute will be
>>>>> ignored?
>>>>> This looks ok to me otherwise.
>>>>>
>>>> Can easily do and might be more user friendly. How about
>>>> "<attribute_name> attribute ignored without -mcmse option."
>>> Yes, that's fine (without the full stop at the end)
>>> Kyrill
>>>
>>>> Cheers,
>>>> Andre
>>>>
>> Hi,
>>
>> Reworked comments. No change to ChangeLogs.
> 
> Ok.
> Thanks,
> Kyrill
> 
>> Cheers,
>> Andre
> 
Hi,

Backported this to the embedded-6-branch in revision r243248.

Cheers,
Andre

gcc/ChangeLog.arm:
2016-12-05  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	Backport from mainline
	2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
		    Thomas Preud'homme	<thomas.preudhomme@arm.com>

	* config/arm/arm.c (arm_handle_cmse_nonsecure_entry): New.
	(arm_attribute_table): Added cmse_nonsecure_entry
	(arm_compute_func_type): Handle cmse_nonsecure_entry.
	(cmse_func_args_or_return_in_stack): New.
	(arm_handle_cmse_nonsecure_entry): New.
	* config/arm/arm.h (ARM_FT_CMSE_ENTRY): New macro define.
	(IS_CMSE_ENTRY): Likewise.
	* doc/extend.texi (ARM ARMv8-M Security Extensions): New attribute.

gcc/testsuite/ChangeLog.arm:
2016-12-05  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	Backport from mainline
	2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
		    Thomas Preud'homme	<thomas.preudhomme@arm.com>
diff mbox

Patch

diff --git a/gcc/ChangeLog.arm b/gcc/ChangeLog.arm
index 98704eb438dadd73cf793da5a7b8266b5e9ef267..c93007a6b814320f3a3fb283873e21347b4cd333 100644
--- a/gcc/ChangeLog.arm
+++ b/gcc/ChangeLog.arm
@@ -4,6 +4,21 @@ 
 	2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
 		    Thomas Preud'homme	<thomas.preudhomme@arm.com>
 
+	* config/arm/arm.c (arm_handle_cmse_nonsecure_entry): New.
+	(arm_attribute_table): Added cmse_nonsecure_entry
+	(arm_compute_func_type): Handle cmse_nonsecure_entry.
+	(cmse_func_args_or_return_in_stack): New.
+	(arm_handle_cmse_nonsecure_entry): New.
+	* config/arm/arm.h (ARM_FT_CMSE_ENTRY): New macro define.
+	(IS_CMSE_ENTRY): Likewise.
+	* doc/extend.texi (ARM ARMv8-M Security Extensions): New attribute.
+
+2016-12-05  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+
+	Backport from mainline
+	2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+		    Thomas Preud'homme	<thomas.preudhomme@arm.com>
+
 	* config.gcc (extra_headers): Added arm_cmse.h.
 	* config/arm/arm-arches.def (ARM_ARCH):
 	(armv8-m): Add FL2_CMSE.
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index de9ad3e6a2df5103519ec16fcecdac8861a1cdfc..4e5e477bd2ba4eaa30640d0fdb4336b56cb37391 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1383,6 +1383,7 @@  enum reg_class
 #define ARM_FT_VOLATILE		(1 << 4) /* Does not return.  */
 #define ARM_FT_NESTED		(1 << 5) /* Embedded inside another func.  */
 #define ARM_FT_STACKALIGN	(1 << 6) /* Called with misaligned stack.  */
+#define ARM_FT_CMSE_ENTRY	(1 << 7) /* ARMv8-M non-secure entry function.  */
 
 /* Some macros to test these flags.  */
 #define ARM_FUNC_TYPE(t)	(t & ARM_FT_TYPE_MASK)
@@ -1391,6 +1392,7 @@  enum reg_class
 #define IS_NAKED(t)        	(t & ARM_FT_NAKED)
 #define IS_NESTED(t)       	(t & ARM_FT_NESTED)
 #define IS_STACKALIGN(t)       	(t & ARM_FT_STACKALIGN)
+#define IS_CMSE_ENTRY(t)	(t & ARM_FT_CMSE_ENTRY)
 
 
 /* Structure used to hold the function stack frame layout.  Offsets are
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 7050f4897ddd9886d6c5377ca9c3e2764e2dff25..6eafba774542fb4b20f7b72fd353621a54ca5bc6 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -136,6 +136,7 @@  static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
 #endif
+static tree arm_handle_cmse_nonsecure_entry (tree *, tree, tree, int, bool *);
 static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
 static int arm_comp_type_attributes (const_tree, const_tree);
@@ -348,6 +349,9 @@  static const struct attribute_spec arm_attribute_table[] =
   { "notshared",    0, 0, false, true, false, arm_handle_notshared_attribute,
     false },
 #endif
+  /* ARMv8-M Security Extensions support.  */
+  { "cmse_nonsecure_entry", 0, 0, true, false, false,
+    arm_handle_cmse_nonsecure_entry, false },
   { NULL,           0, 0, false, false, false, NULL, false }
 };
 
@@ -3601,6 +3605,9 @@  arm_compute_func_type (void)
   else
     type |= arm_isr_value (TREE_VALUE (a));
 
+  if (lookup_attribute ("cmse_nonsecure_entry", attr))
+    type |= ARM_FT_CMSE_ENTRY;
+
   return type;
 }
 
@@ -6594,6 +6601,113 @@  arm_handle_notshared_attribute (tree *node,
 }
 #endif
 
+/* This function returns true if a function with declaration FNDECL and type
+   FNTYPE uses the stack to pass arguments or return variables and false
+   otherwise.  This is used for functions with the attributes
+   'cmse_nonsecure_call' or 'cmse_nonsecure_entry' and this function will issue
+   diagnostic messages if the stack is used.  NAME is the name of the attribute
+   used.  */
+
+static bool
+cmse_func_args_or_return_in_stack (tree fndecl, tree name, tree fntype)
+{
+  function_args_iterator args_iter;
+  CUMULATIVE_ARGS args_so_far_v;
+  cumulative_args_t args_so_far;
+  bool first_param = true;
+  tree arg_type, prev_arg_type = NULL_TREE, ret_type;
+
+  /* Error out if any argument is passed on the stack.  */
+  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;
+      machine_mode arg_mode = TYPE_MODE (arg_type);
+
+      prev_arg_type = arg_type;
+      if (VOID_TYPE_P (arg_type))
+	continue;
+
+      if (!first_param)
+	arm_function_arg_advance (args_so_far, arg_mode, arg_type, true);
+      arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type, true);
+      if (!arg_rtx
+	  || arm_arg_partial_bytes (args_so_far, arg_mode, arg_type, true))
+	{
+	  error ("%qE attribute not available to functions with arguments "
+		 "passed on the stack", name);
+	  return true;
+	}
+      first_param = false;
+    }
+
+  /* Error out for variadic functions since we cannot control how many
+     arguments will be passed and thus stack could be used.  stdarg_p () is not
+     used for the checking to avoid browsing arguments twice.  */
+  if (prev_arg_type != NULL_TREE && !VOID_TYPE_P (prev_arg_type))
+    {
+      error ("%qE attribute not available to functions with variable number "
+	     "of arguments", name);
+      return true;
+    }
+
+  /* Error out if return value is passed on the stack.  */
+  ret_type = TREE_TYPE (fntype);
+  if (arm_return_in_memory (ret_type, fntype))
+    {
+      error ("%qE attribute not available to functions that return value on "
+	     "the stack", name);
+      return true;
+    }
+  return false;
+}
+
+/* Called upon detection of the use of the cmse_nonsecure_entry attribute, this
+   function will check whether the attribute is allowed here and will add the
+   attribute to the function declaration tree or otherwise issue a warning.  */
+
+static tree
+arm_handle_cmse_nonsecure_entry (tree *node, tree name,
+				 tree /* args */,
+				 int /* flags */,
+				 bool *no_add_attrs)
+{
+  tree fndecl;
+
+  if (!use_cmse)
+    {
+      *no_add_attrs = true;
+      warning (OPT_Wattributes, "%qE attribute ignored without -mcmse option.",
+	       name);
+      return NULL_TREE;
+    }
+
+  /* Ignore attribute for function types.  */
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+	       name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  fndecl = *node;
+
+  /* Warn for static linkage functions.  */
+  if (!TREE_PUBLIC (fndecl))
+    {
+      warning (OPT_Wattributes, "%qE attribute has no effect on functions "
+	       "with static linkage", name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  *no_add_attrs |= cmse_func_args_or_return_in_stack (fndecl, name,
+						TREE_TYPE (fndecl));
+  return NULL_TREE;
+}
+
 /* Return 0 if the attributes for two types are incompatible, 1 if they
    are compatible, and 2 if they are nearly compatible (which causes a
    warning to be generated).  */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index b582d5300d464ac3783c1fe60a73aca2527a9575..1693c5968c608303159ac8b4a24744c0c57b7936 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -12269,6 +12269,9 @@  Security Extensions: Requiremenets on Development Tools Engineering
 Specification, which can be found at
 @uref{http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/ECM0359818_armv8m_security_extensions_reqs_on_dev_tools_1_0.pdf}.
 
+As part of the Security Extensions GCC implements a new function attribute
+@code{cmse_nonsecure_entry}.
+
 As part of the Security Extensions GCC implements the intrinsics below.  FPTR
 is used here to mean any function pointer type.
 
diff --git a/gcc/testsuite/ChangeLog.arm b/gcc/testsuite/ChangeLog.arm
index 767b44aec61c90663ed7540e34c0e24da8c4835c..30afd4b0fa9b6f2859a3f0c84485b40487f602e9 100644
--- a/gcc/testsuite/ChangeLog.arm
+++ b/gcc/testsuite/ChangeLog.arm
@@ -4,6 +4,14 @@ 
 	2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
 		    Thomas Preud'homme	<thomas.preudhomme@arm.com>
 
+	* gcc.target/arm/cmse/cmse-3.c: New.
+
+2016-12-05  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+
+	Backport from mainline
+	2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+		    Thomas Preud'homme	<thomas.preudhomme@arm.com>
+
 	* gcc.target/arm/cmse/cmse.exp: New.
 	* gcc.target/arm/cmse/cmse-1.c: New.
 	* gcc.target/arm/cmse/cmse-12.c: New.
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c2920e1dc310106d83203eb51e1a68a275d0152
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
@@ -0,0 +1,37 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mcmse" }  */
+
+struct span {
+  int a, b;
+};
+struct span2 {
+  float a, b, c, d;
+};
+
+union test_union
+{
+  long long a;
+  int b;
+  struct span2 c;
+} test_union;
+
+void __attribute__ ((cmse_nonsecure_entry))
+foo (long long a, int b, long long c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */
+
+void __attribute__ ((cmse_nonsecure_entry))
+bar (long long a, int b, struct span c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */
+
+void __attribute__ ((cmse_nonsecure_entry))
+baz (int a, ...) {} /* { dg-error "not available to functions with variable number of arguments" } */
+
+struct span __attribute__ ((cmse_nonsecure_entry))
+qux (void) { /* { dg-error "not available to functions that return value on the stack" } */
+  struct span ret = {0, 0};
+  return ret;
+}
+
+void __attribute__ ((cmse_nonsecure_entry))
+norf (struct span2 a) {}
+
+void __attribute__ ((cmse_nonsecure_entry))
+foo2 (long long a, int b, union test_union c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */