| /* SPDX-License-Identifier: GPL-2.0 */ |
| #ifndef _LINUX_LINKAGE_H |
| #define _LINUX_LINKAGE_H |
| |
| #include <linux/compiler_types.h> |
| #include <linux/stringify.h> |
| #include <linux/export.h> |
| #include <asm/linkage.h> |
| |
| /* Some toolchains use other characters (e.g. '`') to mark new line in macro */ |
| #ifndef ASM_NL |
| #define ASM_NL ; |
| #endif |
| |
| #ifdef __cplusplus |
| #define CPP_ASMLINKAGE extern "C" |
| #else |
| #define CPP_ASMLINKAGE |
| #endif |
| |
| #ifndef asmlinkage |
| #define asmlinkage CPP_ASMLINKAGE |
| #endif |
| |
| #ifndef cond_syscall |
| #define cond_syscall(x) asm( \ |
| ".weak " __stringify(x) "\n\t" \ |
| ".set " __stringify(x) "," \ |
| __stringify(sys_ni_syscall)) |
| #endif |
| |
| #ifndef SYSCALL_ALIAS |
| #define SYSCALL_ALIAS(alias, name) asm( \ |
| ".globl " __stringify(alias) "\n\t" \ |
| ".set " __stringify(alias) "," \ |
| __stringify(name)) |
| #endif |
| |
| #define __page_aligned_data __section(".data..page_aligned") __aligned(PAGE_SIZE) |
| #define __page_aligned_bss __section(".bss..page_aligned") __aligned(PAGE_SIZE) |
| |
| /* |
| * For assembly routines. |
| * |
| * Note when using these that you must specify the appropriate |
| * alignment directives yourself |
| */ |
| #define __PAGE_ALIGNED_DATA .section ".data..page_aligned", "aw" |
| #define __PAGE_ALIGNED_BSS .section ".bss..page_aligned", "aw" |
| |
| /* |
| * This is used by architectures to keep arguments on the stack |
| * untouched by the compiler by keeping them live until the end. |
| * The argument stack may be owned by the assembly-language |
| * caller, not the callee, and gcc doesn't always understand |
| * that. |
| * |
| * We have the return value, and a maximum of six arguments. |
| * |
| * This should always be followed by a "return ret" for the |
| * protection to work (ie no more work that the compiler might |
| * end up needing stack temporaries for). |
| */ |
| /* Assembly files may be compiled with -traditional .. */ |
| #ifndef __ASSEMBLY__ |
| #ifndef asmlinkage_protect |
| # define asmlinkage_protect(n, ret, args...) do { } while (0) |
| #endif |
| #endif |
| |
| #ifndef __ALIGN |
| #define __ALIGN .align 4,0x90 |
| #define __ALIGN_STR ".align 4,0x90" |
| #endif |
| |
| #ifdef __ASSEMBLY__ |
| |
| /* SYM_T_FUNC -- type used by assembler to mark functions */ |
| #ifndef SYM_T_FUNC |
| #define SYM_T_FUNC STT_FUNC |
| #endif |
| |
| /* SYM_T_OBJECT -- type used by assembler to mark data */ |
| #ifndef SYM_T_OBJECT |
| #define SYM_T_OBJECT STT_OBJECT |
| #endif |
| |
| /* SYM_T_NONE -- type used by assembler to mark entries of unknown type */ |
| #ifndef SYM_T_NONE |
| #define SYM_T_NONE STT_NOTYPE |
| #endif |
| |
| /* SYM_A_* -- align the symbol? */ |
| #define SYM_A_ALIGN ALIGN |
| #define SYM_A_NONE /* nothing */ |
| |
| /* SYM_L_* -- linkage of symbols */ |
| #define SYM_L_GLOBAL(name) .globl name |
| #define SYM_L_WEAK(name) .weak name |
| #define SYM_L_LOCAL(name) /* nothing */ |
| |
| #ifndef LINKER_SCRIPT |
| #define ALIGN __ALIGN |
| #define ALIGN_STR __ALIGN_STR |
| |
| /* === DEPRECATED annotations === */ |
| |
| #ifndef CONFIG_ARCH_USE_SYM_ANNOTATIONS |
| #ifndef GLOBAL |
| /* deprecated, use SYM_DATA*, SYM_ENTRY, or similar */ |
| #define GLOBAL(name) \ |
| .globl name ASM_NL \ |
| name: |
| #endif |
| |
| #ifndef ENTRY |
| /* deprecated, use SYM_FUNC_START */ |
| #define ENTRY(name) \ |
| SYM_FUNC_START(name) |
| #endif |
| #endif /* CONFIG_ARCH_USE_SYM_ANNOTATIONS */ |
| #endif /* LINKER_SCRIPT */ |
| |
| #ifndef CONFIG_ARCH_USE_SYM_ANNOTATIONS |
| #ifndef WEAK |
| /* deprecated, use SYM_FUNC_START_WEAK* */ |
| #define WEAK(name) \ |
| SYM_FUNC_START_WEAK(name) |
| #endif |
| |
| #ifndef END |
| /* deprecated, use SYM_FUNC_END, SYM_DATA_END, or SYM_END */ |
| #define END(name) \ |
| .size name, .-name |
| #endif |
| |
| /* If symbol 'name' is treated as a subroutine (gets called, and returns) |
| * then please use ENDPROC to mark 'name' as STT_FUNC for the benefit of |
| * static analysis tools such as stack depth analyzer. |
| */ |
| #ifndef ENDPROC |
| /* deprecated, use SYM_FUNC_END */ |
| #define ENDPROC(name) \ |
| SYM_FUNC_END(name) |
| #endif |
| #endif /* CONFIG_ARCH_USE_SYM_ANNOTATIONS */ |
| |
| /* === generic annotations === */ |
| |
| /* SYM_ENTRY -- use only if you have to for non-paired symbols */ |
| #ifndef SYM_ENTRY |
| #define SYM_ENTRY(name, linkage, align...) \ |
| linkage(name) ASM_NL \ |
| align ASM_NL \ |
| name: |
| #endif |
| |
| /* SYM_START -- use only if you have to */ |
| #ifndef SYM_START |
| #define SYM_START(name, linkage, align...) \ |
| SYM_ENTRY(name, linkage, align) |
| #endif |
| |
| /* SYM_END -- use only if you have to */ |
| #ifndef SYM_END |
| #define SYM_END(name, sym_type) \ |
| .type name sym_type ASM_NL \ |
| .size name, .-name |
| #endif |
| |
| /* === code annotations === */ |
| |
| /* |
| * FUNC -- C-like functions (proper stack frame etc.) |
| * CODE -- non-C code (e.g. irq handlers with different, special stack etc.) |
| * |
| * Objtool validates stack for FUNC, but not for CODE. |
| * Objtool generates debug info for both FUNC & CODE, but needs special |
| * annotations for each CODE's start (to describe the actual stack frame). |
| * |
| * Objtool requires that all code must be contained in an ELF symbol. Symbol |
| * names that have a .L prefix do not emit symbol table entries. .L |
| * prefixed symbols can be used within a code region, but should be avoided for |
| * denoting a range of code via ``SYM_*_START/END`` annotations. |
| * |
| * ALIAS -- does not generate debug info -- the aliased function will |
| */ |
| |
| /* SYM_INNER_LABEL_ALIGN -- only for labels in the middle of code */ |
| #ifndef SYM_INNER_LABEL_ALIGN |
| #define SYM_INNER_LABEL_ALIGN(name, linkage) \ |
| .type name SYM_T_NONE ASM_NL \ |
| SYM_ENTRY(name, linkage, SYM_A_ALIGN) |
| #endif |
| |
| /* SYM_INNER_LABEL -- only for labels in the middle of code */ |
| #ifndef SYM_INNER_LABEL |
| #define SYM_INNER_LABEL(name, linkage) \ |
| .type name SYM_T_NONE ASM_NL \ |
| SYM_ENTRY(name, linkage, SYM_A_NONE) |
| #endif |
| |
| /* |
| * SYM_FUNC_START_LOCAL_ALIAS -- use where there are two local names for one |
| * function |
| */ |
| #ifndef SYM_FUNC_START_LOCAL_ALIAS |
| #define SYM_FUNC_START_LOCAL_ALIAS(name) \ |
| SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) |
| #endif |
| |
| /* |
| * SYM_FUNC_START_ALIAS -- use where there are two global names for one |
| * function |
| */ |
| #ifndef SYM_FUNC_START_ALIAS |
| #define SYM_FUNC_START_ALIAS(name) \ |
| SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) |
| #endif |
| |
| /* SYM_FUNC_START -- use for global functions */ |
| #ifndef SYM_FUNC_START |
| /* |
| * The same as SYM_FUNC_START_ALIAS, but we will need to distinguish these two |
| * later. |
| */ |
| #define SYM_FUNC_START(name) \ |
| SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) |
| #endif |
| |
| /* SYM_FUNC_START_NOALIGN -- use for global functions, w/o alignment */ |
| #ifndef SYM_FUNC_START_NOALIGN |
| #define SYM_FUNC_START_NOALIGN(name) \ |
| SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) |
| #endif |
| |
| /* SYM_FUNC_START_LOCAL -- use for local functions */ |
| #ifndef SYM_FUNC_START_LOCAL |
| /* the same as SYM_FUNC_START_LOCAL_ALIAS, see comment near SYM_FUNC_START */ |
| #define SYM_FUNC_START_LOCAL(name) \ |
| SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) |
| #endif |
| |
| /* SYM_FUNC_START_LOCAL_NOALIGN -- use for local functions, w/o alignment */ |
| #ifndef SYM_FUNC_START_LOCAL_NOALIGN |
| #define SYM_FUNC_START_LOCAL_NOALIGN(name) \ |
| SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) |
| #endif |
| |
| /* SYM_FUNC_START_WEAK -- use for weak functions */ |
| #ifndef SYM_FUNC_START_WEAK |
| #define SYM_FUNC_START_WEAK(name) \ |
| SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) |
| #endif |
| |
| /* SYM_FUNC_START_WEAK_NOALIGN -- use for weak functions, w/o alignment */ |
| #ifndef SYM_FUNC_START_WEAK_NOALIGN |
| #define SYM_FUNC_START_WEAK_NOALIGN(name) \ |
| SYM_START(name, SYM_L_WEAK, SYM_A_NONE) |
| #endif |
| |
| /* SYM_FUNC_END_ALIAS -- the end of LOCAL_ALIASed or ALIASed function */ |
| #ifndef SYM_FUNC_END_ALIAS |
| #define SYM_FUNC_END_ALIAS(name) \ |
| SYM_END(name, SYM_T_FUNC) |
| #endif |
| |
| /* |
| * SYM_FUNC_END -- the end of SYM_FUNC_START_LOCAL, SYM_FUNC_START, |
| * SYM_FUNC_START_WEAK, ... |
| */ |
| #ifndef SYM_FUNC_END |
| /* the same as SYM_FUNC_END_ALIAS, see comment near SYM_FUNC_START */ |
| #define SYM_FUNC_END(name) \ |
| SYM_END(name, SYM_T_FUNC) |
| #endif |
| |
| /* SYM_CODE_START -- use for non-C (special) functions */ |
| #ifndef SYM_CODE_START |
| #define SYM_CODE_START(name) \ |
| SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) |
| #endif |
| |
| /* SYM_CODE_START_NOALIGN -- use for non-C (special) functions, w/o alignment */ |
| #ifndef SYM_CODE_START_NOALIGN |
| #define SYM_CODE_START_NOALIGN(name) \ |
| SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) |
| #endif |
| |
| /* SYM_CODE_START_LOCAL -- use for local non-C (special) functions */ |
| #ifndef SYM_CODE_START_LOCAL |
| #define SYM_CODE_START_LOCAL(name) \ |
| SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) |
| #endif |
| |
| /* |
| * SYM_CODE_START_LOCAL_NOALIGN -- use for local non-C (special) functions, |
| * w/o alignment |
| */ |
| #ifndef SYM_CODE_START_LOCAL_NOALIGN |
| #define SYM_CODE_START_LOCAL_NOALIGN(name) \ |
| SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) |
| #endif |
| |
| /* SYM_CODE_END -- the end of SYM_CODE_START_LOCAL, SYM_CODE_START, ... */ |
| #ifndef SYM_CODE_END |
| #define SYM_CODE_END(name) \ |
| SYM_END(name, SYM_T_NONE) |
| #endif |
| |
| /* === data annotations === */ |
| |
| /* SYM_DATA_START -- global data symbol */ |
| #ifndef SYM_DATA_START |
| #define SYM_DATA_START(name) \ |
| SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) |
| #endif |
| |
| /* SYM_DATA_START -- local data symbol */ |
| #ifndef SYM_DATA_START_LOCAL |
| #define SYM_DATA_START_LOCAL(name) \ |
| SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) |
| #endif |
| |
| /* SYM_DATA_END -- the end of SYM_DATA_START symbol */ |
| #ifndef SYM_DATA_END |
| #define SYM_DATA_END(name) \ |
| SYM_END(name, SYM_T_OBJECT) |
| #endif |
| |
| /* SYM_DATA_END_LABEL -- the labeled end of SYM_DATA_START symbol */ |
| #ifndef SYM_DATA_END_LABEL |
| #define SYM_DATA_END_LABEL(name, linkage, label) \ |
| linkage(label) ASM_NL \ |
| .type label SYM_T_OBJECT ASM_NL \ |
| label: \ |
| SYM_END(name, SYM_T_OBJECT) |
| #endif |
| |
| /* SYM_DATA -- start+end wrapper around simple global data */ |
| #ifndef SYM_DATA |
| #define SYM_DATA(name, data...) \ |
| SYM_DATA_START(name) ASM_NL \ |
| data ASM_NL \ |
| SYM_DATA_END(name) |
| #endif |
| |
| /* SYM_DATA_LOCAL -- start+end wrapper around simple local data */ |
| #ifndef SYM_DATA_LOCAL |
| #define SYM_DATA_LOCAL(name, data...) \ |
| SYM_DATA_START_LOCAL(name) ASM_NL \ |
| data ASM_NL \ |
| SYM_DATA_END(name) |
| #endif |
| |
| #endif /* __ASSEMBLY__ */ |
| |
| #endif /* _LINUX_LINKAGE_H */ |