[PING] Re: [RFC][PATCH, ARM 4/8] ARMv8-M Security Extension's cmse_nonsecure_entry: __acle_se label and bxns return
On 26/12/15 01:52, 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 in two ways: 1) Generate two labels for the function, the regular function name and one with the function's name appended to '__acle_se_', this will trigger the linker to create a secure gateway veneer for this entry function. 2) Return from cmse_nonsecure_entry marked functions using bxns. 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 VieiraThomas Preud'homme * gcc/config/arm/arm.c (use_return_insn): Change to return with bxns when cmse_nonsecure_entry. (output_return_instruction): Likewise. (arm_output_function_prologue): Likewise. (thumb_pop): Likewise. (thumb_exit): Likewise. (arm_function_ok_for_sibcall): Disable sibcall for entry functions. (arm_asm_declare_function_name): New. (thumb1_cmse_nonsecure_entry_return): New. * gcc/config/arm/arm-protos.h (arm_asm_declare_function_name): New. * gcc/config/arm/elf.h (ASM_DECLARE_FUNCTION_NAME): Redefine to use arm_asm_declare_function_name. *** gcc/testsuite/ChangeLog *** 2015-10-27 Andre Vieira Thomas Preud'homme * gcc.target/arm/cmse/cmse-2.c: New. * gcc.target/arm/cmse/cmse-4.c: New. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 85dca057d63544c672188db39b05a33b1be10915..9ee8c333046d9a5bb0487f7b710a5aff42d2 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -31,6 +31,7 @@ extern int arm_volatile_func (void); extern void arm_expand_prologue (void); extern void arm_expand_epilogue (bool); extern void arm_declare_function_name (FILE *, const char *, tree); +extern void arm_asm_declare_function_name (FILE *, const char *, tree); extern void thumb2_expand_return (bool); extern const char *arm_strip_name_encoding (const char *); extern void arm_asm_output_labelref (FILE *, const char *); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 5b9e51b10e91eee64e3383c1ed50269c3e6cf24c..e530b772e3cc053c16421a2a2861d815d53ebb01 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3795,6 +3795,11 @@ use_return_insn (int iscond, rtx sibling) return 0; } + /* ARMv8-M nonsecure entry function need to use bxns to return and thus need + several instructions if anything needs to be popped. */ + if (saved_int_regs && IS_CMSE_ENTRY (func_type)) +return 0; + /* If there are saved registers but the LR isn't saved, then we need two instructions for the return. */ if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM))) @@ -6820,6 +6825,11 @@ arm_function_ok_for_sibcall (tree decl, tree exp) if (IS_INTERRUPT (func_type)) return false; + /* ARMv8-M non-secure entry functions need to return with bxns which is only + generated for entry functions themselves. */ + if (IS_CMSE_ENTRY (arm_current_func_type ())) +return false; + if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl { /* Check that the return value locations are the same. For @@ -19607,6 +19617,7 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, (e.g. interworking) then we can load the return address directly into the PC. Otherwise we must load it into LR. */ if (really_return + && !IS_CMSE_ENTRY (func_type) && (IS_INTERRUPT (func_type) || !TARGET_INTERWORK)) return_reg = reg_names[PC_REGNUM]; else @@ -19742,8 +19753,12 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, break; default: + if (IS_CMSE_ENTRY (func_type)) + { + snprintf (instr, sizeof (instr), "bxns%s\t%%|lr", conditional); + } /* Use bx if it's available. */ - if (arm_arch5 || arm_arch4t) + else if (arm_arch5 || arm_arch4t) sprintf (instr, "bx%s\t%%|lr", conditional); else sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional); @@ -19756,6 +19771,42 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, return ""; } +/* Output in FILE asm statements needed to declare the NAME of the function + defined by its DECL node. */ + +void +arm_asm_declare_function_name (FILE *file, const char *name, tree decl) +{ + size_t cmse_name_len; + char *cmse_name = 0; + char cmse_prefix[] = "__acle_se_"; + + if (use_cmse && lookup_attribute ("cmse_nonsecure_entry", +
[RFC][PATCH, ARM 4/8] ARMv8-M Security Extension's cmse_nonsecure_entry: __acle_se label and bxns return
[Sending on behalf of Andre Vieira] Hello, This patch extends support for the ARMv8-M Security Extensions 'cmse_nonsecure_entry' attribute in two ways: 1) Generate two labels for the function, the regular function name and one with the function's name appended to '__acle_se_', this will trigger the linker to create a secure gateway veneer for this entry function. 2) Return from cmse_nonsecure_entry marked functions using bxns. 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 VieiraThomas Preud'homme * gcc/config/arm/arm.c (use_return_insn): Change to return with bxns when cmse_nonsecure_entry. (output_return_instruction): Likewise. (arm_output_function_prologue): Likewise. (thumb_pop): Likewise. (thumb_exit): Likewise. (arm_function_ok_for_sibcall): Disable sibcall for entry functions. (arm_asm_declare_function_name): New. (thumb1_cmse_nonsecure_entry_return): New. * gcc/config/arm/arm-protos.h (arm_asm_declare_function_name): New. * gcc/config/arm/elf.h (ASM_DECLARE_FUNCTION_NAME): Redefine to use arm_asm_declare_function_name. *** gcc/testsuite/ChangeLog *** 2015-10-27 Andre Vieira Thomas Preud'homme * gcc.target/arm/cmse/cmse-2.c: New. * gcc.target/arm/cmse/cmse-4.c: New. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 85dca057d63544c672188db39b05a33b1be10915..9ee8c333046d9a5bb0487f7b710a5aff42d2 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -31,6 +31,7 @@ extern int arm_volatile_func (void); extern void arm_expand_prologue (void); extern void arm_expand_epilogue (bool); extern void arm_declare_function_name (FILE *, const char *, tree); +extern void arm_asm_declare_function_name (FILE *, const char *, tree); extern void thumb2_expand_return (bool); extern const char *arm_strip_name_encoding (const char *); extern void arm_asm_output_labelref (FILE *, const char *); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 5b9e51b10e91eee64e3383c1ed50269c3e6cf24c..e530b772e3cc053c16421a2a2861d815d53ebb01 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3795,6 +3795,11 @@ use_return_insn (int iscond, rtx sibling) return 0; } + /* ARMv8-M nonsecure entry function need to use bxns to return and thus need + several instructions if anything needs to be popped. */ + if (saved_int_regs && IS_CMSE_ENTRY (func_type)) +return 0; + /* If there are saved registers but the LR isn't saved, then we need two instructions for the return. */ if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM))) @@ -6820,6 +6825,11 @@ arm_function_ok_for_sibcall (tree decl, tree exp) if (IS_INTERRUPT (func_type)) return false; + /* ARMv8-M non-secure entry functions need to return with bxns which is only + generated for entry functions themselves. */ + if (IS_CMSE_ENTRY (arm_current_func_type ())) +return false; + if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl { /* Check that the return value locations are the same. For @@ -19607,6 +19617,7 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, (e.g. interworking) then we can load the return address directly into the PC. Otherwise we must load it into LR. */ if (really_return + && !IS_CMSE_ENTRY (func_type) && (IS_INTERRUPT (func_type) || !TARGET_INTERWORK)) return_reg = reg_names[PC_REGNUM]; else @@ -19742,8 +19753,12 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, break; default: + if (IS_CMSE_ENTRY (func_type)) + { + snprintf (instr, sizeof (instr), "bxns%s\t%%|lr", conditional); + } /* Use bx if it's available. */ - if (arm_arch5 || arm_arch4t) + else if (arm_arch5 || arm_arch4t) sprintf (instr, "bx%s\t%%|lr", conditional); else sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional); @@ -19756,6 +19771,42 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, return ""; } +/* Output in FILE asm statements needed to declare the NAME of the function + defined by its DECL node. */ + +void +arm_asm_declare_function_name (FILE *file, const char *name, tree decl) +{ + size_t cmse_name_len; + char *cmse_name = 0; + char cmse_prefix[] = "__acle_se_"; + + if (use_cmse && lookup_attribute ("cmse_nonsecure_entry", + DECL_ATTRIBUTES (decl))) +{ + cmse_name_len = sizeof (cmse_prefix) + strlen