diff mbox

[RFC,ARM,6/8] Handling ARMv8-M Security Extension's cmse_nonsecure_call attribute

Message ID 001901d13f80$813a7230$83af5690$@foss.arm.com
State New
Headers show

Commit Message

Thomas Preudhomme Dec. 26, 2015, 1:55 a.m. UTC
[Sending on behalf of Andre Vieira]

Hello,

This patch adds support for the ARMv8-M Security Extensions 'cmse_nonsecure_call' attribute. This attribute may only be used for function types and when used in combination with the '-mcmse' compilation flag. See Section 5.5 of ARM®v8-M Security Extensions (http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/index.html).

We currently do not support cmse_nonsecure_call functions that pass arguments or return variables on the stack and we diagnose this. 

*** gcc/ChangeLog ***
2015-10-27  Andre Vieira        <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * gcc/config/arm/arm.c (gimplify.h): New include.
          (arm_handle_cmse_nonsecure_call): New.
          (arm_attribute_table): Added cmse_nonsecure_call.

*** gcc/testsuite/ChangeLog ***
2015-10-27  Andre Vieira        <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * gcc.target/arm/cmse/cmse-3.c: Add tests.
        * gcc.target/arm/cmse/cmse-4.c: Add tests.



We welcome any comment.

Cheers,

Andre

Comments

