From patchwork Mon Jul 25 13:21:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Andre Vieira (lists)" X-Patchwork-Id: 652264 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ryhjJ6bkPz9t1b for ; Mon, 25 Jul 2016 23:21:24 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Ra/dQk10; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=XWr5JGPxeTMLSwFvR XRNN5ZJtWpVIq77ZbcImIS7YrXPs7YMi34P9ANjheZIYnAXL7vt80dDgh8BDSVAK 4/smL4LRNVU9A0drY6e/smottK+a48ubZ79qNVP99DzWdYUzp/tTDCy+mTz6kSin npwRMpGAxzDnelMf7zv88iSB9E= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=QHisUKKntF5N6xgUC7EOl8l ZdZc=; b=Ra/dQk10KLEgaSwbKAkqbzDTwYiNvSdytquyM3UzLWKDX3OEJdkXwAW I8S2ybh80s5NpXO2Yv7/MqQVyhhH9JPgKFMes4tK12ENupUdAhMx4yByAKN/tOv7 UvwQ2FQ6/bkp1sbtBlRicR7bJC3oYisUE6XY75M3W1/CdAnpw87s= Received: (qmail 81147 invoked by alias); 25 Jul 2016 13:21:16 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 81088 invoked by uid 89); 25 Jul 2016 13:21:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=BAYES_00, KAM_LOTSOFHASH, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=browsing, 5.4 X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 25 Jul 2016 13:21:04 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id AE0DD28 for ; Mon, 25 Jul 2016 06:22:17 -0700 (PDT) Received: from [10.2.206.221] (e107157-lin.cambridge.arm.com [10.2.206.221]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B74C03F21A for ; Mon, 25 Jul 2016 06:21:02 -0700 (PDT) Subject: [PATCH 2/7, GCC, ARM, V8M] Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute To: gcc-patches@gcc.gnu.org References: <5796116C.6010100@arm.com> From: "Andre Vieira (lists)" Message-ID: <5796123D.6020702@arm.com> Date: Mon, 25 Jul 2016 14:21:01 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 In-Reply-To: <5796116C.6010100@arm.com> X-IsSubscribed: yes 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 *** 2016-07-25 Andre Vieira Thomas Preud'homme * 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. *** gcc/testsuite/ChangeLog *** 2016-07-25 Andre Vieira Thomas Preud'homme * gcc.target/arm/cmse/cmse-3.c: New. diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index e3697bbcb425999db31ac2b4f47e14bb3f2ffa89..5307ec8f904230db5ea44150ef471d928926ab6d 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1373,6 +1373,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) @@ -1381,6 +1382,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 9903d9cd8c5ff68a2318a643bdf31cf48016eba4..11417ab3c2f7101866ee5d6b100913480e5c336e 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -134,6 +134,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 } }; @@ -3633,6 +3637,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; } @@ -6634,6 +6641,110 @@ arm_handle_notshared_attribute (tree *node, } #endif +/* This function returns true if a function with declaration FNDECL, name + NAME 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. */ + +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..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" } */