* [RFC][PATCH, ARM 3/8] Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute
@ 2015-12-26 1:47 Thomas Preud'homme
2016-01-29 17:07 ` [PING] " Andre Vieira (lists)
0 siblings, 1 reply; 2+ messages in thread
From: Thomas Preud'homme @ 2015-12-26 1:47 UTC (permalink / raw)
To: gcc-patches
[Sending on behalf of Andre Vieira]
Hello,
This patch adds support for the ARMv8-M Security Extensions 'cmse_nonsecure_entry' attribute. In this patch we implement the attribute handling and diagnosis around the attribute. See Section 5.4 of ARM®v8-M Security Extensions (http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/index.html).
*** gcc/ChangeLog ***
2015-10-27 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc/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.
* gcc/config/arm/arm.h (ARM_FT_CMSE_ENTRY): New macro define.
(IS_CMSE_ENTRY): 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-3.c: New.
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index cf6d9466fb79e4f8a2dbfe725c52d5be8ea24fd2..f12e3c93bbe24b10ed8eee6687161826773ef649 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1375,6 +1375,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)
@@ -1383,6 +1384,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 2223101fbf96bceb4beb3a7d6cb04162481dc3bf..5b9e51b10e91eee64e3383c1ed50269c3e6cf24c 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -135,6 +135,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);
@@ -343,6 +344,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 }
};
@@ -3562,6 +3566,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;
}
@@ -6552,6 +6559,109 @@ arm_handle_notshared_attribute (tree *node,
}
#endif
+/* This function is used to check whether functions with attributes
+ cmse_nonsecure_call or cmse_nonsecure_entry use the stack to pass arguments
+ or return variables. If the function does indeed use the stack this
+ function returns true and diagnoses this, otherwise it returns false. */
+
+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;
+ 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/testsuite/gcc.target/arm/cmse/cmse-3.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..f806951e90256e8286d2d0f9467b51a73a522e2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_cmse_ok } */
+/* { 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" } */
We welcome any comment.
Cheers,
Andre
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PING] Re: [RFC][PATCH, ARM 3/8] Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute
2015-12-26 1:47 [RFC][PATCH, ARM 3/8] Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute Thomas Preud'homme
@ 2016-01-29 17:07 ` Andre Vieira (lists)
0 siblings, 0 replies; 2+ messages in thread
From: Andre Vieira (lists) @ 2016-01-29 17:07 UTC (permalink / raw)
To: gcc-patches
On 26/12/15 01:47, Thomas Preud'homme wrote:
> [Sending on behalf of Andre Vieira]
>
> Hello,
>
> This patch adds support for the ARMv8-M Security Extensions 'cmse_nonsecure_entry' attribute. In this patch we implement the attribute handling and diagnosis around the attribute. See Section 5.4 of ARM®v8-M Security Extensions (http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/index.html).
>
> *** gcc/ChangeLog ***
> 2015-10-27 Andre Vieira <andre.simoesdiasvieira@arm.com>
> Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * gcc/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.
> * gcc/config/arm/arm.h (ARM_FT_CMSE_ENTRY): New macro define.
> (IS_CMSE_ENTRY): 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-3.c: New.
>
>
> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> index cf6d9466fb79e4f8a2dbfe725c52d5be8ea24fd2..f12e3c93bbe24b10ed8eee6687161826773ef649 100644
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -1375,6 +1375,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)
> @@ -1383,6 +1384,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 2223101fbf96bceb4beb3a7d6cb04162481dc3bf..5b9e51b10e91eee64e3383c1ed50269c3e6cf24c 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -135,6 +135,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);
> @@ -343,6 +344,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 }
> };
>
>
> @@ -3562,6 +3566,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;
> }
>
> @@ -6552,6 +6559,109 @@ arm_handle_notshared_attribute (tree *node,
> }
> #endif
>
> +/* This function is used to check whether functions with attributes
> + cmse_nonsecure_call or cmse_nonsecure_entry use the stack to pass arguments
> + or return variables. If the function does indeed use the stack this
> + function returns true and diagnoses this, otherwise it returns false. */
> +
> +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;
> + 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/testsuite/gcc.target/arm/cmse/cmse-3.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..f806951e90256e8286d2d0f9467b51a73a522e2b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c
> @@ -0,0 +1,38 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target arm_cmse_ok } */
> +/* { 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" } */
>
>
> We welcome any comment.
>
> Cheers,
>
> Andre
>
Ping.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-01-29 17:07 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-26 1:47 [RFC][PATCH, ARM 3/8] Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute Thomas Preud'homme
2016-01-29 17:07 ` [PING] " Andre Vieira (lists)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).