Andre Vieira (lists) Jan. 29, 2016, 5:07 p.m. UTC | #1
On 26/12/15 01:55, Thomas Preud'homme wrote:
> [Sending on behalf of Andre Vieira]
>
> Hello,
>
> This patch adds support for the ARMv8-M Security Extensions 'cmse_nonsecure_call' attribute. This attribute may only be used for function types and when used in combination with the '-mcmse' compilation flag. See Section 5.5 of ARM®v8-M Security Extensions (http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/index.html).
>
> We currently do not support cmse_nonsecure_call functions that pass arguments or return variables on the stack and we diagnose this.
>
> *** gcc/ChangeLog ***
> 2015-10-27  Andre Vieira        <andre.simoesdiasvieira@arm.com>
>              Thomas Preud'homme  <thomas.preudhomme@arm.com>
>
>          * gcc/config/arm/arm.c (gimplify.h): New include.
>            (arm_handle_cmse_nonsecure_call): New.
>            (arm_attribute_table): Added cmse_nonsecure_call.
>
> *** gcc/testsuite/ChangeLog ***
> 2015-10-27  Andre Vieira        <andre.simoesdiasvieira@arm.com>
>              Thomas Preud'homme  <thomas.preudhomme@arm.com>
>
>          * gcc.target/arm/cmse/cmse-3.c: Add tests.
>          * gcc.target/arm/cmse/cmse-4.c: Add tests.
>
>
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 0700478ca38307f35d0cb01f83ea182802ba28fa..4b4eea88cbec8e04d5b92210f0af2440ce6fb6e4 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -61,6 +61,7 @@
>   #include "builtins.h"
>   #include "tm-constrs.h"
>   #include "rtl-iter.h"
> +#include "gimplify.h"
>
>   /* This file should be included last.  */
>   #include "target-def.h"
> @@ -136,6 +137,7 @@ static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
>   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 tree arm_handle_cmse_nonsecure_call (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);
> @@ -347,6 +349,8 @@ static const struct attribute_spec arm_attribute_table[] =
>     /* ARMv8-M Security Extensions support.  */
>     { "cmse_nonsecure_entry", 0, 0, true, false, false,
>       arm_handle_cmse_nonsecure_entry, false },
> +  { "cmse_nonsecure_call", 0, 0, true, false, false,
> +    arm_handle_cmse_nonsecure_call, false },
>     { NULL,           0, 0, false, false, false, NULL, false }
>   };
>
>
> @@ -6667,6 +6671,76 @@ arm_handle_cmse_nonsecure_entry (tree *node, tree name,
>     return NULL_TREE;
>   }
>
> +
> +/* Called upon detection of the use of the cmse_nonsecure_call attribute, this
> +   function will check whether the attribute is allowed here and will add the
> +   attribute to the function type tree or otherwise issue a diagnose.  The
> +   reason we check this at declaration time is to only allow the use of the
> +   attribute with declartions of function pointers and not function
> +   declartions.  */
> +
> +static tree
> +arm_handle_cmse_nonsecure_call (tree *node, tree name,
> +				 tree /* args */,
> +				 int /* flags */,
> +				 bool *no_add_attrs)
> +{
> +  tree decl = NULL_TREE;
> +  tree type, fntype, main_variant;
> +
> +  if (!use_cmse)
> +    {
> +      *no_add_attrs = true;
> +      return NULL_TREE;
> +    }
> +
> +  if (TREE_CODE (*node) == VAR_DECL || TREE_CODE (*node) == TYPE_DECL)
> +    {
> +      decl = *node;
> +      type = TREE_TYPE (decl);
> +    }
> +
> +  if (!decl
> +      || (!(TREE_CODE (type) == POINTER_TYPE
> +	    && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
> +	  && TREE_CODE (type) != FUNCTION_TYPE))
> +    {
> +	warning (OPT_Wattributes, "%qE attribute only applies to base type of a "
> +		 "function pointer", name);
> +	*no_add_attrs = true;
> +	return NULL_TREE;
> +    }
> +
> +  /* type is either a function pointer, when the attribute is used on a function
> +   * pointer, or a function type when used in a typedef.  */
> +  if (TREE_CODE (type) == FUNCTION_TYPE)
> +    fntype = type;
> +  else
> +    fntype = TREE_TYPE (type);
> +
> +  *no_add_attrs |= cmse_func_args_or_return_in_stack (NULL, name, fntype);
> +
> +  if (*no_add_attrs)
> +    return NULL_TREE;
> +
> +  /* Prevent tree's being shared among function types with and without
> +     cmse_nonsecure_call attribute.  Do however make sure they keep the same
> +     main_variant, this is required for correct DIE output.  */
> +  main_variant = TYPE_MAIN_VARIANT (fntype);
> +  fntype = build_distinct_type_copy (fntype);
> +  TYPE_MAIN_VARIANT (fntype) = main_variant;
> +  if (TREE_CODE (type) == FUNCTION_TYPE)
> +    TREE_TYPE (decl) = fntype;
> +  else
> +    TREE_TYPE (type) = fntype;
> +
> +  /* Construct a type attribute and add it to the function type.  */
> +  tree attrs = tree_cons (get_identifier ("cmse_nonsecure_call"), NULL_TREE,
> +			  TYPE_ATTRIBUTES (fntype));
> +  TYPE_ATTRIBUTES (fntype) = attrs;
> +  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/testsuite/gcc.target/arm/cmse/cmse-3.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
> index f806951e90256e8286d2d0f9467b51a73a522e2b..0fe6eff45d2884736ba7049ce4ed5b9785b1018d 100644
> --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
> @@ -36,3 +36,11 @@ 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" } */
> +
> +typedef void __attribute__ ((cmse_nonsecure_call)) bar2 (long long a, int b, long long c); /* { dg-error "not available to functions with arguments passed on the stack" } */
> +
> +typedef void __attribute__ ((cmse_nonsecure_call)) baz2 (long long a, int b, struct span c); /* { dg-error "not available to functions with arguments passed on the stack" } */
> +
> +typedef struct span __attribute__ ((cmse_nonsecure_call)) qux2 (void); /* { dg-error "not available to functions that return value on the stack" } */
> +
> +typedef void __attribute__ ((cmse_nonsecure_call)) norf2 (int a, ...); /* { dg-error "not available to functions with variable number of arguments" } */
> diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c
> index ee4121f2e3f49aed4cae7bcc0e70217cbf1bd809..3521dc61f8fb974b43f504e3f634baf27a559b0b 100644
> --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c
> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c
> @@ -20,9 +20,16 @@ baz (void)
>     return qux ();
>   }
>
> +void __attribute__ ((cmse_nonsecure_call))
> +quux (void) {} /* { dg-warning "attribute only applies to base type of a function pointer" } */
> +
> +int __attribute__ ((cmse_nonsecure_call)) norf; /* { dg-warning "attribute only applies to base type of a function pointer" } */
> +
>   /* { dg-final { scan-assembler-times "bxns" 2 } } */
>   /* { dg-final { scan-assembler "foo:" } } */
>   /* { dg-final { scan-assembler "__acle_se_foo:" } } */
>   /* { dg-final { scan-assembler-not "__acle_se_bar:" } } */
>   /* { dg-final { scan-assembler "baz:" } } */
>   /* { dg-final { scan-assembler "__acle_se_baz:" } } */
> +/* { dg-final { scan-assembler-not "__acle_se_quux:" } } */
> +/* { dg-final { scan-assembler-not "__acle_se_norf:" } } */
>
> We welcome any comment.
>
> Cheers,
>
> Andre
>
Ping.
diff mbox

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 0700478ca38307f35d0cb01f83ea182802ba28fa..4b4eea88cbec8e04d5b92210f0af2440ce6fb6e4 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -61,6 +61,7 @@ 
 #include "builtins.h"
 #include "tm-constrs.h"
 #include "rtl-iter.h"
+#include "gimplify.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -136,6 +137,7 @@  static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
 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 tree arm_handle_cmse_nonsecure_call (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);
@@ -347,6 +349,8 @@  static const struct attribute_spec arm_attribute_table[] =
   /* ARMv8-M Security Extensions support.  */
   { "cmse_nonsecure_entry", 0, 0, true, false, false,
     arm_handle_cmse_nonsecure_entry, false },
+  { "cmse_nonsecure_call", 0, 0, true, false, false,
+    arm_handle_cmse_nonsecure_call, false },
   { NULL,           0, 0, false, false, false, NULL, false }
 };
 

@@ -6667,6 +6671,76 @@  arm_handle_cmse_nonsecure_entry (tree *node, tree name,
   return NULL_TREE;
 }
 
+
+/* Called upon detection of the use of the cmse_nonsecure_call attribute, this
+   function will check whether the attribute is allowed here and will add the
+   attribute to the function type tree or otherwise issue a diagnose.  The
+   reason we check this at declaration time is to only allow the use of the
+   attribute with declartions of function pointers and not function
+   declartions.  */
+
+static tree
+arm_handle_cmse_nonsecure_call (tree *node, tree name,
+				 tree /* args */,
+				 int /* flags */,
+				 bool *no_add_attrs)
+{
+  tree decl = NULL_TREE;
+  tree type, fntype, main_variant;
+
+  if (!use_cmse)
+    {
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  if (TREE_CODE (*node) == VAR_DECL || TREE_CODE (*node) == TYPE_DECL)
+    {
+      decl = *node;
+      type = TREE_TYPE (decl);
+    }
+
+  if (!decl
+      || (!(TREE_CODE (type) == POINTER_TYPE
+	    && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+	  && TREE_CODE (type) != FUNCTION_TYPE))
+    {
+	warning (OPT_Wattributes, "%qE attribute only applies to base type of a "
+		 "function pointer", name);
+	*no_add_attrs = true;
+	return NULL_TREE;
+    }
+
+  /* type is either a function pointer, when the attribute is used on a function
+   * pointer, or a function type when used in a typedef.  */
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    fntype = type;
+  else
+    fntype = TREE_TYPE (type);
+
+  *no_add_attrs |= cmse_func_args_or_return_in_stack (NULL, name, fntype);
+
+  if (*no_add_attrs)
+    return NULL_TREE;
+
+  /* Prevent tree's being shared among function types with and without
+     cmse_nonsecure_call attribute.  Do however make sure they keep the same
+     main_variant, this is required for correct DIE output.  */
+  main_variant = TYPE_MAIN_VARIANT (fntype);
+  fntype = build_distinct_type_copy (fntype);
+  TYPE_MAIN_VARIANT (fntype) = main_variant;
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    TREE_TYPE (decl) = fntype;
+  else
+    TREE_TYPE (type) = fntype;
+
+  /* Construct a type attribute and add it to the function type.  */
+  tree attrs = tree_cons (get_identifier ("cmse_nonsecure_call"), NULL_TREE,
+			  TYPE_ATTRIBUTES (fntype));
+  TYPE_ATTRIBUTES (fntype) = attrs;
+  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/testsuite/gcc.target/arm/cmse/cmse-3.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
index f806951e90256e8286d2d0f9467b51a73a522e2b..0fe6eff45d2884736ba7049ce4ed5b9785b1018d 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
@@ -36,3 +36,11 @@  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" } */
+
+typedef void __attribute__ ((cmse_nonsecure_call)) bar2 (long long a, int b, long long c); /* { dg-error "not available to functions with arguments passed on the stack" } */
+
+typedef void __attribute__ ((cmse_nonsecure_call)) baz2 (long long a, int b, struct span c); /* { dg-error "not available to functions with arguments passed on the stack" } */
+
+typedef struct span __attribute__ ((cmse_nonsecure_call)) qux2 (void); /* { dg-error "not available to functions that return value on the stack" } */
+
+typedef void __attribute__ ((cmse_nonsecure_call)) norf2 (int a, ...); /* { dg-error "not available to functions with variable number of arguments" } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c
index ee4121f2e3f49aed4cae7bcc0e70217cbf1bd809..3521dc61f8fb974b43f504e3f634baf27a559b0b 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c
@@ -20,9 +20,16 @@  baz (void)
   return qux ();
 }
 
+void __attribute__ ((cmse_nonsecure_call))
+quux (void) {} /* { dg-warning "attribute only applies to base type of a function pointer" } */
+
+int __attribute__ ((cmse_nonsecure_call)) norf; /* { dg-warning "attribute only applies to base type of a function pointer" } */
+
 /* { dg-final { scan-assembler-times "bxns" 2 } } */
 /* { dg-final { scan-assembler "foo:" } } */
 /* { dg-final { scan-assembler "__acle_se_foo:" } } */
 /* { dg-final { scan-assembler-not "__acle_se_bar:" } } */
 /* { dg-final { scan-assembler "baz:" } } */
 /* { dg-final { scan-assembler "__acle_se_baz:" } } */
+/* { dg-final { scan-assembler-not "__acle_se_quux:" } } */
+/* { dg-final { scan-assembler-not "__acle_se_norf:" } } */