x86: macrofying inline asm
Subsystems (64)
v9 cover x86: macrofying inline asm
This patch-set deals with an interesting yet stupid problem: kernel code that does not get inlined despite its simplicity. There are several causes for this behavior: "cold" attribute on __init, different function optimization levels; conditional constant computations based on __builtin_constant_p(); and finally large inline assembly blocks.
This patch-set deals with the inline assembly problem. I separated these patches from the others (that were sent in the RFC) for easier inclusion. I also separated the removal of unnecessary new-lines which would be sent separately.
The problem with inline assembly is that inline assembly is often used by the kernel for things that are other than code - for example, assembly directives and data. GCC however is oblivious to the content of the blocks and assumes their cost in space and time is proportional to the number of the perceived assembly "instruction", according to the number of newlines and semicolons. Alternatives, paravirt and other mechanisms are affected, causing code not to be inlined, and degrading compilation quality in general.
The solution that this patch-set carries for this problem is to create an assembly macro, and then call it from the inline assembly block. As a result, the compiler sees a single "instruction" and assigns the more appropriate cost to the code.
To avoid uglification of the code, as many noted, the macros are first precompiled into an assembly file, which is later assembled together with the C files. This also enables to avoid duplicate implementation that was set before for the asm and C code. This can be seen in the exception table changes.
Overall this patch-set slightly increases the kernel size (my build was done using my Ubuntu 18.04 config + localyesconfig for the record):
text data bss dec hex filename
18140829 10224724 2957312 31322865 1ddf2f1 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+0.1%)
The number of static functions in the image is reduced by 379, but actually inlining is even better, which does not always shows in these
numbers: a function may be inlined causing the calling function not to be inlined.
I ran some limited number of benchmarks, and in general the performance impact is not very notable. You can still see >10 cycles shaved off some syscalls that manipulate page-tables (e.g., mprotect()), in which paravirt caused many functions not to be inlined. In addition this patch-set can prevent issues such as [1], and improves code readability and maintainability.
Update: Rasmus recently caused me (inadvertently) to become paranoid about the dependencies. To clarify: if any of the headers changes, any c file which uses macros that are included in macros.S would be fine as long as it includes the header as well (as it should). Adding an assertion to check this is done might become slightly ugly, and nobody else is concerned about it. Another minor issue is that changes of macros.S would not trigger a global rebuild, but that is pretty similar to changes of the Makefile that do not trigger a rebuild.
[1] https://patchwork.kernel.org/patch/10450037/
v8->v9: * Restoring the '-pipe' parameter (Rasmus)
* Adding Kees's tested-by tag (Kees)
v7->v8: * Add acks (Masahiro, Max)
* Rebase on 4.19 (Ingo)
v6->v7: * Fix context switch tracking (Ingo)
* Fix xtensa build error (Ingo)
* Rebase on 4.18-rc8
v5->v6: * Removing more code from jump-labels (PeterZ)
* Fix build issue on i386 (0-day, PeterZ)
v4->v5: * Makefile fixes (Masahiro, Sam)
v3->v4: * Changed naming of macros in 2 patches (PeterZ)
* Minor cleanup of the paravirt patch
v2->v3: * Several build issues resolved (0-day)
* Wrong comments fix (Josh)
* Change asm vs C order in refcount (Kees)
v1->v2: * Compiling the macros into a separate .s file, improving
readability (Linus)
* Improving assembly formatting, applying most of the comments according to my judgment (Jan)
* Adding exception-table, cpufeature and jump-labels
* Removing new-line cleanup; to be submitted separately
Nadav Amit (10):
xtensa: defining LINKER_SCRIPT for the linker script
Makefile: Prepare for using macros for inline asm
x86: objtool: use asm macro for better compiler decisions
x86: refcount: prevent gcc distortions
x86: alternatives: macrofy locks for better inlining
x86: bug: prevent gcc distortions
x86: prevent inline distortion by paravirt ops
x86: extable: use macros instead of inline assembly
x86: cpufeature: use macros instead of inline assembly
x86: jump-labels: use macros instead of inline assembly
Makefile | 9 ++- arch/x86/Makefile | 7 ++ arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/alternative-asm.h | 20 ++++-- arch/x86/include/asm/alternative.h | 11 +-- arch/x86/include/asm/asm.h | 61 +++++++--------- arch/x86/include/asm/bug.h | 98 +++++++++++++++----------- arch/x86/include/asm/cpufeature.h | 82 ++++++++++++--------- arch/x86/include/asm/jump_label.h | 77 ++++++++------------ arch/x86/include/asm/paravirt_types.h | 56 +++++++-------- arch/x86/include/asm/refcount.h | 74 +++++++++++-------- arch/x86/kernel/macros.S | 16 +++++ arch/xtensa/kernel/Makefile | 4 +- include/asm-generic/bug.h | 8 +-- include/linux/compiler.h | 56 +++++++++++---- scripts/Kbuild.include | 4 +- scripts/mod/Makefile | 2 + 17 files changed, 331 insertions(+), 256 deletions(-) create mode 100644 arch/x86/kernel/macros.S
Signature · 1 line
2.17.1
PATCH v9 1/10 xtensa: defining LINKER_SCRIPT for the linker script
Defining the LINKER_SCRIPT when building the linker script as being done in other architectures. This is required for the next Makefile changes would otherwise break things.
--- arch/xtensa/kernel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/xtensa/kernel/Makefile +2 -2
@@ -35,8 +35,8 @@ sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unl -e 's/\.{text}/.text/g' quiet_cmd__cpp_lds_S = LDS $@ -cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \ - | sed $(sed-y) >$@ +cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ \ + -DLINKER_SCRIPT $< | sed $(sed-y) >$@ $(obj)/vmlinux.lds: $(src)/vmlinux.lds.S FORCE $(call if_changed_dep,_cpp_lds_S)
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] kbuild/arch/xtensa: Define LINKER_SCRIPT for the linker script
kbuild/arch/xtensa: Define LINKER_SCRIPT for the linker script
Commit-ID: 35e76b99ddf20405a6196bb7c9eb152675c93106 Gitweb: https://git.kernel.org/tip/35e76b99ddf20405a6196bb7c9eb152675c93106 Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:51 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 10:05:38 +0200
kbuild/arch/xtensa: Define LINKER_SCRIPT for the linker script
Define the LINKER_SCRIPT when building the linker script as being done in other architectures. This is required, because upcoming Makefile changes would otherwise break things.
--- arch/xtensa/kernel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/xtensa/kernel/Makefile +2 -2
@@ -35,8 +35,8 @@ sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unl -e 's/\.{text}/.text/g' quiet_cmd__cpp_lds_S = LDS $@ -cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \ - | sed $(sed-y) >$@ +cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ \ + -DLINKER_SCRIPT $< | sed $(sed-y) >$@ $(obj)/vmlinux.lds: $(src)/vmlinux.lds.S FORCE $(call if_changed_dep,_cpp_lds_S)
PATCH v9 2/10 Makefile: Prepare for using macros for inline asm
In reply to Nadav AmitUsing macros for inline assembly improves both readability and compilation decisions that are distorted by big assembly blocks that use alternative sections. Compile macros.S and use it to assemble all C files. Currently, only x86 will use it.
--- Makefile | 9 +++++++-- arch/x86/Makefile | 7 +++++++ arch/x86/kernel/macros.S | 7 +++++++ scripts/Kbuild.include | 4 +++- scripts/mod/Makefile | 2 ++ 5 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 arch/x86/kernel/macros.S
Makefile +7 -2
@@ -1071,7 +1071,7 @@ scripts: scripts_basic asm-generic gcc-plugins $(autoksyms_h) # version.h and scripts_basic is processed / created. # Listed in dependency order -PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3 +PHONY += prepare archprepare macroprepare prepare0 prepare1 prepare2 prepare3 # prepare3 is used to check if we are building in a separate output directory, # and if so do:
@@ -1094,7 +1094,9 @@ prepare2: prepare3 outputmakefile asm-generic prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h $(cmd_crmodverdir) -archprepare: archheaders archscripts prepare1 scripts_basic +macroprepare: prepare1 archmacros + +archprepare: archheaders archscripts macroprepare scripts_basic prepare0: archprepare gcc-plugins $(Q)$(MAKE) $(build)=.
@@ -1162,6 +1164,9 @@ archheaders: PHONY += archscripts archscripts: +PHONY += archmacros +archmacros: + PHONY += __headers __headers: $(version_h) scripts_basic uapi-asm-generic archheaders archscripts $(Q)$(MAKE) $(build)=scripts build_unifdef
arch/x86/Makefile +7 -0
@@ -237,6 +237,13 @@ archscripts: scripts_basic archheaders: $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all +archmacros: + $(Q)$(MAKE) $(build)=arch/x86/kernel arch/x86/kernel/macros.s + +ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s -Wa,- +export ASM_MACRO_FLAGS +KBUILD_CFLAGS += $(ASM_MACRO_FLAGS) + ### # Kernel objects
arch/x86/kernel/macros.S new file +7 -0
@@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * This file includes headers whose assembly part includes macros which are + * commonly used. The macros are precompiled into assmebly file which is later + * assembled together with each compiled file. + */
scripts/Kbuild.include +3 -1
@@ -115,7 +115,9 @@ __cc-option = $(call try-run,\ # Do not attempt to build with gcc plugins during cc-option tests. # (And this uses delayed resolution so the flags will be up to date.) -CC_OPTION_CFLAGS = $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) +# In addition, do not include the asm macros which are built later. +CC_OPTION_FILTERED = $(GCC_PLUGINS_CFLAGS) $(ASM_MACRO_FLAGS) +CC_OPTION_CFLAGS = $(filter-out $(CC_OPTION_FILTERED),$(KBUILD_CFLAGS)) # cc-option # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
scripts/mod/Makefile +2 -0
@@ -4,6 +4,8 @@ OBJECT_FILES_NON_STANDARD := y hostprogs-y := modpost mk_elfconfig always := $(hostprogs-y) empty.o +CFLAGS_REMOVE_empty.o := $(ASM_MACRO_FLAGS) + modpost-objs := modpost.o file2alias.o sumversion.o devicetable-offsets-file := devicetable-offsets.h
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs
kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs
Commit-ID: 77b0bf55bc675233d22cd5df97605d516d64525e Gitweb: https://git.kernel.org/tip/77b0bf55bc675233d22cd5df97605d516d64525e Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:52 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 10:57:09 +0200
kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs
Using macros in inline assembly allows us to work around bugs in GCC's inlining decisions.
Compile macros.S and use it to assemble all C files. Currently only x86 will use it.
Background:
The inlining pass of GCC doesn't include an assembler, so it's not aware of basic properties of the generated code, such as its size in bytes, or that there are such things as discontiuous blocks of code and data due to the newfangled linker feature called 'sections' ...
Instead GCC uses a lazy and fragile heuristic: it does a linear count of certain syntactic and whitespace elements in inlined assembly block source code, such as a count of new-lines and semicolons (!), as a poor substitute for "code size and complexity".
Unsurprisingly this heuristic falls over and breaks its neck whith certain common types of kernel code that use inline assembly, such as the frequent practice of putting useful information into alternative sections.
As a result of this fresh, 20+ years old GCC bug, GCC's inlining decisions are effectively disabled for inlined functions that make use of such asm() blocks, because GCC thinks those sections of code are "large" - when in reality they are often result in just a very low number of machine instructions.
This absolute lack of inlining provess when GCC comes across such asm() blocks both increases generated kernel code size and causes performance overhead, which is particularly noticeable on paravirt kernels, which make frequent use of these inlining facilities in attempt to stay out of the way when running on baremetal hardware.
Instead of fixing the compiler we use a workaround: we set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction. (Which it often isn't but I digress.)
This uglifies and bloats the source code - for example just the refcount related changes have this impact:
Makefile | 9 +++++++-- arch/x86/Makefile | 7 +++++++ arch/x86/kernel/macros.S | 7 +++++++ scripts/Kbuild.include | 4 +++- scripts/mod/Makefile | 2 ++ 5 files changed, 26 insertions(+), 3 deletions(-)
Yay readability and maintainability, it's not like assembly code is hard to read and maintain ...
We also hope that GCC will eventually get fixed, but we are not holding our breath for that. Yet we are optimistic, it might still happen, any decade now.
[ mingo: Wrote new changelog describing the background. ]
--- Makefile | 9 +++++++-- arch/x86/Makefile | 7 +++++++ arch/x86/kernel/macros.S | 7 +++++++ scripts/Kbuild.include | 4 +++- scripts/mod/Makefile | 2 ++ 5 files changed, 26 insertions(+), 3 deletions(-)
Makefile +7 -2
@@ -1071,7 +1071,7 @@ scripts: scripts_basic asm-generic gcc-plugins $(autoksyms_h) # version.h and scripts_basic is processed / created. # Listed in dependency order -PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3 +PHONY += prepare archprepare macroprepare prepare0 prepare1 prepare2 prepare3 # prepare3 is used to check if we are building in a separate output directory, # and if so do:
@@ -1094,7 +1094,9 @@ prepare2: prepare3 outputmakefile asm-generic prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h $(cmd_crmodverdir) -archprepare: archheaders archscripts prepare1 scripts_basic +macroprepare: prepare1 archmacros + +archprepare: archheaders archscripts macroprepare scripts_basic prepare0: archprepare gcc-plugins $(Q)$(MAKE) $(build)=.
@@ -1162,6 +1164,9 @@ archheaders: PHONY += archscripts archscripts: +PHONY += archmacros +archmacros: + PHONY += __headers __headers: $(version_h) scripts_basic uapi-asm-generic archheaders archscripts $(Q)$(MAKE) $(build)=scripts build_unifdef
arch/x86/Makefile +7 -0
@@ -236,6 +236,13 @@ archscripts: scripts_basic archheaders: $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all +archmacros: + $(Q)$(MAKE) $(build)=arch/x86/kernel arch/x86/kernel/macros.s + +ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s -Wa,- +export ASM_MACRO_FLAGS +KBUILD_CFLAGS += $(ASM_MACRO_FLAGS) + ### # Kernel objects
arch/x86/kernel/macros.S new file +7 -0
@@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * This file includes headers whose assembly part includes macros which are + * commonly used. The macros are precompiled into assmebly file which is later + * assembled together with each compiled file. + */
scripts/Kbuild.include +3 -1
@@ -115,7 +115,9 @@ __cc-option = $(call try-run,\ # Do not attempt to build with gcc plugins during cc-option tests. # (And this uses delayed resolution so the flags will be up to date.) -CC_OPTION_CFLAGS = $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) +# In addition, do not include the asm macros which are built later. +CC_OPTION_FILTERED = $(GCC_PLUGINS_CFLAGS) $(ASM_MACRO_FLAGS) +CC_OPTION_CFLAGS = $(filter-out $(CC_OPTION_FILTERED),$(KBUILD_CFLAGS)) # cc-option # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
scripts/mod/Makefile +2 -0
@@ -4,6 +4,8 @@ OBJECT_FILES_NON_STANDARD := y hostprogs-y := modpost mk_elfconfig always := $(hostprogs-y) empty.o +CFLAGS_REMOVE_empty.o := $(ASM_MACRO_FLAGS) + modpost-objs := modpost.o file2alias.o sumversion.o devicetable-offsets-file := devicetable-offsets.h
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
In reply to Nadav Amitarch/x86/Makefile archscripts: scripts_basic · line 245
Quoted 3 lines · Nadav Amit
arch/x86/Makefile +3
-0+ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s -Wa,- +export ASM_MACRO_FLAGS +KBUILD_CFLAGS += $(ASM_MACRO_FLAGS)
I'm not sure how much we care about this or what we can do about it, but adding the macros.s to the command line like this has effectively broken distributed compiling with distcc and icecc as of v4.20-rc1. Neither tool will successfully distribute any compile processes because the non-local machines won't have a copy of macros.s.
Thanks,
Logan
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: Logan Gunthorpe
Sent: November 6, 2018 at 6:57:57 PM GMT
Quoted 8 lines
To: Nadav Amit <[email protected]>, Ingo Molnar <[email protected]>
Cc: [email protected]>, [email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, H. Peter Anvin <[email protected]>, [email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmOn 2018-10-03 3:30 p.m., Nadav Amit wrote:
Quoted 9 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s -Wa,- +export ASM_MACRO_FLAGS +KBUILD_CFLAGS += $(ASM_MACRO_FLAGS)I'm not sure how much we care about this or what we can do about it, but adding the macros.s to the command line like this has effectively broken distributed compiling with distcc and icecc as of v4.20-rc1. Neither tool will successfully distribute any compile processes because the non-local machines won't have a copy of macros.s.
Err.. I don’t have a dist-cc environment. I wonder whether something like that would do the trick:
-- >8 —
Subject: [PATCH] x86: Fix dist-cc
--- arch/x86/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/Makefile +2 -2
@@ -237,9 +237,9 @@ archheaders: $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all archmacros: - $(Q)$(MAKE) $(build)=arch/x86/kernel arch/x86/kernel/macros.s + $(Q)$(MAKE) $(build)=arch/x86/kernel ${objtree}/arch/x86/kernel/macros.s -ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s -Wa,- +ASM_MACRO_FLAGS = -Wa,${objtree}/arch/x86/kernel/macros.s -Wa,- export ASM_MACRO_FLAGS KBUILD_CFLAGS += $(ASM_MACRO_FLAGS)
Signature · 1 line
2.17.1
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 2 lines · Nadav Amit
Err.. I don’t have a dist-cc environment. I wonder whether something like that would do the trick:
I tested it to be sure -- but, no, this does not have any affect on distcc. Distcc usually does pre-processing locally and then sends the single output of cpp to a remote for compilation and assembly. It doesn't expect there to be additional assembly files tacked on the command line and isn't going to handle that case correctly. Thus, changing the path of the file won't fix anything.
Logan
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: Logan Gunthorpe
Sent: November 6, 2018 at 8:01:31 PM GMT
Quoted 11 lines
To: Nadav Amit <[email protected]>, Ingo Molnar <[email protected]>
Cc: LKML <[email protected]>, X86 ML <[email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, H. Peter Anvin <[email protected]>, LinuxKbuildmailing list <[email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmQuoted 2 lines · Nadav Amit
Err.. I don’t have a dist-cc environment. I wonder whether something like that would do the trick:
Quoted 6 lines
I tested it to be sure -- but, no, this does not have any affect on distcc. Distcc usually does pre-processing locally and then sends the single output of cpp to a remote for compilation and assembly. It doesn't expect there to be additional assembly files tacked on the command line and isn't going to handle that case correctly. Thus, changing the path of the file won't fix anything.
Thanks for the explanation.
I played with dist-cc and gave it some thought, but I do not have a solution. I thought that perhaps some hack is possible by using the same preprocessed file can be used as both the source file and the assembly file, but that’s as far as I managed to get.
Ideas? Do people care about it?
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 1 line · Nadav Amit
Ideas? Do people care about it?
Just spit balling, but is there a reason we didn't just put the macros for inline assembly directly in the header? Something like this:
asm(".macro ANNOTATE_UNREACHABLE counter:req\n\t"
"\\counter:\n\t"
".pushsection .discard.unreachable\n\t"
".long \\counter\\()b -.\n\t"
".popsection\n\t"
".endm\n");#define annotate_unreachable() ({ \
asm volatile("ANNOTATE_UNREACHABLE counter=%c0" \
: : "i" (__COUNTER__)); \
})It does mean the macros won't be usable in non-inline assembly, without duplicating them, but do we care about that?
I would have expected people compiling the kernel with distcc to be fairly common -- it certainly speeds up my kernel compiles quite significantly and thus saves me a lot of time.
Logan
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: Logan Gunthorpe
Sent: November 7, 2018 at 6:53:02 PM GMT
Quoted 18 lines
Subject: Re: [PATCH v9 02/10]
Makefile: Prepare for using macros for inline asmQuoted 1 line · Nadav Amit
Ideas? Do people care about it?
Just spit balling, but is there a reason we didn't just put the macros for inline assembly directly in the header? Something like this:
asm(".macro
ANNOTATE_UNREACHABLEcounter:req\n\t"
"\\counter:\n\t"".pushsection .discard.unreachable\n\t" ".long \\counter\\()b -.\n\t" ".popsection\n\t"".endm\n");
Quoted 7 lines
#define annotate_unreachable() ({ \ asm volatile("ANNOTATE_UNREACHABLE counter=%c0" \ : : "i" (__COUNTER__)); \ })It does mean the macros won't be usable in non-inline assembly, without duplicating them, but do we care about that?
HPA indicated more than once that this is wrong (and that was indeed my initial solution), since it is not guaranteed that the compiler would put the macro assembly before its use.
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 3 lines · Nadav Amit
HPA indicated more than once that this is wrong (and that was indeed my initial solution), since it is not guaranteed that the compiler would put the macro assembly before its use.
Hmm, that's very unfortunate. I don't really understand why the compiler would not put the macro assembly in the same order as it appears in the code and it would be in the correct order there.
In any case, I've submitted a couple of issues to icecc[1] and distcc[2] to see if they have any ideas about supporting this on their sides.
Thanks,
Logan
[1] https://github.com/icecc/icecream/issues/428
[2] https://github.com/distcc/distcc/issues/312
[email protected]
reviewerRe: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 18 lines · Logan Gunthorpe
Quoted 1 line · Nadav Amit
HPA indicated more than once that this is wrong (and that was indeed
my
Quoted 1 line
initial solution), since it is not guaranteed that the compiler would
put
Quoted 1 line
the macro assembly before its use.
Hmm, that's very unfortunate. I don't really understand why the compiler
would not put the macro assembly in the same order as it appears in the code and it would be in the correct order there.In any case, I've submitted a couple of issues to icecc[1] and distcc[2]
to see if they have any ideas about supporting this on their sides.
Quoted 6 lines
Thanks,
Logan
[1] https://github.com/icecc/icecream/issues/428
[2] https://github.com/distcc/distcc/issues/312
Apparently gcc will treat them like basic blocks and possibly move them around.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: [email protected]
Sent: November 7, 2018 at 9:50:28 PM GMT
Quoted 22 lines
To: Logan Gunthorpe <[email protected]>, Nadav Amit <[email protected]>, Ingo Molnar <[email protected]>
Cc: LKML <[email protected]>, X86 ML <[email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, LinuxKbuildmailing list <[email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmQuoted 16 lines · Logan Gunthorpe
Quoted 1 line · Nadav Amit
HPA indicated more than once that this is wrong (and that was indeed
my
Quoted 1 line
initial solution), since it is not guaranteed that the compiler would
put
Quoted 1 line
the macro assembly before its use.
Hmm, that's very unfortunate. I don't really understand why the compiler
would not put the macro assembly in the same order as it appears in the code and it would be in the correct order there.In any case, I've submitted a couple of issues to icecc[1] and distcc[2]
to see if they have any ideas about supporting this on their sides.
Quoted 8 lines
Quoted 6 lines
Thanks,
Logan
[1] https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ficecc%2Ficecream%2Fissues%2F428&data=02%7C01%7Cnamit%40vmware.com%7C30ab3751343b49f869ab08d644fb1d8c%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636772242666772528&sdata=dXKTR79LkFDQ9IXxYw9XYt0VPFa4MXrMUcc86w5uy%2Fk%3D&reserved=0
[2] https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fdistcc%2Fdistcc%2Fissues%2F312&data=02%7C01%7Cnamit%40vmware.com%7C30ab3751343b49f869ab08d644fb1d8c%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636772242666772528&sdata=XynZ1bFbKAb8V2eoPQbXudEJ%2B%2Bu8QA3mM4Sr4E%2FTzWs%3D&reserved=0Apparently gcc will treat them like basic blocks and possibly move them around.
Maybe it is possible to break the compilation of each object into two
stages: first, compile the source without assembly, and then take the generated .s file and assemble it with the .s file of the macros.
Does it sounds as something that may work? I guess it should only be done when distcc is used.
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 8 lines · Nadav Amit
Quoted 1 line
Apparently gcc will treat them like basic blocks and possibly move them around.
Maybe it is possible to break the compilation of each object into two
stages: first, compile the source without assembly, and then take the generated .s file and assemble it with the .s file of the macros.Does it sounds as something that may work? I guess it should only be done when distcc is used.
In theory it would at least allow the compile step to be distributed, the assembly step would still have to be done locally... It'd be better than nothing, I guess.
It'd also be difficult to know when distribution is being done and that it's necessary to split the steps. We'd have to add an environment variable or something and users would need to know they have to set it when using a distributed compile.
Logan
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: Logan Gunthorpe
Sent: November 8, 2018 at 5:14:58 PM GMT
Quoted 14 lines
To: Nadav Amit <[email protected]>, [email protected] <[email protected]>, Ingo Molnar <[email protected]>
Cc: LKML <[email protected]>, X86 ML <[email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, LinuxKbuildmailing list <[email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmQuoted 6 lines · Nadav Amit
Quoted 1 line
Apparently gcc will treat them like basic blocks and possibly move them around.
Maybe it is possible to break the compilation of each object into two
stages: first, compile the source without assembly, and then take the generated .s file and assemble it with the .s file of the macros.
Quoted 6 lines
Quoted 2 lines
Does it sounds as something that may work? I guess it should only be done when distcc is used.
In theory it would at least allow the compile step to be distributed, the assembly step would still have to be done locally... It'd be better than nothing, I guess.
I don’t think the assembly stage needs to be done locally. gcc can still be used to deploy the assembler. I am not too familiar with distcc, so I don’t know whether the preprocessing supports multiple source-files, and whether it has some strange-behavior when it comes to .S/.s files.
Well, I’ll give it a try.
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 4 lines · Nadav Amit
I don’t think the assembly stage needs to be done locally. gcc can still be used to deploy the assembler. I am not too familiar with distcc, so I don’t know whether the preprocessing supports multiple source-files, and whether it has some strange-behavior when it comes to .S/.s files.
The problem is that it's the assembly stage that needs the extra macros.s and without that file being transferred somehow, that stage must be done locally.
The distcc guys have a thought that the macros.s file might be able to be transferred using pump mode with a change to include_server.py. I don't think that will work for icecc though.
Logan
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: Logan Gunthorpe
Sent: November 8, 2018 at 8:00:33 PM GMT
Quoted 8 lines
To: Nadav Amit <[email protected]>, [email protected] <[email protected]>, Ingo Molnar <[email protected]>
Cc: LKML <[email protected]>, X86 ML <[email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, LinuxKbuildmailing list <[email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmOn 2018-11-08 12:54 p.m., Nadav Amit wrote:
Quoted 8 lines
Quoted 4 lines
I don’t think the assembly stage needs to be done locally. gcc can still be used to deploy the assembler. I am not too familiar with distcc, so I don’t know whether the preprocessing supports multiple source-files, and whether it has some strange-behavior when it comes to .S/.s files.
The problem is that it's the assembly stage that needs the extra macros.s and without that file being transferred somehow, that stage must be done locally.
I understand, but the idea is to have two stages, for instance:
gcc ... -S -o .tmp_[unit].S [unit].c
and then
gcc ... -D__ASSEMBLY__ arch/x86/kernel/macros.S .tmp_[unit].S
(Yes, I realize the .tmp_[unit].S was already preprocessed, but this way you can combine both inputs)
Unfortunately, as I write this email (and run tests) I realize distcc is too dumb to handle two input files:
"(dcc_scan_args) do we have two inputs? i give up "
Just great. So I guess macros.s would need to be concatenated with .tmp_[unit].s as a separate (local) interim stage.
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
From: Nadav Amit
Sent: November 8, 2018 at 8:18:23 PM GMT
Quoted 35 lines
To: Logan Gunthorpe <[email protected]>, [email protected] <[email protected]>, Ingo Molnar <[email protected]>
Cc: LKML <[email protected]>, X86 ML <[email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, LinuxKbuildmailing list <[email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmFrom: Logan Gunthorpe
Sent: November 8, 2018 at 8:00:33 PM GMTQuoted 8 lines
To: Nadav Amit <[email protected]>, [email protected] <[email protected]>, Ingo Molnar <[email protected]>
Cc: LKML <[email protected]>, X86 ML <[email protected]>, Sam Ravnborg <[email protected]>, Michal Marek <[email protected]>, Thomas Gleixner <[email protected]>, LinuxKbuildmailing list <[email protected]>, Stephen Bates <[email protected]>
Subject: Re: [PATCH v9 02/10]Makefile: Prepare for using macros for inline asmOn 2018-11-08 12:54 p.m., Nadav Amit wrote:
Quoted 8 lines
Quoted 4 lines
I don’t think the assembly stage needs to be done locally. gcc can still be used to deploy the assembler. I am not too familiar with distcc, so I don’t know whether the preprocessing supports multiple source-files, and whether it has some strange-behavior when it comes to .S/.s files.
The problem is that it's the assembly stage that needs the extra macros.s and without that file being transferred somehow, that stage must be done locally.
I understand, but the idea is to have two stages, for instance:
gcc ... -S -o .tmp_[unit].S [unit].c
and then
gcc ... -D__ASSEMBLY__
arch/x86/kernel/macros.S.tmp_[unit].S(Yes, I realize the .tmp_[unit].S was already preprocessed, but this way you can combine both inputs)
Quoted 7 lines
Unfortunately, as I write this email (and run tests) I realize distcc is too dumb to handle two input files:
"(
dcc_scan_args) do we have two inputs? i give up "Just great. So I guess macros.s would need to be concatenated with .tmp_[unit].s as a separate (local) interim stage.
Err.. I hate makefiles and distcc doesn’t make life easier. For instance, if it sees two source files on the command-line, it freaks out and compiles it locally. It also has an option to distribute assembly, but it is not enabled by default.
Anyhow, can you try the following patch?
-- >8 --
Subject: [PATCH] Makefile: Fix distcc compilation with x86 macros
Introducing the use of asm macros in c-code broke distcc, since it only sends the preprocessed source file. The solution is to break the compilation into two separate phases of compilation and assembly, and between the two concatanate the assembly macros and the compiled (yet not assembled) source file. Since this is less efficient, this compilation mode is only used when make is called with the "DISTCC=y" parameter.
Note that the assembly stage should also be distributable, if distcc is configured using "CFLAGS=-DENABLE_REMOTE_ASSEMBLE".
--- Makefile | 4 +++- arch/x86/Makefile | 4 +++- scripts/Makefile.build | 29 +++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 4 deletions(-)
Makefile +3 -1
@@ -743,7 +743,9 @@ KBUILD_CFLAGS += $(call cc-option, -gsplit-dwarf, -g) else KBUILD_CFLAGS += -g endif -KBUILD_AFLAGS += -Wa,-gdwarf-2 +AFLAGS_DEBUG_INFO = -Wa,-gdwarf-2 +export AFLAGS_DEBUG_INFO +KBUILD_AFLAGS += $(AFLAGS_DEBUG_INFO) endif ifdef CONFIG_DEBUG_INFO_DWARF4 KBUILD_CFLAGS += $(call cc-option, -gdwarf-4,)
arch/x86/Makefile +3 -1
@@ -238,7 +238,9 @@ archheaders: archmacros: $(Q)$(MAKE) $(build)=arch/x86/kernel arch/x86/kernel/macros.s -ASM_MACRO_FLAGS = -Wa,arch/x86/kernel/macros.s +ASM_MACRO_FILE = arch/x86/kernel/macros.s +export ASM_MACRO_FILE +ASM_MACRO_FLAGS = -Wa,$(ASM_MACRO_FILE) export ASM_MACRO_FLAGS KBUILD_CFLAGS += $(ASM_MACRO_FLAGS)
scripts/Makefile.build +27 -2
@@ -155,8 +155,33 @@ $(obj)/%.ll: $(src)/%.c FORCE quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ +# If distcc is used, then when an assembly macro files is needed, the +# compilation stage and the assembly stage need to be separated. Providing +# "DISTCC=y" option enables the separate compilation and assembly. +cmd_cc_o_c_simple = $(CC) $(c_flags) -c -o $(1) $< + +ifeq ($(DISTCC),y) +a_flags_no_debug = $(filter-out $(AFLAGS_DEBUG_INFO), $(a_flags)) +c_flags_no_macros = $(filter-out $(ASM_MACRO_FLAGS), $(c_flags)) + +cmd_cc_o_c_two_steps = \ + $(CC) $(c_flags_no_macros) $(DISABLE_LTO) -fverbose-asm -S \ + -o $(@D)/.$(@F:.o=.s) $< ; \ + cat $(ASM_MACRO_FILE) $(@D)/.$(@F:.o=.s) > \ + $(@D)/.tmp_$(@F:.o=.s); \ + $(CC) $(a_flags_no_debug) -c -o $(1) $(@D)/.tmp_$(@F:.o=.s) ; \ + rm -f $(@D)/.$(@F:.o=.s) $(@D)/.tmp_$(@F:.o=.s) \ + +cmd_cc_o_c_helper = \ + $(if $(findstring $(ASM_MACRO_FLAGS),$(c_flags)), \ + $(call cmd_cc_o_c_two_steps, $(1)), \ + $(call cmd_cc_o_c_simple, $(1))) +else +cmd_cc_o_c_helper = $(call cmd_cc_o_c_simple, $(1)) +endif + ifndef CONFIG_MODVERSIONS -cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +cmd_cc_o_c = $(call cmd_cc_o_c_helper,$@) else # When module versioning is enabled the following steps are executed:
@@ -171,7 +196,7 @@ else # replace the unresolved symbols __crc_exported_symbol with # the actual value of the checksum generated by genksyms -cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< +cmd_cc_o_c = $(call cmd_cc_o_c_helper,$(@D)/.tmp_$(@F)) cmd_modversions_c = \ if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
Signature · 1 line
2.17.1
Re: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Quoted 6 lines · Nadav Amit
Err.. I hate makefiles and distcc doesn’t make life easier. For instance, if it sees two source files on the command-line, it freaks out and compiles it locally. It also has an option to distribute assembly, but it is not enabled by default.
Anyhow, can you try the following patch?
Very nice, great work! It works as expected. I tested with both distcc and icecc and both work well with DISTCC=y.
Also worth noting, is that distcc has a patch to work without DISTCC=y in pump mode (though pump mode doesn't work super great with the kernel as some of the include processing takes a long time). When I have some free time, I may also try to patch icecc to work with it, as in my experience, it performs better.
Regardless, I think your patch would be very valuable to be in upstream so there's at least some way to use the existing versions of distcc and icecc.
Thanks!
Logan
PATCH v9 3/10 x86: objtool: use asm macro for better compiler decisions
In reply to Nadav AmitGCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
In the case of objtool, this distortion is extreme, since anyhow the annotations of objtool are discarded during linkage.
The solution is to set an assembly macro and call it from the inline assembly block. As a result GCC considers the inline assembly block as a single instruction.
This patch slightly increases the kernel size.
text data bss dec hex filename
18140829 10224724 2957312 31322865 1ddf2f1 ./vmlinux before 18140970 10225412 2957312 31323694 1ddf62e ./vmlinux after (+829)
Static text symbols:
Before: 40321
After: 40302 (-19)
--- arch/x86/kernel/macros.S | 2 ++ include/linux/compiler.h | 56 ++++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 13 deletions(-)
arch/x86/kernel/macros.S +2 -0
@@ -5,3 +5,5 @@ * commonly used. The macros are precompiled into assmebly file which is later * assembled together with each compiled file. */ + +#include <linux/compiler.h>
include/linux/compiler.h +43 -13
71 lines not on this page · raw message
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/objtool: Use asm macros to work around GCC inlining bugs
x86/objtool: Use asm macros to work around GCC inlining bugs
Commit-ID: c06c4d8090513f2974dfdbed2ac98634357ac475 Gitweb: https://git.kernel.org/tip/c06c4d8090513f2974dfdbed2ac98634357ac475 Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:53 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 11:24:58 +0200
x86/objtool: Use asm macros to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
In the case of objtool the resulting borkage can be significant, since all the annotations of objtool are discarded during linkage and never inlined, yet GCC bogusly considers most functions affected by objtool annotations as 'too large'.
The workaround is to set an assembly macro and call it from the inline assembly block. As a result GCC considers the inline assembly block as a single instruction. (Which it isn't, but that's the best we can get.)
This increases the kernel size slightly:
text data bss dec hex filename
18140829 10224724 2957312 31322865 1ddf2f1 ./vmlinux before 18140970 10225412 2957312 31323694 1ddf62e ./vmlinux after (+829)
The number of static text symbols (i.e. non-inlined functions) is reduced:
Before: 40321
After: 40302 (-19)
[ mingo: Rewrote the changelog. ]
--- arch/x86/kernel/macros.S | 2 ++ include/linux/compiler.h | 56 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 13 deletions(-)
arch/x86/kernel/macros.S +2 -0
@@ -5,3 +5,5 @@ * commonly used. The macros are precompiled into assmebly file which is later * assembled together with each compiled file. */ + +#include <linux/compiler.h>
include/linux/compiler.h +43 -13
71 lines not on this page · raw message
PATCH v9 4/10 x86: refcount: prevent gcc distortions
In reply to Nadav AmitGCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
The solution is to set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction.
This patch allows to inline functions such as __get_seccomp_filter(). Interestingly, this allows more aggressive inlining while reducing the kernel size.
text data bss dec hex filename
18140970 10225412 2957312 31323694 1ddf62e ./vmlinux before 18140140 10225284 2957312 31322736 1ddf270 ./vmlinux after (-958)
Static text symbols:
Before: 40302
After: 40286 (-16)
Functions such as kref_get(), free_user(), fuse_file_get() now get inlined.
--- arch/x86/include/asm/refcount.h | 74 ++++++++++++++++++++------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 46 insertions(+), 29 deletions(-)
arch/x86/include/asm/refcount.h +45 -29
@@ -4,6 +4,41 @@* x86-specific implementation of refcount_t. Based on PAX_REFCOUNT from * PaX/grsecurity. */ + +#ifdef __ASSEMBLY__ + +#include <asm/asm.h> +#include <asm/bug.h> + +.macro REFCOUNT_EXCEPTION counter:req + .pushsection .text..refcount +111: lea \counter, %_ASM_CX +112: ud2 + ASM_UNREACHABLE + .popsection +113: _ASM_EXTABLE_REFCOUNT(112b, 113b) +.endm + +/* Trigger refcount exception if refcount result is negative. */ +.macro REFCOUNT_CHECK_LT_ZERO counter:req + js 111f + REFCOUNT_EXCEPTION counter="\counter" +.endm + +/* Trigger refcount exception if refcount result is zero or negative. */ +.macro REFCOUNT_CHECK_LE_ZERO counter:req + jz 111f + REFCOUNT_CHECK_LT_ZERO counter="\counter" +.endm + +/* Trigger refcount exception unconditionally. */ +.macro REFCOUNT_ERROR counter:req + jmp 111f + REFCOUNT_EXCEPTION counter="\counter" +.endm + +#else /* __ASSEMBLY__ */ +#include <linux/refcount.h> #include <asm/bug.h>
@@ -15,34 +50,11 @@* central refcount exception. The fixup address for the exception points * back to the regular execution flow in .text. */ -#define _REFCOUNT_EXCEPTION \ - ".pushsection .text..refcount\n" \ - "111:\tlea %[counter], %%" _ASM_CX "\n" \ - "112:\t" ASM_UD2 "\n" \ - ASM_UNREACHABLE \ - ".popsection\n" \ - "113:\n" \ - _ASM_EXTABLE_REFCOUNT(112b, 113b) - -/* Trigger refcount exception if refcount result is negative. */ -#define REFCOUNT_CHECK_LT_ZERO \ - "js 111f\n\t" \ - _REFCOUNT_EXCEPTION - -/* Trigger refcount exception if refcount result is zero or negative. */ -#define REFCOUNT_CHECK_LE_ZERO \ - "jz 111f\n\t" \ - REFCOUNT_CHECK_LT_ZERO - -/* Trigger refcount exception unconditionally. */ -#define REFCOUNT_ERROR \ - "jmp 111f\n\t" \ - _REFCOUNT_EXCEPTION static __always_inline void refcount_add(unsigned int i, refcount_t *r) { asmvolatile (LOCK_PREFIX "addl %1,%0\n\t" -REFCOUNT_CHECK_LT_ZERO +"REFCOUNT_CHECK_LT_ZERO counter=\"%[counter]\"" : [counter]"+m" (r->refs.counter) :"ir" (i) :"cc" ,"cx" );
@@ -51,7 +63,7 @@ static __always_inline void refcount_add(unsigned int i, refcount_t *r) static __always_inline void refcount_inc(refcount_t *r) { asmvolatile (LOCK_PREFIX "incl %0\n\t" -REFCOUNT_CHECK_LT_ZERO +"REFCOUNT_CHECK_LT_ZERO counter=\"%[counter]\"" : [counter]"+m" (r->refs.counter) : :"cc" ,"cx" ); }
@@ -59,7 +71,7 @@ static __always_inline void refcount_inc(refcount_t *r) static __always_inline void refcount_dec(refcount_t *r) { asmvolatile (LOCK_PREFIX "decl %0\n\t" -REFCOUNT_CHECK_LE_ZERO +"REFCOUNT_CHECK_LE_ZERO counter=\"%[counter]\"" : [counter]"+m" (r->refs.counter) : :"cc" ,"cx" ); }
@@ -67,13 +79,15 @@ static __always_inline void refcount_dec(refcount_t *r)static __always_inline __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r) { -GEN_BINARY_SUFFIXED_RMWcc (LOCK_PREFIX "subl" ,REFCOUNT_CHECK_LT_ZERO , +GEN_BINARY_SUFFIXED_RMWcc (LOCK_PREFIX "subl" , +"REFCOUNT_CHECK_LT_ZERO counter=\"%0\"" , r->refs.counter,"er" , i,"%0" , e,"cx" ); } static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r) { -GEN_UNARY_SUFFIXED_RMWcc (LOCK_PREFIX "decl" ,REFCOUNT_CHECK_LT_ZERO , +GEN_UNARY_SUFFIXED_RMWcc (LOCK_PREFIX "decl" , +"REFCOUNT_CHECK_LT_ZERO counter=\"%0\"" , r->refs.counter,"%0" , e,"cx" ); }
@@ -91,7 +105,7 @@ bool refcount_add_not_zero(unsigned int i, refcount_t *r)/* Did we try to increment from/to an undesirable state? */ if (unlikely (c <0 || c ==INT_MAX || result < c)) { - asm volatile(REFCOUNT_ERROR + asmvolatile ("REFCOUNT_ERROR counter=\"%[counter]\"" : : [counter]"m" (r->refs.counter) :"cc" ,"cx" );break ;
@@ -107,4 +121,6 @@ static __always_inline __must_check bool refcount_inc_not_zero(refcount_t *r)return refcount_add_not_zero (1 , r); } +#endif /* __ASSEMBLY__ */ +#endif
arch/x86/kernel/macros.S +1 -0
@@ -7,3 +7,4 @@ */ #include <linux/compiler.h> +#include <asm/refcount.h>
Signature · 1 line
2.17.1
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 18 lines · Nadav Amit
GCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
The solution is to set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction.
This patch allows to inline functions such as
__get_seccomp_filter(). Interestingly, this allows more aggressive inlining while reducing the kernel size.text data bss dec hex filename
18140970 10225412 2957312 31323694 1ddf62e ./vmlinux before 18140140 10225284 2957312 31322736 1ddf270 ./vmlinux after (-958)
Quoted 6 lines
Static text symbols:
Before: 40302
After: 40286 (-16)Functions such as
kref_get(),free_user(),fuse_file_get()now get inlined.
Yeah, so I kind of had your series on the back-burner (I'm sure you noticed!), mostly because what I complained about in a previous round of review a couple of months ago: that the description of the series and the changelog of every single patch in it is tiptoeing around the *real* problem and never truly describes it:
** This is a GCC bug, plain and simple, and we are uglifying ** ** and complicating kernel assembly code to work it around. **
We'd never ever consider such uglification for Clang, not even _close_.
Sure this would have warranted a passing mention? Instead the changelogs are lovingly calling it a "distortion" as if this was no-one's fault really, and the patch a "solution".
How about calling it a "GCC inlining bug" and a "workaround with costs" which it is in reality, and stop whitewashing the problem?
At the same time I realize that we still need this series because GCC won't get fixed, so as a consolation I wrote the changelog below that explains how it really is, no holds barred.
Since the tone of the changelog is a bit ... frosty, I added this disclaimer:
[ mingo: Wrote new changelog. ]
Let me know if you want me to make it more prominent that you had absolutely no role in writing that changelog.
I'm also somewhat annoyed at the fact that this series carries a boatload of reviewed-by's and acked-by's, yet none of those reviewers found it important to point out the large chasm that is gaping between description and reality.
Thanks,
Ingo
=============>
Subject: x86/refcount: Prevent inlining related GCC distortions
From: Nadav Amit <[email protected]>
Date: Wed, 3 Oct 2018 14:30:54 -0700
The inlining pass of GCC doesn't include an assembler, so it's not aware of basic properties of the generated code, such as its size in bytes, or that there are such things as discontiuous blocks of code and data due to the newfangled linker feature called 'sections' ...
Instead GCC uses a lazy and fragile heuristic: it does a linear count of certain syntactic and whitespace elements in inlined assembly block source code, such as a count of new-lines and semicolons (!), as a poor substitute for "code size and complexity".
Unsurprisingly this heuristic falls over and breaks its neck whith certain common types of kernel code that use inline assembly, such as the frequent practice of putting useful information into alternative sections.
As a result of this fresh, 20+ years old GCC bug, GCC's inlining decisions are effectively disabled for inlined functions that make use of such asm() blocks, because GCC thinks those sections of code are "large" - when in reality they are often result in just a very low number of machine instructions generated.
This absolute lack of inlining provess when GCC comes across such asm() blocks both increases generated kernel code size and causes performance overhead, which is particularly noticeable on paravirt kernels, which make frequent use of these inlining facilities in attemt to stay out of the way when running on baremetal hardware.
Instead of fixing the compiler we use a workaround: we set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction. (Which it often isn't but I digress.)
This uglifies and bloats the source code:
2 files changed, 46 insertions(+), 29 deletions(-)
Yay readability and maintainability, it's not like assembly code is hard to read and maintain ...
This patch allows GCC to inline simple functions such as __get_seccomp_filter().
To no-one's surprise the result is GCC performs more aggressive (read: correct) inlining decisions in these senarios, which reduces the kernel size and presumably also speeds it up:
text data bss dec hex filename 18140970 10225412 2957312 31323694 1ddf62e ./vmlinux before 18140140 10225284 2957312 31322736 1ddf270 ./vmlinux after (-958)
Change in size of static text symbols:
Before: 40302
After: 40286 (-16)
Functions such as kref_get(), free_user(), fuse_file_get() now get inlined. Hurray!
We also hope that GCC will eventually get fixed, but we are not holding our breath for that. Yet we are optimistic, it might still happen, any decade now.
[ mingo: Wrote new changelog. ]
---
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 4 lines · Ingo Molnar
I'm also somewhat annoyed at the fact that this series carries a boatload of reviewed-by's and acked-by's, yet none of those reviewers found it important to point out the large chasm that is gaping between description and reality.
Another problem I just realized is that we now include arch/x86/kernel/macros.S in every translation pass when building the kernel, right?
But arch/x86/kernel/macros.S expands to a pretty large hiearchy of header files:
$ make arch/x86/kernel/macros.s
$ cat $(grep include arch/x86/kernel/macros.s | cut -d\" -f2 | sort | uniq) | wc -l 4128
That's 4,100 extra lines of code to be preprocessed for every translation unit, of which there are tens of thousands. More if other pieces of code get macrofied in this fasion in the future.
If we assume that a typical distribution kernel build has ~20,000 translation units then this change adds 82,560,000 more lines to be preprocessed, just to work around a stupid GCC bug?
I'm totally unhappy about that. Can we do this without adding macros.S?
It's also a pretty stupidly central file anyway that moves source code away from where it's used.
Thanks,
Ingo
[email protected]
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 37 lines · Ingo Molnar
Quoted 1 line · Ingo Molnar
I'm also somewhat annoyed at the fact that this series carries a
boatload
Quoted 2 lines
of reviewed-by's and acked-by's, yet none of those reviewers found it important to point out the large chasm that is gaping between
description
Quoted 1 line
and reality.
Another problem I just realized is that we now include
arch/x86/kernel/macros.Sin every
translation pass when building the kernel, right?But
arch/x86/kernel/macros.Sexpands to a pretty large hiearchy of header files:$ make arch/x86/kernel/macros.s$ cat $(grep include arch/x86/kernel/macros.s | cut -d\" -f2 | sort | uniq) | wc -l 4128That's 4,100 extra lines of code to be preprocessed for every translation unit, of
which there are tens of thousands. More if other pieces of code get macrofied in
this fasion in the future.If we assume that a typical distribution kernel build has ~20,000 translation units
then this change adds 82,560,000 more lines to be preprocessed, just to work around
a stupid GCC bug?I'm totally unhappy about that. Can we do this without adding
macros.S?
Quoted 7 lines
It's also a pretty stupidly central file anyway that moves source code away
from where it's used.Thanks,
Ingo
It's not just for working around a stupid GCC bug, but it also has a huge potential for cleaning up the inline asm in general.
I would like to know if there is an actual number for the build overhead (an actual benchmark); I have asked for that once already.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 2 lines · * [email protected] <[email protected]> wrote:
It's not just for working around a stupid GCC bug, but it also has a huge potential for cleaning up the inline asm in general.
Sorry but that's just plain false. For example this patch:
x86: cpufeature: use macros instead of inline assembly
... adds an extra macro indirection layer called STATIC_CPU_HAS, just to macrofy a single asm() statement that was perfectly readable and on-topic already...
There are some other cases where macrofying is also a cleanup due to sharing and naming a common pattern of code, but this is by no means an absolute quality of this approach.
Thanks,
Ingo
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to [email protected]Quoted 43 lines · at 1:40 AM, [email protected] wrote:
Quoted 42 lines · Ingo Molnar
Quoted 1 line · Ingo Molnar
I'm also somewhat annoyed at the fact that this series carries a
boatload
Quoted 2 lines
of reviewed-by's and acked-by's, yet none of those reviewers found it important to point out the large chasm that is gaping between
description
Quoted 1 line
and reality.
Another problem I just realized is that we now include
arch/x86/kernel/macros.Sin every
translation pass when building the kernel, right?But
arch/x86/kernel/macros.Sexpands to a pretty large hiearchy of header files:$ make arch/x86/kernel/macros.s$ cat $(grep include arch/x86/kernel/macros.s | cut -d\" -f2 | sort | uniq) | wc -l 4128That's 4,100 extra lines of code to be preprocessed for every translation unit, of
which there are tens of thousands. More if other pieces of code get macrofied in
this fasion in the future.If we assume that a typical distribution kernel build has ~20,000 translation units
then this change adds 82,560,000 more lines to be preprocessed, just to work around
a stupid GCC bug?I'm totally unhappy about that. Can we do this without adding
macros.S?It's also a pretty stupidly central file anyway that moves source code away
from where it's used.Thanks,
Quoted 7 lines
Quoted 1 line
Ingo
It's not just for working around a stupid GCC bug, but it also has a huge potential for cleaning up the inline asm in general.
I would like to know if there is an actual number for the build overhead (an actual benchmark); I have asked for that once already.
I can run some tests. (@hpa: I thought you asked about the -pipe overhead; perhaps I misunderstood).
I guess you regard to the preprocessing of the assembler. Note that the C preprocessing of macros.S obviously happens only once. That’s the reason I assumed it’s not that expensive.
Anyhow, I remember that we discussed at some point doing something like ‘asm(“.include XXX.s”)’ and somebody said it is not good, but I don’t remember why and don’t see any reason it is so. Unless I am missing something, I think it is possible to take each individual header and preprocess the assembly part of into a separate .s file. Then we can put in the C part of the header ‘asm(".include XXX.s”)’.
What do you think?
[email protected]
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 79 lines · Nadav Amit
Quoted 1 line · at 1:40 AM, [email protected] wrote:
On October 4, 2018 1:33:33 AM PDT, Ingo Molnar <[email protected]>
Quoted 5 lines · wrote:
Quoted 5 lines · Ingo Molnar
Quoted 2 lines
I'm also somewhat annoyed at the fact that this series carries a
boatload
Quoted 1 line
of reviewed-by's and acked-by's, yet none of those reviewers found
it
Quoted 8 lines
Quoted 8 lines
Quoted 1 line
important to point out the large chasm that is gaping between
description
Quoted 1 line
and reality.
Another problem I just realized is that we now include
arch/x86/kernel/macros.Sin every
translation pass when building the kernel, right?Quoted 6 lines
Quoted 6 lines
But
arch/x86/kernel/macros.Sexpands to a pretty large hiearchy of header files:$ make arch/x86/kernel/macros.s$ cat $(grep include arch/x86/kernel/macros.s | cut -d\" -f2 | sort|
Quoted 9 lines
Quoted 9 lines
uniq) | wc -l
4128That's 4,100 extra lines of code to be preprocessed for every translation unit, of
which there are tens of thousands. More if other pieces of code get macrofied in
this fasion in the future.Quoted 3 lines
Quoted 3 lines
If we assume that a typical distribution kernel build has ~20,000 translation units
then this change adds 82,560,000 more lines to be preprocessed, justto
Quoted 4 lines
Quoted 4 lines
work around
a stupid GCC bug?I'm totally unhappy about that. Can we do this without adding
macros.S?Quoted 2 lines
Quoted 2 lines
It's also a pretty stupidly central file anyway that moves source
code
Quoted 8 lines
Quoted 6 lines
away
from where it's used.Thanks,
Ingo
It's not just for working around a stupid GCC bug, but it also has a
huge
Quoted 3 lines
potential for cleaning up the inline asm in general.
I would like to know if there is an actual number for the build
overhead
Quoted 1 line
(an actual benchmark); I have asked for that once already.
I can run some tests. (@hpa: I thought you asked about the -pipe overhead;
perhaps I misunderstood).I guess you regard to the preprocessing of the assembler. Note that the C
preprocessing ofmacros.Sobviously happens only once. That’s the reason
I assumed it’s not that expensive.Anyhow, I remember that we discussed at some point doing something like ‘asm(“.include XXX.s”)’ and somebody said it is not good, but I don’t remember why and don’t see any reason it is so. Unless I am missing something, I think it is possible to take each individual header and preprocess the assembly part of into a separate .s file. Then we can put in
the C part of the header ‘asm(".include XXX.s”)’.
Quoted 1 line
What do you think?
Ingo: I wasn't talking necessarily about the specifics of each bit, but rather the general concept about being able to use macros in inlines... I can send you something I have been working on in the background, but have been holding off on because of this, in the morning my time.
But that's no excuse for not doing it right.
Global asm() statements are problematic because there is no guarantee where in the assembly source they will end up. You'd almost need to intercept the assembly output, move all the includes to the top, and then process...
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 2 lines · * [email protected] <[email protected]> wrote:
Ingo: I wasn't talking necessarily about the specifics of each bit, but rather the general concept about being able to use macros in inlines...
Ok, agreed about that part - and some of the patches did improve readability.
Also, the 275 lines macros.s is a lot nicer than the 4,200 lines macros.S.
Also, I'm not against using workarounds when the benefits are larger than the costs, but I am against *hiding* the fact that these are workarounds and that for some of them there are costs.
Quoted 2 lines
I can send you something I have been working on in the background, but have been holding off on because of this, in the morning my time.
BTW., I have applied most of the series to tip:x86/kbuild already, and will push them out later today after some testing. I didn't apply the final 3 patches as they have dependencies, but applied the basics and fixed up the changelogs.
So you can rely on this.
Thanks,
Ingo
H. Peter Anvin
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 6 lines · Ingo Molnar
Quoted 2 lines · * [email protected] <[email protected]> wrote:
Ingo: I wasn't talking necessarily about the specifics of each bit, but rather the general concept about being able to use macros in inlines...
Quoted 7 lines
Ok, agreed about that part - and some of the patches did improve readability.
Also, the 275 lines macros.s is a lot nicer than the 4,200 lines
macros.S.Also, I'm not against using workarounds when the benefits are larger than the costs, but I am against *hiding* the fact that these are workarounds and that for some of them there are costs.
Agreed, of course.
Quoted 9 lines
Quoted 2 lines
I can send you something I have been working on in the background, but have been holding off on because of this, in the morning my time.
BTW., I have applied most of the series to tip:x86/kbuild already, and will push them out later today after some testing. I didn't apply the final 3 patches as they have dependencies, but applied the basics and fixed up the changelogs.
So you can rely on this.
Wonderful.
Here is the horrible code I mentioned yesterday. This is about implementing the immediate-patching framework that Linus and others have discussed (it helps both performance and kernel hardening):
Warning: this stuff can cause serious damage to your eyes, and this is a just a small chunk of the whole mess; and relying on gas macros, as brain damaged as they are, really is much, much cleaner than not:
http://www.zytor.com/~hpa/foo.S -hpa
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 30 lines · H. Peter Anvin
Quoted 11 lines · Ingo Molnar
Quoted 2 lines · * [email protected] <[email protected]> wrote:
Ingo: I wasn't talking necessarily about the specifics of each bit, but rather the general concept about being able to use macros in inlines...
Ok, agreed about that part - and some of the patches did improve readability.
Also, the 275 lines macros.s is a lot nicer than the 4,200 lines
macros.S.Also, I'm not against using workarounds when the benefits are larger than the costs, but I am against *hiding* the fact that these are workarounds and that for some of them there are costs.
Agreed, of course.
Quoted 8 lines
Quoted 2 lines
I can send you something I have been working on in the background, but have been holding off on because of this, in the morning my time.
BTW., I have applied most of the series to tip:x86/kbuild already, and will push them out later today after some testing. I didn't apply the final 3 patches as they have dependencies, but applied the basics and fixed up the changelogs.
So you can rely on this.
Wonderful.
Here is the horrible code I mentioned yesterday. This is about implementing the immediate-patching framework that Linus and others have discussed (it helps both performance and kernel hardening):
Quoted 5 lines
Warning: this stuff can cause serious damage to your eyes, and this is a just a small chunk of the whole mess; and relying on gas macros, as brain damaged as they are, really is much, much cleaner than not:
https://na01.safelinks.protection.outlook.com/?url=http:%2F%2Fwww.zytor.com%2F~hpa%2Ffoo.S&data=02%7C01%7Cnamit%40vmware.com%7C326f1a3beb4649df319508d62a3042fa%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636742784111671122&sdata=anYIOXzlSTXPQKttTBHjSQgapBmaO9gfibBF34ZlHeQ%3D&reserved=0
Funny. Immediate-patching is what I was playing with when I encountered the gcc issue. Performance got worse instead of improving (or at least staying the same), because inlining got crazy.
Anyhow, wait for my soon-to-be-sent RFC in which I define a macro called “call” (to reduce the retpoline overhead) before you talk about damage to the eyes.
H. Peter Anvin
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 9 lines · Nadav Amit
Funny. Immediate-patching is what I was playing with when I encountered the gcc issue. Performance got worse instead of improving (or at least staying the same), because inlining got crazy.
Anyhow, wait for my soon-to-be-sent RFC in which I define a macro called “call” (to reduce the retpoline overhead) before you talk about damage to the eyes.
Doing it well is *hard*, as I discovered. The actual patch is much, much, larger.
-hpa
Andy Lutomirski
maintainerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to H. Peter AnvinQuoted 25 lines · H. Peter Anvin
Quoted 6 lines · Ingo Molnar
Quoted 2 lines · * [email protected] <[email protected]> wrote:
Ingo: I wasn't talking necessarily about the specifics of each bit, but rather the general concept about being able to use macros in inlines...
Quoted 7 lines
Ok, agreed about that part - and some of the patches did improve readability.
Also, the 275 lines macros.s is a lot nicer than the 4,200 lines
macros.S.Also, I'm not against using workarounds when the benefits are larger than the costs, but I am against *hiding* the fact that these are workarounds and that for some of them there are costs.
Agreed, of course.
Quoted 7 lines
Quoted 2 lines
I can send you something I have been working on in the background, but have been holding off on because of this, in the morning my time.
BTW., I have applied most of the series to tip:x86/kbuild already, and will push them out later today after some testing. I didn't apply the final 3 patches as they have dependencies, but applied the basics and fixed up the changelogs.
Quoted 9 lines
Quoted 2 lines
So you can rely on this.
Wonderful.
Here is the horrible code I mentioned yesterday. This is about implementing the immediate-patching framework that Linus and others have discussed (it helps both performance and kernel hardening):
I'm wondering if a production version should look more like:
patch_point:
mov $whatever, [target]
.pushsection ".immediate_patches"
.quad .Lpatch_point
.popsection
and let objtool parse the resulting assembled output and emit an entry in some table mapping patch_point to the actual address and size of the immediate to be patched.
H. Peter Anvin
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 16 lines · Andy Lutomirski
Quoted 7 lines
Wonderful.
Here is the horrible code I mentioned yesterday. This is about implementing the immediate-patching framework that Linus and others have discussed (it helps both performance and kernel hardening):
I'm wondering if a production version should look more like:
patch_point:
mov $whatever, [target]
.pushsection ".immediate_patches"
.quad .Lpatch_point
.popsection
Quoted 4 lines
and let objtool parse the resulting assembled output and emit an entry in some table mapping
patch_pointto the actual address and size of the immediate to be patched.
Putting the generation of the ersatz code in objtool is an interesting idea, although I'm wondering if these macros, as awful as they are, wouldn't have generic applicability (what they do is they allow the cold branch of an asm to push temporaries to the stack rather than having to have gcc clobber them.)
I'll think about it.
-hpa
Rasmus Villemoes
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to H. Peter AnvinQuoted 3 lines · H. Peter Anvin
Here is the horrible code I mentioned yesterday. This is about implementing the immediate-patching framework that Linus and others have discussed (it helps both performance and kernel hardening):
Heh, I did a POC in userspace some years ago for loading an "eventually constant" value into a register - the idea being to avoid a load in cases like kmemcache_alloc(foo_cachep) or kmemcache_free(foo_cachep, p), and I assume this is something along the same lines? I didn't do anything with it since I had no idea if the performance gain would be worth it, and at the time (before __ro_after_init) there was no good way to know that the values would really be constant eventually. Also, I had hoped to come up with a way to avoid having to annotate the loads.
I just tried expanding this to deal with some of the hash tables sized at init time which I can see was also mentioned on LKML some time ago. I'm probably missing something fundamental, but there's some sorta working code at https://github.com/villemoes/rai which is not too horrible (IMO). Attaching gcc at various times and doing disassembly shows that the patching does take place. Can I get you to take a look at raimacros.S and tell me why that won't work?
Thanks,
Rasmus
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to Nadav AmitQuoted 2 lines · Nadav Amit
I can run some tests. (@hpa: I thought you asked about the -pipe overhead; perhaps I misunderstood).
Well, tests are unlikely to show the overhead of extra lines of this magnitude, unless done very carefully, yet the added bloat exists and is not even mentioned by the changelog, it just says:
Subject: [PATCH v9 02/10] Makefile: Prepare for using macros for inline asm
Using macros for inline assembly improves both readability and compilation decisions that are distorted by big assembly blocks that use alternative sections. Compile macros.S and use it to assemble all C files. Currently, only x86 will use it.
Quoted 3 lines
I guess you regard to the preprocessing of the assembler. Note that the C preprocessing of
macros.Sobviously happens only once. That’s the reason I assumed it’s not that expensive.
True - so first we build macros.s, and that gets included in every C file build, right?
macros.s is smaller: 275 lines only in the distro test build I tried, which looks a lot better than my first 4,200 lines guesstimate.
Quoted 8 lines
Anyhow, I remember that we discussed at some point doing something like ‘asm(“.include XXX.s”)’ and somebody said it is not good, but I don’t remember why and don’t see any reason it is so. Unless I am missing something, I think it is possible to take each individual header and preprocess the assembly part of into a separate .s file. Then we can put in the C part of the header ‘asm(".include XXX.s”)’.
What do you think?
Hm, this looks quite complex - macros.s is better I think. Also, 275 straight assembly lines is a lot better than 4,200.
Another, separate question I wanted to ask: how do we ensure that the kernel stays fixed? I.e. is there some tooling we can use to actually measure whether there's bad inlining decisions done, to detect all these bad patterns that cause bad GCC code generation?
Thanks,
Ingo
[email protected]
reviewerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 56 lines · Ingo Molnar
Quoted 1 line · Nadav Amit
I can run some tests. (@hpa: I thought you asked about the -pipe
overhead;
Quoted 1 line
perhaps I misunderstood).
Well, tests are unlikely to show the overhead of extra lines of this magnitude, unless done very carefully, yet the added bloat exists and is not even
mentioned by the changelog, it just says:Subject: [PATCH v9 02/10]
Makefile: Prepare for using macros for inline asmUsing macros for inline assembly improves both readability and
compilation decisions that are distorted by big assembly blocks that use
alternative sections. Compilemacros.Sand use it to assemble all C files. Currently, only x86 will use it.Quoted 1 line
I guess you regard to the preprocessing of the assembler. Note that
the C
Quoted 1 line
preprocessing of
macros.Sobviously happens only once. That’s thereason
Quoted 1 line
I assumed it’s not that expensive.
True - so first we build macros.s, and that gets included in every C file build, right?
macros.s is smaller: 275 lines only in the distro test build I tried, which looks
a lot better than my first 4,200 lines guesstimate.Quoted 1 line
Anyhow, I remember that we discussed at some point doing something
like
Quoted 4 lines
‘asm(“.include XXX.s”)’ and somebody said it is not good, but I don’t remember why and don’t see any reason it is so. Unless I am missing something, I think it is possible to take each individual header and preprocess the assembly part of into a separate .s file. Then we can
put in
Quoted 3 lines
the C part of the header ‘asm(".include XXX.s”)’.
What do you think?
Hm, this looks quite complex - macros.s is better I think. Also, 275 straight assembly lines is
a lot better than 4,200.Another, separate question I wanted to ask: how do we ensure that the kernel stays fixed?
I.e. is there some tooling we can use to actually measure whether there's bad inlining decisions
done, to detect all these bad patterns that cause bad GCC code generation?
Quoted 3 lines
Thanks,
Ingo
The assembly output from GCC is quite volumious; I doubt tacking a few hundred lines on will matter one iota.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to Ingo MolnarQuoted 17 lines · Ingo Molnar
Quoted 2 lines · Nadav Amit
I can run some tests. (@hpa: I thought you asked about the -pipe overhead; perhaps I misunderstood).
Well, tests are unlikely to show the overhead of extra lines of this magnitude, unless done very carefully, yet the added bloat exists and is not even mentioned by the changelog, it just says:
Subject: [PATCH v9 02/10]
Makefile: Prepare for using macros for inline asmUsing macros for inline assembly improves both readability and compilation decisions that are distorted by big assembly blocks that use alternative sections. Compile
macros.Sand use it to assemble all C files. Currently, only x86 will use it.
Quoted 5 lines
Quoted 3 lines
I guess you regard to the preprocessing of the assembler. Note that the C preprocessing of
macros.Sobviously happens only once. That’s the reason I assumed it’s not that expensive.True - so first we build macros.s, and that gets included in every C file build, right?
Right.
Quoted 11 lines
macros.s is smaller: 275 lines only in the distro test build I tried, which looks a lot better than my first 4,200 lines guesstimate.
Quoted 7 lines
Anyhow, I remember that we discussed at some point doing something like ‘asm(“.include XXX.s”)’ and somebody said it is not good, but I don’t remember why and don’t see any reason it is so. Unless I am missing something, I think it is possible to take each individual header and preprocess the assembly part of into a separate .s file. Then we can put in the C part of the header ‘asm(".include XXX.s”)’.
Quoted 4 lines
Quoted 1 line
What do you think?
Hm, this looks quite complex - macros.s is better I think. Also, 275 straight assembly lines is a lot better than 4,200.
I’m really not into it, and hpa reminded me why it wouldn’t work. For some reason I thought the order of macros doesn’t matter in asm (I probably should go to sleep).
Quoted 3 lines
Another, separate question I wanted to ask: how do we ensure that the kernel stays fixed? I.e. is there some tooling we can use to actually measure whether there's bad inlining decisions done, to detect all these bad patterns that cause bad GCC code generation?
Good question. First, I’ll indicate that this patch-set does not handle all the issues. There is still the issue of conditional use of __builtin_constant_p().
One indication for bad inlining decisions is the inlined functions have multiple (non-inlined) instances in the binary and are short. I don’t have an automatic solution, but you can try, for example to run:
nm --print-size ./vmlinux | grep ' t ' | cut -d' ' -f2- | sort | uniq -c | \ grep -v '^ 1' | sort -n -r | head -n 5
There are however many false positives. After these patches, for example, I get:
11 000000000000012f t jhash
7 0000000000000017 t dst_output
6 0000000000000011 t kzalloc
5 000000000000002f t acpi_os_allocate_zeroed
5 0000000000000029 t acpi_os_allocatejhash() should not have been inlined in my mind, and should have a non-inlined implementation. dst_output() is used as a function pointer. kzalloc() and the next two suffer from the __builtin_constant_p() problem I described in the past.
Regards,
Nadav
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 25 lines · Nadav Amit
Quoted 3 lines
Another, separate question I wanted to ask: how do we ensure that the kernel stays fixed? I.e. is there some tooling we can use to actually measure whether there's bad inlining decisions done, to detect all these bad patterns that cause bad GCC code generation?
Good question. First, I’ll indicate that this patch-set does not handle all the issues. There is still the issue of conditional use of
__builtin_constant_p().One indication for bad inlining decisions is the inlined functions have multiple (non-inlined) instances in the binary and are short. I don’t have an automatic solution, but you can try, for example to run:
nm --print-size ./vmlinux | grep ' t ' | cut -d' ' -f2- | sort | uniq -c | \ grep -v '^ 1' | sort -n -r | head -n 5There are however many false positives. After these patches, for example, I get:
11 000000000000012f t jhash 7 0000000000000017 t dst_output 6 0000000000000011 t kzalloc 5 000000000000002f t acpi_os_allocate_zeroed 5 0000000000000029 t acpi_os_allocate
Quoted 4 lines
jhash()should not have been inlined in my mind, and should have a non-inlined implementation.dst_output()is used as a function pointer.kzalloc()and the next two suffer from the__builtin_constant_p()problem I described in the past.
Ok, that's useful info.
The histogram suggests that with all your patches applied the kernel is now in a pretty good state in terms of inlining decisions, right?
Are you using defconfig or a reasonable distro-config for your tests?
Thanks,
Ingo
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 33 lines · Ingo Molnar
Quoted 25 lines · Nadav Amit
Quoted 3 lines
Another, separate question I wanted to ask: how do we ensure that the kernel stays fixed? I.e. is there some tooling we can use to actually measure whether there's bad inlining decisions done, to detect all these bad patterns that cause bad GCC code generation?
Good question. First, I’ll indicate that this patch-set does not handle all the issues. There is still the issue of conditional use of
__builtin_constant_p().One indication for bad inlining decisions is the inlined functions have multiple (non-inlined) instances in the binary and are short. I don’t have an automatic solution, but you can try, for example to run:
nm --print-size ./vmlinux | grep ' t ' | cut -d' ' -f2- | sort | uniq -c | \ grep -v '^ 1' | sort -n -r | head -n 5There are however many false positives. After these patches, for example, I get:
11 000000000000012f t jhash 7 0000000000000017 t dst_output 6 0000000000000011 t kzalloc 5 000000000000002f t acpi_os_allocate_zeroed 5 0000000000000029 t acpi_os_allocateQuoted 4 lines
jhash()should not have been inlined in my mind, and should have a non-inlined implementation.dst_output()is used as a function pointer.kzalloc()and the next two suffer from the__builtin_constant_p()problem I described in the past.
Quoted 4 lines
Ok, that's useful info.
The histogram suggests that with all your patches applied the kernel is now in a pretty good state in terms of inlining decisions, right?
It was just an example that I ran on the kernel I built right now (with a custom config). Please don’t regard these results as anything indicative.
Quoted 1 line
Are you using defconfig or a reasonable distro-config for your tests?
I think it is best to take the kernel and run localyesconfig for testing.
Taking Ubuntu 18.04 and doing the same gives the following results:
12 000000000000012f t jhash
7 0000000000000017 t dst_output
7 0000000000000014 t init_once
5 00000000000000d8 t jhash2
5 000000000000004e t put_page
5 000000000000002f t acpi_os_allocate_zeroed
5 0000000000000029 t acpi_os_allocate
5 0000000000000028 t umask_show
5 0000000000000011 t kzalloc
4 0000000000000053 t trace_xhci_dbg_quirksNot awful, but not great.
It is a bit hard to fix the __builtin_constant_p() problem without having some negative side-effects.
Reminder: __builtin_constant_p() is evaluated after the inlining decision are done. You can use __builtin_choose_expr() instead of an “if”s and instead of ternary operators when evaluating __builtin_constant_p() to solve the problem. However, this causes the compiler not to know sometimes that a value is constant because __builtin_choose_expr () evaluation happens too early. This __builtin_choose_expr() problem is the reason for put_page() and kzalloc() are not being inlined. Clang, again, does not suffer from this problem.
Anyhow, it may be a good practice to try to get rid of the rest. For example, dst_discard() has four instances because it is always given as a function pointer. So it should not have been inlined.
Regards,
Nadav
Ingo Molnar
Tested-by Kees Cook Acked-by Peter Zijlstra (Intel) Tested-by Kees Cook Acked-by Peter Zijlstra (Intel) Tested-by Kees Cook Acked-by Peter Zijlstra (Intel)Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 3 lines · Nadav Amit
Quoted 1 line
Are you using defconfig or a reasonable distro-config for your tests?
I think it is best to take the kernel and run localyesconfig for testing.
Ok, agreed - and this makes the numbers you provided pretty representative.
Good - now that all of my concerns were addressed I'd like to merge the remaining 3 patches as well - but they are conflicting with ongoing x86 work in tip:x86/core. The extable conflict is trivial, the jump-label conflict a bit more involved.
Could you please pick up the updated changelogs below and resolve the conflicts against tip:master or tip:x86/build and submit the remaining patches as well?
Thanks,
Ingo
=============>
commit b82b0b611740c7c88050ba743c398af7eb920029
Author: Nadav Amit <[email protected]> Date: Wed Oct 3 14:31:00 2018 -0700
x86/jump-labels: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is also a minor cleanup for the jump-label code.
As a result the code size is slightly increased, but inlining decisions are better:
text data bss dec hex filename
18163528 10226300 2957312 31347140 1de51c4 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+1128)
And functions such as intel_pstate_adjust_policy_max(), kvm_cpu_accept_dm_intr(), kvm_register_readl() are inlined.
commit dfc243615d43bb477d1d16a0064fc3d69ade5b3a
Author: Nadav Amit <[email protected]> Date: Wed Oct 3 14:30:59 2018 -0700
x86/cpufeature: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is pretty pointless indirection in the static_cpu_has() case, but is worth it to improve overall inlining quality.
The patch slightly increases the kernel size:
text data bss dec hex filename
18162879 10226256 2957312 31346447 1de4f0f ./vmlinux before 18163528 10226300 2957312 31347140 1de51c4 ./vmlinux after (+693)
And enables the inlining of function such as free_ldt_pgtables().
commit 4021bdcd351fd63d8d5e74264ee18d09388f0221
Author: Nadav Amit <[email protected]> Date: Wed Oct 3 14:30:58 2018 -0700
x86/extable: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is also a minor cleanup for the exception table code.
Text size goes up a bit:
text data bss dec hex filename
18162555 10226288 2957312 31346155 1de4deb ./vmlinux before 18162879 10226256 2957312 31346447 1de4f0f ./vmlinux after (+292)
But this allows the inlining of functions such as nested_vmx_exit_reflected(), set_segment_reg(), __copy_xstate_to_user() which is a net benefit.
Borislav Petkov
maintainerRe: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 5 lines · Ingo Molnar
Quoted 2 lines · Nadav Amit
Quoted 1 line
Are you using defconfig or a reasonable distro-config for your tests?
Quoted 7 lines
Quoted 1 line
I think it is best to take the kernel and run localyesconfig for testing.
Ok, agreed - and this makes the numbers you provided pretty representative.
Good - now that all of my concerns were addressed I'd like to merge the remaining 3 patches as well - but they are conflicting with ongoing x86 work in tip:x86/core. The extable conflict is trivial, the jump-label conflict a bit more involved.
FWIW, gcc guys are not too averse to the idea of enhancing gcc inline asm syntax with a statement which specifies its size so that gcc can use it to do better inlining cost estimation than counting lines.
Lemme work the process ...
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 14 lines · Borislav Petkov
Quoted 5 lines · Ingo Molnar
Quoted 2 lines · Nadav Amit
Quoted 1 line
Are you using defconfig or a reasonable distro-config for your tests?
Quoted 7 lines
Quoted 1 line
I think it is best to take the kernel and run localyesconfig for testing.
Ok, agreed - and this makes the numbers you provided pretty representative.
Good - now that all of my concerns were addressed I'd like to merge the remaining 3 patches as well - but they are conflicting with ongoing x86 work in tip:x86/core. The extable conflict is trivial, the jump-label conflict a bit more involved.
Quoted 5 lines
FWIW, gcc guys are not too averse to the idea of enhancing gcc inline asm syntax with a statement which specifies its size so that gcc can use it to do better inlining cost estimation than counting lines.
Lemme work the process ...
Thanks!
Ingo
cover Macrofying inline asm rebased
In reply to Ingo MolnarThese are the last 3 patches from the "macrofying inline asm" series after rebasing on TIP, per Ingo's request.
For the record: the new commit log was written by Ingo.
Nadav Amit (3):
x86/extable: Macrofy inline assembly code to work around GCC inlining
bugs
x86/cpufeature: Macrofy inline assembly code to work around GCC
inlining bugs
x86/jump-labels: Macrofy inline assembly code to work around GCC
inlining bugs
arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/asm.h | 53 ++++++++------------ arch/x86/include/asm/cpufeature.h | 82 ++++++++++++++++++------------- arch/x86/include/asm/jump_label.h | 72 +++++++-------------------- arch/x86/kernel/macros.S | 3 ++ 5 files changed, 89 insertions(+), 123 deletions(-)
Signature · 1 line
2.17.1
PATCH 1/3 x86/extable: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is also a minor cleanup for the exception table code.
Text size goes up a bit:
text data bss dec hex filename
18162555 10226288 2957312 31346155 1de4deb ./vmlinux before 18162879 10226256 2957312 31346447 1de4f0f ./vmlinux after (+292)
But this allows the inlining of functions such as nested_vmx_exit_reflected(), set_segment_reg(), __copy_xstate_to_user() which is a net benefit.
--- arch/x86/include/asm/asm.h | 53 ++++++++++++++------------------------ arch/x86/kernel/macros.S | 1 + 2 files changed, 21 insertions(+), 33 deletions(-)
arch/x86/include/asm/asm.h +20 -33
@@ -120,12 +120,25 @@/* Exception table entry */ #ifdef __ASSEMBLY__# define _ASM_EXTABLE_HANDLE (from, to, handler) \ - .pushsection "__ex_table","a" ; \ - .balign 4 ; \ - .long (from) - . ; \ - .long (to) - . ; \ - .long (handler) - . ; \ + ASM_EXTABLE_HANDLE from to handler + +.macro ASM_EXTABLE_HANDLE from:req to:req handler:req + .pushsection "__ex_table","a" + .balign 4 + .long (\from) - . + .long (\to) - . + .long (\handler) - . .popsection +.endm +#else /* __ASSEMBLY__ */ + +# define _ASM_EXTABLE_HANDLE (from, to, handler) \ + "ASM_EXTABLE_HANDLE from=" #from " to=" #to \ + " handler=\"" #handler "\"\n\t" + +/* For C file, we already have NOKPROBE_SYMBOL macro */ + +#endif /* __ASSEMBLY__ */ # define _ASM_EXTABLE (from, to) \ _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
@@ -148,6 +161,7 @@_ASM_PTR (entry); \ .popsection +#ifdef __ASSEMBLY__ .macro ALIGN_DESTINATION/* check for bad alignment of destination */ movl %edi,%ecx
@@ -171,34 +185,7 @@ _ASM_EXTABLE_UA(100b, 103b)_ASM_EXTABLE_UA (101b ,103b ) .endm - -#else -# define _EXPAND_EXTABLE_HANDLE (x) #x -# define _ASM_EXTABLE_HANDLE (from, to, handler) \ - " .pushsection \"__ex_table\",\"a\"\n" \ - " .balign 4\n" \ - " .long (" #from ") - .\n" \ - " .long (" #to ") - .\n" \ - " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n" \ - " .popsection\n" - -# define _ASM_EXTABLE (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) - -# define _ASM_EXTABLE_UA (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess) - -# define _ASM_EXTABLE_FAULT (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) - -# define _ASM_EXTABLE_EX (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext) - -# define _ASM_EXTABLE_REFCOUNT (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_refcount) - -/* For C file, we already have NOKPROBE_SYMBOL macro */ -#endif +#endif /* __ASSEMBLY__ */ #ifndef __ASSEMBLY__/*
arch/x86/kernel/macros.S +1 -0
@@ -11,3 +11,4 @@ #include <asm/alternative-asm.h> #include <asm/bug.h> #include <asm/paravirt.h> +#include <asm/asm.h>
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/extable: Macrofy inline assembly code to work around GCC inlining bugs
x86/extable: Macrofy inline assembly code to work around GCC inlining bugs
Commit-ID: 0474d5d9d2f7f3b11262f7bf87d0e7314ead9200 Gitweb: https://git.kernel.org/tip/0474d5d9d2f7f3b11262f7bf87d0e7314ead9200 Author: Nadav Amit <[email protected]> AuthorDate: Fri, 5 Oct 2018 13:27:16 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 6 Oct 2018 15:52:15 +0200
x86/extable: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is also a minor cleanup for the exception table code.
Text size goes up a bit:
text data bss dec hex filename 18162555 10226288 2957312 31346155 1de4deb ./vmlinux before 18162879 10226256 2957312 31346447 1de4f0f ./vmlinux after (+292)
But this allows the inlining of functions such as nested_vmx_exit_reflected(), set_segment_reg(), __copy_xstate_to_user() which is a net benefit.
--- arch/x86/include/asm/asm.h | 53 +++++++++++++++++----------------------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 21 insertions(+), 33 deletions(-)
arch/x86/include/asm/asm.h +20 -33
@@ -120,12 +120,25 @@/* Exception table entry */ #ifdef __ASSEMBLY__# define _ASM_EXTABLE_HANDLE (from, to, handler) \ - .pushsection "__ex_table","a" ; \ - .balign 4 ; \ - .long (from) - . ; \ - .long (to) - . ; \ - .long (handler) - . ; \ + ASM_EXTABLE_HANDLE from to handler + +.macro ASM_EXTABLE_HANDLE from:req to:req handler:req + .pushsection "__ex_table","a" + .balign 4 + .long (\from) - . + .long (\to) - . + .long (\handler) - . .popsection +.endm +#else /* __ASSEMBLY__ */ + +# define _ASM_EXTABLE_HANDLE (from, to, handler) \ + "ASM_EXTABLE_HANDLE from=" #from " to=" #to \ + " handler=\"" #handler "\"\n\t" + +/* For C file, we already have NOKPROBE_SYMBOL macro */ + +#endif /* __ASSEMBLY__ */ # define _ASM_EXTABLE (from, to) \ _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
@@ -148,6 +161,7 @@_ASM_PTR (entry); \ .popsection +#ifdef __ASSEMBLY__ .macro ALIGN_DESTINATION/* check for bad alignment of destination */ movl %edi,%ecx
@@ -171,34 +185,7 @@ _ASM_EXTABLE_UA(100b, 103b)_ASM_EXTABLE_UA (101b ,103b ) .endm - -#else -# define _EXPAND_EXTABLE_HANDLE (x) #x -# define _ASM_EXTABLE_HANDLE (from, to, handler) \ - " .pushsection \"__ex_table\",\"a\"\n" \ - " .balign 4\n" \ - " .long (" #from ") - .\n" \ - " .long (" #to ") - .\n" \ - " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n" \ - " .popsection\n" - -# define _ASM_EXTABLE (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) - -# define _ASM_EXTABLE_UA (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_uaccess) - -# define _ASM_EXTABLE_FAULT (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) - -# define _ASM_EXTABLE_EX (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext) - -# define _ASM_EXTABLE_REFCOUNT (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_refcount) - -/* For C file, we already have NOKPROBE_SYMBOL macro */ -#endif +#endif /* __ASSEMBLY__ */ #ifndef __ASSEMBLY__/*
arch/x86/kernel/macros.S +1 -0
@@ -11,3 +11,4 @@ #include <asm/alternative-asm.h> #include <asm/bug.h> #include <asm/paravirt.h> +#include <asm/asm.h>
PATCH 2/3 x86/cpufeature: Macrofy inline assembly code to work around GCC inlining bugs
In reply to Nadav AmitAs described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is pretty pointless indirection in the static_cpu_has() case, but is worth it to improve overall inlining quality.
The patch slightly increases the kernel size:
text data bss dec hex filename
18162879 10226256 2957312 31346447 1de4f0f ./vmlinux before 18163528 10226300 2957312 31347140 1de51c4 ./vmlinux after (+693)
And enables the inlining of function such as free_ldt_pgtables().
--- arch/x86/include/asm/cpufeature.h | 82 ++++++++++++++++++------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 48 insertions(+), 35 deletions(-)
arch/x86/include/asm/cpufeature.h +47 -35
@@ -2,10 +2,10 @@#ifndef _ASM_X86_CPUFEATURE_H#define _ASM_X86_CPUFEATURE_H -#include <asm/processor.h> - -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#include <asm/processor.h> #include <asm/asm.h> #include <linux/bitops.h>
@@ -161,37 +161,10 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);*/ static __always_inline __pure bool _static_cpu_has(u16 bit) { - asm_volatile_goto("1: jmp 6f\n" - "2:\n" - ".skip -(((5f-4f) - (2b-1b)) > 0) * " - "((5f-4f) - (2b-1b)),0x90\n" - "3:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 4f - .\n" /* repl offset */ - " .word %P[always]\n" /* always replace */ - " .byte 3b - 1b\n" /* src len */ - " .byte 5f - 4f\n" /* repl len */ - " .byte 3b - 2b\n" /* pad len */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "4: jmp %l[t_no]\n" - "5:\n" - ".previous\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 0\n" /* no replacement */ - " .word %P[feature]\n" /* feature bit */ - " .byte 3b - 1b\n" /* src len */ - " .byte 0\n" /* repl len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .altinstr_aux,\"ax\"\n" - "6:\n" - " testb %[bitnum],%[cap_byte]\n" - " jnz %l[t_yes]\n" - " jmp %l[t_no]\n" - ".previous\n" + asm_volatile_goto("STATIC_CPU_HAS bitnum=%[bitnum] " + "cap_byte=\"%[cap_byte]\" " + "feature=%P[feature] t_yes=%l[t_yes] " + "t_no=%l[t_no] always=%P[always]" : : [feature] "i" (bit), [always] "i" (X86_FEATURE_ALWAYS), [bitnum] "i" (1 << (bit & 7)),
@@ -226,5 +199,44 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ boot_cpu_data.x86_model -#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ +#else /* __ASSEMBLY__ */ + +.macro STATIC_CPU_HAS bitnum:req cap_byte:req feature:req t_yes:req t_no:req always:req +1: + jmp 6f +2: + .skip -(((5f-4f) - (2b-1b)) > 0) * ((5f-4f) - (2b-1b)),0x90 +3: + .section .altinstructions,"a" + .long 1b - . /* src offset */ + .long 4f - . /* repl offset */ + .word \always /* always replace */ + .byte 3b - 1b /* src len */ + .byte 5f - 4f /* repl len */ + .byte 3b - 2b /* pad len */ + .previous + .section .altinstr_replacement,"ax" +4: + jmp \t_no +5: + .previous + .section .altinstructions,"a" + .long 1b - . /* src offset */ + .long 0 /* no replacement */ + .word \feature /* feature bit */ + .byte 3b - 1b /* src len */ + .byte 0 /* repl len */ + .byte 0 /* pad len */ + .previous + .section .altinstr_aux,"ax" +6: + testb \bitnum,\cap_byte + jnz \t_yes + jmp \t_no + .previous +.endm + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ #endif /* _ASM_X86_CPUFEATURE_H */
arch/x86/kernel/macros.S +1 -0
@@ -12,3 +12,4 @@ #include <asm/bug.h> #include <asm/paravirt.h> #include <asm/asm.h> +#include <asm/cpufeature.h>
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/cpufeature: Macrofy inline assembly code to work around GCC inlining bugs
x86/cpufeature: Macrofy inline assembly code to work around GCC inlining bugs
Commit-ID: d5a581d84ae6b8a4a740464b80d8d9cf1e7947b2 Gitweb: https://git.kernel.org/tip/d5a581d84ae6b8a4a740464b80d8d9cf1e7947b2 Author: Nadav Amit <[email protected]> AuthorDate: Fri, 5 Oct 2018 13:27:17 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 6 Oct 2018 15:52:16 +0200
x86/cpufeature: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is pretty pointless indirection in the static_cpu_has() case, but is worth it to improve overall inlining quality.
The patch slightly increases the kernel size:
text data bss dec hex filename 18162879 10226256 2957312 31346447 1de4f0f ./vmlinux before 18163528 10226300 2957312 31347140 1de51c4 ./vmlinux after (+693)
And enables the inlining of function such as free_ldt_pgtables().
--- arch/x86/include/asm/cpufeature.h | 82 ++++++++++++++++++++++----------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 48 insertions(+), 35 deletions(-)
arch/x86/include/asm/cpufeature.h +47 -35
@@ -2,10 +2,10 @@#ifndef _ASM_X86_CPUFEATURE_H#define _ASM_X86_CPUFEATURE_H -#include <asm/processor.h> - -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#include <asm/processor.h> #include <asm/asm.h> #include <linux/bitops.h>
@@ -161,37 +161,10 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);*/ static __always_inline __pure bool _static_cpu_has(u16 bit) { - asm_volatile_goto("1: jmp 6f\n" - "2:\n" - ".skip -(((5f-4f) - (2b-1b)) > 0) * " - "((5f-4f) - (2b-1b)),0x90\n" - "3:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 4f - .\n" /* repl offset */ - " .word %P[always]\n" /* always replace */ - " .byte 3b - 1b\n" /* src len */ - " .byte 5f - 4f\n" /* repl len */ - " .byte 3b - 2b\n" /* pad len */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "4: jmp %l[t_no]\n" - "5:\n" - ".previous\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 0\n" /* no replacement */ - " .word %P[feature]\n" /* feature bit */ - " .byte 3b - 1b\n" /* src len */ - " .byte 0\n" /* repl len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .altinstr_aux,\"ax\"\n" - "6:\n" - " testb %[bitnum],%[cap_byte]\n" - " jnz %l[t_yes]\n" - " jmp %l[t_no]\n" - ".previous\n" + asm_volatile_goto("STATIC_CPU_HAS bitnum=%[bitnum] " + "cap_byte=\"%[cap_byte]\" " + "feature=%P[feature] t_yes=%l[t_yes] " + "t_no=%l[t_no] always=%P[always]" : : [feature] "i" (bit), [always] "i" (X86_FEATURE_ALWAYS), [bitnum] "i" (1 << (bit & 7)),
@@ -226,5 +199,44 @@ t_no:#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ boot_cpu_data.x86_model -#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ +#else /* __ASSEMBLY__ */ + +.macro STATIC_CPU_HAS bitnum:req cap_byte:req feature:req t_yes:req t_no:req always:req +1: + jmp 6f +2: + .skip -(((5f-4f) - (2b-1b)) > 0) * ((5f-4f) - (2b-1b)),0x90 +3: + .section .altinstructions,"a" + .long 1b - . /* src offset */ + .long 4f - . /* repl offset */ + .word \always /* always replace */ + .byte 3b - 1b /* src len */ + .byte 5f - 4f /* repl len */ + .byte 3b - 2b /* pad len */ + .previous + .section .altinstr_replacement,"ax" +4: + jmp \t_no +5: + .previous + .section .altinstructions,"a" + .long 1b - . /* src offset */ + .long 0 /* no replacement */ + .word \feature /* feature bit */ + .byte 3b - 1b /* src len */ + .byte 0 /* repl len */ + .byte 0 /* pad len */ + .previous + .section .altinstr_aux,"ax" +6: + testb \bitnum,\cap_byte + jnz \t_yes + jmp \t_no + .previous +.endm + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ #endif /* _ASM_X86_CPUFEATURE_H */
arch/x86/kernel/macros.S +1 -0
@@ -12,3 +12,4 @@ #include <asm/bug.h> #include <asm/paravirt.h> #include <asm/asm.h> +#include <asm/cpufeature.h>
PATCH 3/3 x86/jump-labels: Macrofy inline assembly code to work around GCC inlining bugs
In reply to Nadav AmitAs described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is also a minor cleanup for the jump-label code.
As a result the code size is slightly increased, but inlining decisions are better:
text data bss dec hex filename
18163528 10226300 2957312 31347140 1de51c4 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+1128)
And functions such as intel_pstate_adjust_policy_max(), kvm_cpu_accept_dm_intr(), kvm_register_readl() are inlined.
--- arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/jump_label.h | 72 ++++++++----------------------- arch/x86/kernel/macros.S | 1 + 3 files changed, 20 insertions(+), 55 deletions(-)
arch/x86/entry/calling.h +1 -1
@@ -338,7 +338,7 @@ For 32-bit we have the following conventions - kernel is built with .macro CALL_enter_from_user_mode#ifdef CONFIG_CONTEXT_TRACKING #ifdef HAVE_JUMP_LABEL - STATIC_JUMP_IF_FALSE .Lafter_call_\@, context_tracking_enabled, def=0 + STATIC_BRANCH_JMP l_yes=.Lafter_call_\@, key=context_tracking_enabled, branch=1#endif call enter_from_user_mode .Lafter_call_\@:
arch/x86/include/asm/jump_label.h +18 -54
103 lines not on this page · raw message
arch/x86/kernel/macros.S +1 -0
@@ -13,3 +13,4 @@ #include <asm/paravirt.h> #include <asm/asm.h> #include <asm/cpufeature.h> +#include <asm/jump_label.h>
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/jump-labels: Macrofy inline assembly code to work around GCC inlining bugs
x86/jump-labels: Macrofy inline assembly code to work around GCC inlining bugs
Commit-ID: 5bdcd510c2ac9efaf55c4cbd8d46421d8e2320cd Gitweb: https://git.kernel.org/tip/5bdcd510c2ac9efaf55c4cbd8d46421d8e2320cd Author: Nadav Amit <[email protected]> AuthorDate: Fri, 5 Oct 2018 13:27:18 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 6 Oct 2018 15:52:17 +0200
x86/jump-labels: Macrofy inline assembly code to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - which is also a minor cleanup for the jump-label code.
As a result the code size is slightly increased, but inlining decisions are better:
text data bss dec hex filename 18163528 10226300 2957312 31347140 1de51c4 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+1128)
And functions such as intel_pstate_adjust_policy_max(), kvm_cpu_accept_dm_intr(), kvm_register_readl() are inlined.
--- arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/jump_label.h | 72 ++++++++++----------------------------- arch/x86/kernel/macros.S | 1 + 3 files changed, 20 insertions(+), 55 deletions(-)
arch/x86/entry/calling.h +1 -1
@@ -338,7 +338,7 @@ For 32-bit we have the following conventions - kernel is built with .macro CALL_enter_from_user_mode#ifdef CONFIG_CONTEXT_TRACKING #ifdef HAVE_JUMP_LABEL - STATIC_JUMP_IF_FALSE .Lafter_call_\@, context_tracking_enabled, def=0 + STATIC_BRANCH_JMP l_yes=.Lafter_call_\@, key=context_tracking_enabled, branch=1#endif call enter_from_user_mode .Lafter_call_\@:
arch/x86/include/asm/jump_label.h +18 -54
103 lines not on this page · raw message
arch/x86/kernel/macros.S +1 -0
@@ -13,3 +13,4 @@ #include <asm/paravirt.h> #include <asm/asm.h> #include <asm/cpufeature.h> +#include <asm/jump_label.h>
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to Ingo MolnarQuoted 7 lines · Ingo Molnar
Quoted 3 lines · Nadav Amit
Quoted 1 line
Are you using defconfig or a reasonable distro-config for your tests?
I think it is best to take the kernel and run localyesconfig for testing.
Quoted 8 lines
Ok, agreed - and this makes the numbers you provided pretty representative.
Good - now that all of my concerns were addressed I'd like to merge the remaining 3 patches as well - but they are conflicting with ongoing x86 work in tip:x86/core. The extable conflict is trivial, the jump-label conflict a bit more involved.
Could you please pick up the updated changelogs below and resolve the conflicts against tip:master or tip:x86/build and submit the remaining patches as well?
For the record, I summarized my analysis of the poor function inlining decisions in Linux in the following blog-post:
https://nadav.amit.zone/blog/linux-inline
Regards,
Nadav
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
In reply to Ingo MolnarQuoted 53 lines · Ingo Molnar
Quoted 18 lines · Nadav Amit
GCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
The solution is to set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction.
This patch allows to inline functions such as
__get_seccomp_filter(). Interestingly, this allows more aggressive inlining while reducing the kernel size.text data bss dec hex filename
18140970 10225412 2957312 31323694 1ddf62e ./vmlinux before 18140140 10225284 2957312 31322736 1ddf270 ./vmlinux after (-958)Quoted 6 lines
Static text symbols:
Before: 40302
After: 40286 (-16)Functions such as
kref_get(),free_user(),fuse_file_get()now get inlined.Yeah, so I kind of had your series on the back-burner (I'm sure you noticed!), mostly because what I complained about in a previous round of review a couple of months ago: that the description of the series and the changelog of every single patch in it is tiptoeing around the *real* problem and never truly describes it:
** This is a GCC bug, plain and simple, and we are uglifying ** ** and complicating kernel assembly code to work it around. **
We'd never ever consider such uglification for Clang, not even _close_. Sure this would have warranted a passing mention? Instead the changelogs are lovingly calling it a "distortion" as if this was no-one's fault really, and the patch a "solution".
How about calling it a "GCC inlining bug" and a "workaround with costs" which it is in reality, and stop whitewashing the problem?
At the same time I realize that we still need this series because GCC won't get fixed, so as a consolation I wrote the changelog below that explains how it really is, no holds barred.
Since the tone of the changelog is a bit ... frosty, I added this disclaimer:
[ mingo: Wrote new changelog. ]
Quoted 7 lines
Let me know if you want me to make it more prominent that you had absolutely no role in writing that changelog.
I'm also somewhat annoyed at the fact that this series carries a boatload of reviewed-by's and acked-by's, yet none of those reviewers found it important to point out the large chasm that is gaping between description and reality.
So, I’m sorry for missing your comment about misrepresenting the problem.
Feel free to do whatever you want with the commit message (just fix the typo in “attemt"). As long as you don’t NAK the patches or send me to redo them, it’s fine. I just want to clarify few things for you to consider.
First, you are right that clang does not have this issue (I checked), but the behavior of gcc is clearly documented - once you know what to look for.
Second, I think the end result is not as ugly as you make it sound (and maybe not ugly at all). Using this patch-set, you can write big blocks of inlined assembly code without having those disgusting C macros. You can also share the same code between inline asm and asm files.
You can have a look, for example, on ALTERNATIVE which is defined both as assembly macro and C macro. Is the C macro readable? Is it easy to maintain two different version? I do have a patch that merges the two implementations together (which I still didn’t send, since I wait for the infra to be applied first), and I think makes much more sense.
Finally, note that it’s not as if the binary always becomes smaller. Overall, with the full patch-set it is slightly bigger. But still, that’s how it was supposed to be if gcc wasn’t doing things badly.
Thanks again,
Nadav
Re: [PATCH v9 04/10] x86: refcount: prevent gcc distortions
Quoted 3 lines · Nadav Amit
Finally, note that it’s not as if the binary always becomes smaller. Overall, with the full patch-set it is slightly bigger. But still, that’s how it was supposed to be if gcc wasn’t doing things badly.
So what I cited was the changelog for the refcount patch, which according to your measurements reduced kernel image size.
For other patches where size grew I left that text intact.
And yes, in this particular case a slight increase in kernel size might actually be beneficial, as we get a lot more straight-line execution in exchange. So this is not a show-stopper property as long as the bloat isn't large.
Thanks,
Ingo
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/refcount: Work around GCC inlining bug
In reply to Nadav Amitx86/refcount: Work around GCC inlining bug
Commit-ID: 9e1725b410594911cc5981b6c7b4cea4ec054ca8 Gitweb: https://git.kernel.org/tip/9e1725b410594911cc5981b6c7b4cea4ec054ca8 Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:54 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 11:24:59 +0200
x86/refcount: Work around GCC inlining bug
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block. As a result GCC considers the inline assembly block as a single instruction. (Which it isn't, but that's the best we can get.)
This patch allows GCC to inline simple functions such as __get_seccomp_filter().
To no-one's surprise the result is that GCC performs more aggressive (read: correct) inlining decisions in these senarios, which reduces the kernel size and presumably also speeds it up:
text data bss dec hex filename 18140970 10225412 2957312 31323694 1ddf62e ./vmlinux before 18140140 10225284 2957312 31322736 1ddf270 ./vmlinux after (-958)
16 fewer static text symbols:
Before: 40302
After: 40286 (-16)
these got inlined instead.
Functions such as kref_get(), free_user(), fuse_file_get() now get inlined. Hurray!
[ mingo: Rewrote the changelog. ]
--- arch/x86/include/asm/refcount.h | 74 +++++++++++++++++++++++++---------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 46 insertions(+), 29 deletions(-)
arch/x86/include/asm/refcount.h +45 -29
@@ -4,6 +4,41 @@* x86-specific implementation of refcount_t. Based on PAX_REFCOUNT from * PaX/grsecurity. */ + +#ifdef __ASSEMBLY__ + +#include <asm/asm.h> +#include <asm/bug.h> + +.macro REFCOUNT_EXCEPTION counter:req + .pushsection .text..refcount +111: lea \counter, %_ASM_CX +112: ud2 + ASM_UNREACHABLE + .popsection +113: _ASM_EXTABLE_REFCOUNT(112b, 113b) +.endm + +/* Trigger refcount exception if refcount result is negative. */ +.macro REFCOUNT_CHECK_LT_ZERO counter:req + js 111f + REFCOUNT_EXCEPTION counter="\counter" +.endm + +/* Trigger refcount exception if refcount result is zero or negative. */ +.macro REFCOUNT_CHECK_LE_ZERO counter:req + jz 111f + REFCOUNT_CHECK_LT_ZERO counter="\counter" +.endm + +/* Trigger refcount exception unconditionally. */ +.macro REFCOUNT_ERROR counter:req + jmp 111f + REFCOUNT_EXCEPTION counter="\counter" +.endm + +#else /* __ASSEMBLY__ */ +#include <linux/refcount.h> #include <asm/bug.h>
@@ -15,34 +50,11 @@* central refcount exception. The fixup address for the exception points * back to the regular execution flow in .text. */ -#define _REFCOUNT_EXCEPTION \ - ".pushsection .text..refcount\n" \ - "111:\tlea %[counter], %%" _ASM_CX "\n" \ - "112:\t" ASM_UD2 "\n" \ - ASM_UNREACHABLE \ - ".popsection\n" \ - "113:\n" \ - _ASM_EXTABLE_REFCOUNT(112b, 113b) - -/* Trigger refcount exception if refcount result is negative. */ -#define REFCOUNT_CHECK_LT_ZERO \ - "js 111f\n\t" \ - _REFCOUNT_EXCEPTION - -/* Trigger refcount exception if refcount result is zero or negative. */ -#define REFCOUNT_CHECK_LE_ZERO \ - "jz 111f\n\t" \ - REFCOUNT_CHECK_LT_ZERO - -/* Trigger refcount exception unconditionally. */ -#define REFCOUNT_ERROR \ - "jmp 111f\n\t" \ - _REFCOUNT_EXCEPTION static __always_inline void refcount_add(unsigned int i, refcount_t *r) { asmvolatile (LOCK_PREFIX "addl %1,%0\n\t" -REFCOUNT_CHECK_LT_ZERO +"REFCOUNT_CHECK_LT_ZERO counter=\"%[counter]\"" : [counter]"+m" (r->refs.counter) :"ir" (i) :"cc" ,"cx" );
@@ -51,7 +63,7 @@ static __always_inline void refcount_add(unsigned int i, refcount_t *r) static __always_inline void refcount_inc(refcount_t *r) { asmvolatile (LOCK_PREFIX "incl %0\n\t" -REFCOUNT_CHECK_LT_ZERO +"REFCOUNT_CHECK_LT_ZERO counter=\"%[counter]\"" : [counter]"+m" (r->refs.counter) : :"cc" ,"cx" ); }
@@ -59,7 +71,7 @@ static __always_inline void refcount_inc(refcount_t *r) static __always_inline void refcount_dec(refcount_t *r) { asmvolatile (LOCK_PREFIX "decl %0\n\t" -REFCOUNT_CHECK_LE_ZERO +"REFCOUNT_CHECK_LE_ZERO counter=\"%[counter]\"" : [counter]"+m" (r->refs.counter) : :"cc" ,"cx" ); }
@@ -67,13 +79,15 @@ static __always_inline void refcount_dec(refcount_t *r)static __always_inline __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r) { -GEN_BINARY_SUFFIXED_RMWcc (LOCK_PREFIX "subl" ,REFCOUNT_CHECK_LT_ZERO , +GEN_BINARY_SUFFIXED_RMWcc (LOCK_PREFIX "subl" , +"REFCOUNT_CHECK_LT_ZERO counter=\"%0\"" , r->refs.counter,"er" , i,"%0" , e,"cx" ); } static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r) { -GEN_UNARY_SUFFIXED_RMWcc (LOCK_PREFIX "decl" ,REFCOUNT_CHECK_LT_ZERO , +GEN_UNARY_SUFFIXED_RMWcc (LOCK_PREFIX "decl" , +"REFCOUNT_CHECK_LT_ZERO counter=\"%0\"" , r->refs.counter,"%0" , e,"cx" ); }
@@ -91,7 +105,7 @@ bool refcount_add_not_zero(unsigned int i, refcount_t *r)/* Did we try to increment from/to an undesirable state? */ if (unlikely (c <0 || c ==INT_MAX || result < c)) { - asm volatile(REFCOUNT_ERROR + asmvolatile ("REFCOUNT_ERROR counter=\"%[counter]\"" : : [counter]"m" (r->refs.counter) :"cc" ,"cx" );break ;
@@ -107,4 +121,6 @@ static __always_inline __must_check bool refcount_inc_not_zero(refcount_t *r)return refcount_add_not_zero (1 , r); } +#endif /* __ASSEMBLY__ */ +#endif
arch/x86/kernel/macros.S +1 -0
@@ -7,3 +7,4 @@ */ #include <linux/compiler.h> +#include <asm/refcount.h>
PATCH v9 5/10 x86: alternatives: macrofy locks for better inlining
In reply to Nadav AmitGCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
The solution is to set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction.
This patch handles the LOCK prefix, allowing more aggresive inlining.
text data bss dec hex filename
18140140 10225284 2957312 31322736 1ddf270 ./vmlinux before 18146889 10225380 2957312 31329581 1de0d2d ./vmlinux after (+6845)
Static text symbols:
Before: 40286
After: 40218 (-68)
--- arch/x86/include/asm/alternative-asm.h | 20 ++++++++++++++------ arch/x86/include/asm/alternative.h | 11 ++--------- arch/x86/kernel/macros.S | 1 + 3 files changed, 17 insertions(+), 15 deletions(-)
arch/x86/include/asm/alternative-asm.h +14 -6
@@ -7,16 +7,24 @@#include <asm/asm.h> #ifdef CONFIG_SMP - .macro LOCK_PREFIX -672: lock +.macro LOCK_PREFIX_HERE .pushsection .smp_locks,"a" .balign 4 - .long 672b - . + .long 671f - . # offset .popsection - .endm +671: +.endm + +.macro LOCK_PREFIX insn:vararg + LOCK_PREFIX_HERE + lock \insn +.endm#else - .macro LOCK_PREFIX - .endm +.macro LOCK_PREFIX_HERE +.endm + +.macro LOCK_PREFIX insn:vararg +.endm#endif /*
arch/x86/include/asm/alternative.h +2 -9
@@ -31,15 +31,8 @@*/ #ifdef CONFIG_SMP -#define LOCK_PREFIX_HERE \ - ".pushsection .smp_locks,\"a\"\n" \ - ".balign 4\n" \ - ".long 671f - .\n"/* offset */ \ -".popsection\n" \ - "671:" - -#define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; " - +#define LOCK_PREFIX_HERE "LOCK_PREFIX_HERE\n\t" +#define LOCK_PREFIX "LOCK_PREFIX "#else /* ! CONFIG_SMP */ #define LOCK_PREFIX_HERE ""#define LOCK_PREFIX ""
arch/x86/kernel/macros.S +1 -0
@@ -8,3 +8,4 @@ #include <linux/compiler.h> #include <asm/refcount.h> +#include <asm/alternative-asm.h>
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/alternatives: Macrofy lock prefixes to work around GCC inlining bugs
x86/alternatives: Macrofy lock prefixes to work around GCC inlining bugs
Commit-ID: 77f48ec28e4ccff94d2e5f4260a83ac27a7f3099 Gitweb: https://git.kernel.org/tip/77f48ec28e4ccff94d2e5f4260a83ac27a7f3099 Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:55 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 11:24:59 +0200
x86/alternatives: Macrofy lock prefixes to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block - i.e. to macrify the affected block.
As a result GCC considers the inline assembly block as a single instruction.
This patch handles the LOCK prefix, allowing more aggresive inlining:
text data bss dec hex filename 18140140 10225284 2957312 31322736 1ddf270 ./vmlinux before 18146889 10225380 2957312 31329581 1de0d2d ./vmlinux after (+6845)
This is the reduction in non-inlined functions:
Before: 40286
After: 40218 (-68)
--- arch/x86/include/asm/alternative-asm.h | 20 ++++++++++++++------ arch/x86/include/asm/alternative.h | 11 ++--------- arch/x86/kernel/macros.S | 1 + 3 files changed, 17 insertions(+), 15 deletions(-)
arch/x86/include/asm/alternative-asm.h +14 -6
@@ -7,16 +7,24 @@#include <asm/asm.h> #ifdef CONFIG_SMP - .macro LOCK_PREFIX -672: lock +.macro LOCK_PREFIX_HERE .pushsection .smp_locks,"a" .balign 4 - .long 672b - . + .long 671f - . # offset .popsection - .endm +671: +.endm + +.macro LOCK_PREFIX insn:vararg + LOCK_PREFIX_HERE + lock \insn +.endm#else - .macro LOCK_PREFIX - .endm +.macro LOCK_PREFIX_HERE +.endm + +.macro LOCK_PREFIX insn:vararg +.endm#endif /*
arch/x86/include/asm/alternative.h +2 -9
@@ -31,15 +31,8 @@*/ #ifdef CONFIG_SMP -#define LOCK_PREFIX_HERE \ - ".pushsection .smp_locks,\"a\"\n" \ - ".balign 4\n" \ - ".long 671f - .\n"/* offset */ \ -".popsection\n" \ - "671:" - -#define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; " - +#define LOCK_PREFIX_HERE "LOCK_PREFIX_HERE\n\t" +#define LOCK_PREFIX "LOCK_PREFIX "#else /* ! CONFIG_SMP */ #define LOCK_PREFIX_HERE ""#define LOCK_PREFIX ""
arch/x86/kernel/macros.S +1 -0
@@ -8,3 +8,4 @@ #include <linux/compiler.h> #include <asm/refcount.h> +#include <asm/alternative-asm.h>
PATCH v9 6/10 x86: bug: prevent gcc distortions
In reply to Nadav AmitGCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
The solution is to set an assembly macro and call it from the inlinedv assembly block. As a result GCC considers the inline assembly block as a single instruction.
This patch increases the kernel size:
text data bss dec hex filename
18146889 10225380 2957312 31329581 1de0d2d ./vmlinux before 18147336 10226688 2957312 31331336 1de1408 ./vmlinux after (+1755)
But enables more aggressive inlining (and probably branch decisions). The number of static text symbols in vmlinux is lower.
Static text symbols:
Before: 40218
After: 40053 (-165)
--- arch/x86/include/asm/bug.h | 98 ++++++++++++++++++++++---------------- arch/x86/kernel/macros.S | 1 + include/asm-generic/bug.h | 8 ++-- 3 files changed, 61 insertions(+), 46 deletions(-)
arch/x86/include/asm/bug.h +56 -42
@@ -4,6 +4,8 @@#include <linux/stringify.h> +#ifndef __ASSEMBLY__ +/* * Despite that some emulators terminate on UD2, we use it for WARN(). *
@@ -20,53 +22,15 @@#define LEN_UD2 2 -#ifdef CONFIG_GENERIC_BUG - -#ifdef CONFIG_X86_32 -# define __BUG_REL (val) ".long " __stringify(val) -#else -# define __BUG_REL (val) ".long " __stringify(val) " - 2b" -#endif - -#ifdef CONFIG_DEBUG_BUGVERBOSE - -#define _BUG_FLAGS (ins, flags) \ -do { \ - asm volatile("1:\t" ins "\n" \ - ".pushsection __bug_table,\"aw\"\n" \ - "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ - "\t" __BUG_REL(%c0) "\t# bug_entry::file\n" \ - "\t.word %c1" "\t# bug_entry::line\n" \ - "\t.word %c2" "\t# bug_entry::flags\n" \ - "\t.org 2b+%c3\n" \ - ".popsection" \ - : : "i" (__FILE__), "i" (__LINE__), \ - "i" (flags), \ - "i" (sizeof(struct bug_entry))); \ -} while (0) - -#else /* !CONFIG_DEBUG_BUGVERBOSE */ -#define _BUG_FLAGS (ins, flags) \ do { \ - asm volatile("1:\t" ins "\n" \ - ".pushsection __bug_table,\"aw\"\n" \ - "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ - "\t.word %c0" "\t# bug_entry::flags\n" \ - "\t.org 2b+%c1\n" \ - ".popsection" \ - : : "i" (flags), \ + asm volatile("ASM_BUG ins=\"" ins "\" file=%c0 line=%c1 " \ + "flags=%c2 size=%c3" \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (flags), \ "i" (sizeof(struct bug_entry))); \ } while (0) -#endif /* CONFIG_DEBUG_BUGVERBOSE */ - -#else - -#define _BUG_FLAGS (ins, flags) asm volatile(ins) - -#endif /* CONFIG_GENERIC_BUG */ -#define HAVE_ARCH_BUG #define BUG () \ do { \
@@ -82,4 +46,54 @@ do { \#include <asm-generic/bug.h> +#else /* __ASSEMBLY__ */ + +#ifdef CONFIG_GENERIC_BUG + +#ifdef CONFIG_X86_32 +.macro __BUG_REL val:req + .long \val +.endm +#else +.macro __BUG_REL val:req + .long \val - 2b +.endm +#endif + +#ifdef CONFIG_DEBUG_BUGVERBOSE + +.macro ASM_BUG ins:req file:req line:req flags:req size:req +1: \ins + .pushsection __bug_table,"aw" +2: __BUG_REL val=1b # bug_entry::bug_addr + __BUG_REL val=\file # bug_entry::file + .word \line # bug_entry::line + .word \flags # bug_entry::flags + .org 2b+\size + .popsection +.endm + +#else /* !CONFIG_DEBUG_BUGVERBOSE */ + +.macro ASM_BUG ins:req file:req line:req flags:req size:req +1: \ins + .pushsection __bug_table,"aw" +2: __BUG_REL val=1b # bug_entry::bug_addr + .word \flags # bug_entry::flags + .org 2b+\size + .popsection +.endm + +#endif /* CONFIG_DEBUG_BUGVERBOSE */ + +#else /* CONFIG_GENERIC_BUG */ + +.macro ASM_BUG ins:req file:req line:req flags:req size:req + \ins +.endm + +#endif /* CONFIG_GENERIC_BUG */ + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_BUG_H */
arch/x86/kernel/macros.S +1 -0
@@ -9,3 +9,4 @@ #include <linux/compiler.h> #include <asm/refcount.h> #include <asm/alternative-asm.h> +#include <asm/bug.h>
include/asm-generic/bug.h +4 -4
@@ -17,10 +17,8 @@ #ifndef __ASSEMBLY__ #include <linux/kernel.h> -#ifdef CONFIG_BUG - -#ifdef CONFIG_GENERIC_BUG struct bug_entry { +#ifdef CONFIG_GENERIC_BUG #ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS unsigned long bug_addr; #else
@@ -35,8 +33,10 @@ struct bug_entry {unsigned short line;#endif unsigned short flags; -};#endif /* CONFIG_GENERIC_BUG */ +}; + +#ifdef CONFIG_BUG /* * Don't use BUG() or BUG_ON() unless there's really no way out; one
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/bug: Macrofy the BUG table section handling, to work around GCC inlining bugs
x86/bug: Macrofy the BUG table section handling, to work around GCC inlining bugs
Commit-ID: f81f8ad56fd1c7b99b2ed1c314527f7d9ac447c6 Gitweb: https://git.kernel.org/tip/f81f8ad56fd1c7b99b2ed1c314527f7d9ac447c6 Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:56 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 11:25:00 +0200
x86/bug: Macrofy the BUG table section handling, to work around GCC inlining bugs
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block. As a result GCC considers the inline assembly block as a single instruction. (Which it isn't, but that's the best we can get.)
This patch increases the kernel size:
text data bss dec hex filename 18146889 10225380 2957312 31329581 1de0d2d ./vmlinux before 18147336 10226688 2957312 31331336 1de1408 ./vmlinux after (+1755)
But enables more aggressive inlining (and probably better branch decisions).
The number of static text symbols in vmlinux is much lower:
Before: 40218
After: 40053 (-165)
The assembly code gets harder to read due to the extra macro layer.
[ mingo: Rewrote the changelog. ]
--- arch/x86/include/asm/bug.h | 98 ++++++++++++++++++++++++++-------------------- arch/x86/kernel/macros.S | 1 + include/asm-generic/bug.h | 8 ++-- 3 files changed, 61 insertions(+), 46 deletions(-)
arch/x86/include/asm/bug.h +56 -42
@@ -4,6 +4,8 @@#include <linux/stringify.h> +#ifndef __ASSEMBLY__ +/* * Despite that some emulators terminate on UD2, we use it for WARN(). *
@@ -20,53 +22,15 @@#define LEN_UD2 2 -#ifdef CONFIG_GENERIC_BUG - -#ifdef CONFIG_X86_32 -# define __BUG_REL (val) ".long " __stringify(val) -#else -# define __BUG_REL (val) ".long " __stringify(val) " - 2b" -#endif - -#ifdef CONFIG_DEBUG_BUGVERBOSE - -#define _BUG_FLAGS (ins, flags) \ -do { \ - asm volatile("1:\t" ins "\n" \ - ".pushsection __bug_table,\"aw\"\n" \ - "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ - "\t" __BUG_REL(%c0) "\t# bug_entry::file\n" \ - "\t.word %c1" "\t# bug_entry::line\n" \ - "\t.word %c2" "\t# bug_entry::flags\n" \ - "\t.org 2b+%c3\n" \ - ".popsection" \ - : : "i" (__FILE__), "i" (__LINE__), \ - "i" (flags), \ - "i" (sizeof(struct bug_entry))); \ -} while (0) - -#else /* !CONFIG_DEBUG_BUGVERBOSE */ -#define _BUG_FLAGS (ins, flags) \ do { \ - asm volatile("1:\t" ins "\n" \ - ".pushsection __bug_table,\"aw\"\n" \ - "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ - "\t.word %c0" "\t# bug_entry::flags\n" \ - "\t.org 2b+%c1\n" \ - ".popsection" \ - : : "i" (flags), \ + asm volatile("ASM_BUG ins=\"" ins "\" file=%c0 line=%c1 " \ + "flags=%c2 size=%c3" \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (flags), \ "i" (sizeof(struct bug_entry))); \ } while (0) -#endif /* CONFIG_DEBUG_BUGVERBOSE */ - -#else - -#define _BUG_FLAGS (ins, flags) asm volatile(ins) - -#endif /* CONFIG_GENERIC_BUG */ -#define HAVE_ARCH_BUG #define BUG () \ do { \
@@ -82,4 +46,54 @@ do { \#include <asm-generic/bug.h> +#else /* __ASSEMBLY__ */ + +#ifdef CONFIG_GENERIC_BUG + +#ifdef CONFIG_X86_32 +.macro __BUG_REL val:req + .long \val +.endm +#else +.macro __BUG_REL val:req + .long \val - 2b +.endm +#endif + +#ifdef CONFIG_DEBUG_BUGVERBOSE + +.macro ASM_BUG ins:req file:req line:req flags:req size:req +1: \ins + .pushsection __bug_table,"aw" +2: __BUG_REL val=1b # bug_entry::bug_addr + __BUG_REL val=\file # bug_entry::file + .word \line # bug_entry::line + .word \flags # bug_entry::flags + .org 2b+\size + .popsection +.endm + +#else /* !CONFIG_DEBUG_BUGVERBOSE */ + +.macro ASM_BUG ins:req file:req line:req flags:req size:req +1: \ins + .pushsection __bug_table,"aw" +2: __BUG_REL val=1b # bug_entry::bug_addr + .word \flags # bug_entry::flags + .org 2b+\size + .popsection +.endm + +#endif /* CONFIG_DEBUG_BUGVERBOSE */ + +#else /* CONFIG_GENERIC_BUG */ + +.macro ASM_BUG ins:req file:req line:req flags:req size:req + \ins +.endm + +#endif /* CONFIG_GENERIC_BUG */ + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_BUG_H */
arch/x86/kernel/macros.S +1 -0
@@ -9,3 +9,4 @@ #include <linux/compiler.h> #include <asm/refcount.h> #include <asm/alternative-asm.h> +#include <asm/bug.h>
include/asm-generic/bug.h +4 -4
@@ -17,10 +17,8 @@ #ifndef __ASSEMBLY__ #include <linux/kernel.h> -#ifdef CONFIG_BUG - -#ifdef CONFIG_GENERIC_BUG struct bug_entry { +#ifdef CONFIG_GENERIC_BUG #ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS unsigned long bug_addr; #else
@@ -35,8 +33,10 @@ struct bug_entry {unsigned short line;#endif unsigned short flags; -};#endif /* CONFIG_GENERIC_BUG */ +}; + +#ifdef CONFIG_BUG /* * Don't use BUG() or BUG_ON() unless there's really no way out; one
PATCH v9 7/10 x86: prevent inline distortion by paravirt ops
In reply to Nadav AmitGCC considers the number of statements in inlined assembly blocks, according to new-lines and semicolons, as an indication to the cost of the block in time and space. This data is distorted by the kernel code, which puts information in alternative sections. As a result, the compiler may perform incorrect inlining and branch optimizations.
The solution is to set an assembly macro and call it from the inlined assembly block. As a result GCC considers the inline assembly block as a single instruction.
The effect of the patch is a more aggressive inlining, which also causes a size increase of kernel.
text data bss dec hex filename
18147336 10226688 2957312 31331336 1de1408 ./vmlinux before 18162555 10226288 2957312 31346155 1de4deb ./vmlinux after (+14819)
Static text symbols:
Before: 40053
After: 39942 (-111)
--- arch/x86/include/asm/paravirt_types.h | 56 +++++++++++++-------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 28 insertions(+), 29 deletions(-)
arch/x86/include/asm/paravirt_types.h +27 -29
@@ -346,23 +346,11 @@ extern struct pv_lock_ops pv_lock_ops;#define paravirt_clobber (clobber) \ [paravirt_clobber] "i" (clobber) -/* -* Generate some code, and mark it as patchable by the -* apply_paravirt() alternate instruction patcher. -*/ -#define _paravirt_alt (insn_string, type, clobber) \ - "771:\n\t" insn_string "\n" "772:\n" \ - ".pushsection .parainstructions,\"a\"\n" \ - _ASM_ALIGN "\n" \ - _ASM_PTR " 771b\n" \ - " .byte " type "\n" \ - " .byte 772b-771b\n" \ - " .short " clobber "\n" \ - ".popsection\n" -/* Generate patchable code, with the default asm parameters. */ -#define paravirt_alt (insn_string) \ - _paravirt_alt(insn_string, "%c[paravirt_typenum]", "%c[paravirt_clobber]") +#define paravirt_call \ + "PARAVIRT_CALL type=\"%c[paravirt_typenum]\"" \ + " clobber=\"%c[paravirt_clobber]\"" \ + " pv_opptr=\"%c[paravirt_opptr]\";"/* Simple instruction patching code. */ #define NATIVE_LABEL (a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"
@@ -390,16 +378,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,int paravirt_disable_iospace (void ); -/* -* This generates an indirect call based on the operation type number. -* The type number, computed in PARAVIRT_PATCH, is derived from the -* offset into the paravirt_patch_template structure, and can therefore be -* freely converted back into a structure offset. -*/ -#define PARAVIRT_CALL \ - ANNOTATE_RETPOLINE_SAFE \ - "call *%c[paravirt_opptr];" -/* * These macros are intended to wrap calls through one of the paravirt * ops structs, so that they can be later identified and patched at
@@ -537,7 +515,7 @@ int paravirt_disable_iospace(void);/* since this condition will never hold */ \if (sizeof (rettype) >sizeof (unsigned long )) { \ asm volatile(pre \ - paravirt_alt(PARAVIRT_CALL) \ + paravirt_call \ post \ : call_clbr, ASM_CALL_CONSTRAINT \ : paravirt_type(op), \
@@ -547,7 +525,7 @@ int paravirt_disable_iospace(void); __ret = (rettype)((((u64 )__edx) <<32 ) | __eax); \ }else { \ asm volatile(pre \ - paravirt_alt(PARAVIRT_CALL) \ + paravirt_call \ post \ : call_clbr, ASM_CALL_CONSTRAINT \ : paravirt_type(op), \
@@ -574,7 +552,7 @@ int paravirt_disable_iospace(void);PVOP_VCALL_ARGS ; \PVOP_TEST_NULL (op); \ asm volatile(pre \ - paravirt_alt(PARAVIRT_CALL) \ + paravirt_call \ post \ : call_clbr, ASM_CALL_CONSTRAINT \ : paravirt_type(op), \
@@ -694,6 +672,26 @@ struct paravirt_patch_site {extern struct paravirt_patch_site __parainstructions[], __parainstructions_end[]; +#else /* __ASSEMBLY__ */ + +/* +* This generates an indirect call based on the operation type number. +* The type number, computed in PARAVIRT_PATCH, is derived from the +* offset into the paravirt_patch_template structure, and can therefore be +* freely converted back into a structure offset. +*/ +.macro PARAVIRT_CALL type:req clobber:req pv_opptr:req +771: ANNOTATE_RETPOLINE_SAFE + call *\pv_opptr +772: .pushsection .parainstructions,"a" + _ASM_ALIGN + _ASM_PTR 771b + .byte \type + .byte 772b-771b + .short \clobber + .popsection +.endm +#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_PARAVIRT_TYPES_H */
arch/x86/kernel/macros.S +1 -0
@@ -10,3 +10,4 @@ #include <asm/refcount.h> #include <asm/alternative-asm.h> #include <asm/bug.h> +#include <asm/paravirt.h>
Signature · 1 line
2.17.1
tip-bot for Nadav Amit
merge bot[tip:x86/build] x86/paravirt: Work around GCC inlining bugs when compiling paravirt ops
x86/paravirt: Work around GCC inlining bugs when compiling paravirt ops
Commit-ID: 494b5168f2de009eb80f198f668da374295098dd Gitweb: https://git.kernel.org/tip/494b5168f2de009eb80f198f668da374295098dd Author: Nadav Amit <[email protected]> AuthorDate: Wed, 3 Oct 2018 14:30:57 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Thu, 4 Oct 2018 11:25:00 +0200
x86/paravirt: Work around GCC inlining bugs when compiling paravirt ops
As described in:
77b0bf55bc67: ("kbuild/Makefile: Prepare for using macros in inline assembly code to work around asm() related GCC inlining bugs")
GCC's inlining heuristics are broken with common asm() patterns used in kernel code, resulting in the effective disabling of inlining.
The workaround is to set an assembly macro and call it from the inline assembly block. As a result GCC considers the inline assembly block as a single instruction. (Which it isn't, but that's the best we can get.)
In this patch we wrap the paravirt call section tricks in a macro, to hide it from GCC.
The effect of the patch is a more aggressive inlining, which also causes a size increase of kernel.
text data bss dec hex filename 18147336 10226688 2957312 31331336 1de1408 ./vmlinux before 18162555 10226288 2957312 31346155 1de4deb ./vmlinux after (+14819)
The number of static text symbols (non-inlined functions) goes down:
Before: 40053
After: 39942 (-111)
[ mingo: Rewrote the changelog. ]
--- arch/x86/include/asm/paravirt_types.h | 56 +++++++++++++++++------------------ arch/x86/kernel/macros.S | 1 + 2 files changed, 28 insertions(+), 29 deletions(-)
arch/x86/include/asm/paravirt_types.h +27 -29
@@ -346,23 +346,11 @@ extern struct pv_lock_ops pv_lock_ops;#define paravirt_clobber (clobber) \ [paravirt_clobber] "i" (clobber) -/* -* Generate some code, and mark it as patchable by the -* apply_paravirt() alternate instruction patcher. -*/ -#define _paravirt_alt (insn_string, type, clobber) \ - "771:\n\t" insn_string "\n" "772:\n" \ - ".pushsection .parainstructions,\"a\"\n" \ - _ASM_ALIGN "\n" \ - _ASM_PTR " 771b\n" \ - " .byte " type "\n" \ - " .byte 772b-771b\n" \ - " .short " clobber "\n" \ - ".popsection\n" -/* Generate patchable code, with the default asm parameters. */ -#define paravirt_alt (insn_string) \ - _paravirt_alt(insn_string, "%c[paravirt_typenum]", "%c[paravirt_clobber]") +#define paravirt_call \ + "PARAVIRT_CALL type=\"%c[paravirt_typenum]\"" \ + " clobber=\"%c[paravirt_clobber]\"" \ + " pv_opptr=\"%c[paravirt_opptr]\";"/* Simple instruction patching code. */ #define NATIVE_LABEL (a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"
@@ -390,16 +378,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,int paravirt_disable_iospace (void ); -/* -* This generates an indirect call based on the operation type number. -* The type number, computed in PARAVIRT_PATCH, is derived from the -* offset into the paravirt_patch_template structure, and can therefore be -* freely converted back into a structure offset. -*/ -#define PARAVIRT_CALL \ - ANNOTATE_RETPOLINE_SAFE \ - "call *%c[paravirt_opptr];" -/* * These macros are intended to wrap calls through one of the paravirt * ops structs, so that they can be later identified and patched at
@@ -537,7 +515,7 @@ int paravirt_disable_iospace(void);/* since this condition will never hold */ \if (sizeof (rettype) >sizeof (unsigned long )) { \ asm volatile(pre \ - paravirt_alt(PARAVIRT_CALL) \ + paravirt_call \ post \ : call_clbr, ASM_CALL_CONSTRAINT \ : paravirt_type(op), \
@@ -547,7 +525,7 @@ int paravirt_disable_iospace(void); __ret = (rettype)((((u64 )__edx) <<32 ) | __eax); \ }else { \ asm volatile(pre \ - paravirt_alt(PARAVIRT_CALL) \ + paravirt_call \ post \ : call_clbr, ASM_CALL_CONSTRAINT \ : paravirt_type(op), \
@@ -574,7 +552,7 @@ int paravirt_disable_iospace(void);PVOP_VCALL_ARGS ; \PVOP_TEST_NULL (op); \ asm volatile(pre \ - paravirt_alt(PARAVIRT_CALL) \ + paravirt_call \ post \ : call_clbr, ASM_CALL_CONSTRAINT \ : paravirt_type(op), \
@@ -694,6 +672,26 @@ struct paravirt_patch_site {extern struct paravirt_patch_site __parainstructions[], __parainstructions_end[]; +#else /* __ASSEMBLY__ */ + +/* +* This generates an indirect call based on the operation type number. +* The type number, computed in PARAVIRT_PATCH, is derived from the +* offset into the paravirt_patch_template structure, and can therefore be +* freely converted back into a structure offset. +*/ +.macro PARAVIRT_CALL type:req clobber:req pv_opptr:req +771: ANNOTATE_RETPOLINE_SAFE + call *\pv_opptr +772: .pushsection .parainstructions,"a" + _ASM_ALIGN + _ASM_PTR 771b + .byte \type + .byte 772b-771b + .short \clobber + .popsection +.endm +#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_PARAVIRT_TYPES_H */
arch/x86/kernel/macros.S +1 -0
@@ -10,3 +10,4 @@ #include <asm/refcount.h> #include <asm/alternative-asm.h> #include <asm/bug.h> +#include <asm/paravirt.h>
PATCH v9 8/10 x86: extable: use macros instead of inline assembly
In reply to Nadav AmitUse assembly macros for exception-tables and call them from inline assembly. This not only makes the code more readable and allows to avoid the duplicate implementation, but also improves compilation decision, specifically inline decisions which GCC base on the number of new lines in inline assembly.
text data bss dec hex filename
18162555 10226288 2957312 31346155 1de4deb ./vmlinux before 18162879 10226256 2957312 31346447 1de4f0f ./vmlinux after (+292)
This allows to inline functions such as nested_vmx_exit_reflected(), set_segment_reg(), __copy_xstate_to_user().
--- arch/x86/include/asm/asm.h | 61 +++++++++++++++++--------------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 28 insertions(+), 34 deletions(-)
arch/x86/include/asm/asm.h +27 -34
@@ -117,28 +117,44 @@# define CC_OUT (c) [_cc_ ## c] "=qm"#endif -/* Exception table entry */ #ifdef __ASSEMBLY__# define _ASM_EXTABLE_HANDLE (from, to, handler) \ - .pushsection "__ex_table","a" ; \ - .balign 4 ; \ - .long (from) - . ; \ - .long (to) - . ; \ - .long (handler) - . ; \ - .popsection + ASM_EXTABLE_HANDLE from to handler + +#else /* __ASSEMBLY__ */ + +# define _ASM_EXTABLE_HANDLE (from, to, handler) \ + "ASM_EXTABLE_HANDLE from=" #from " to=" #to \ + " handler=\"" #handler "\"\n\t" + +/* For C file, we already have NOKPROBE_SYMBOL macro */ + +#endif /* __ASSEMBLY__ */ -# define _ASM_EXTABLE (from, to) \ +#define _ASM_EXTABLE (from, to) \ _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) -# define _ASM_EXTABLE_FAULT (from, to) \ +#define _ASM_EXTABLE_FAULT (from, to) \ _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) -# define _ASM_EXTABLE_EX (from, to) \ +#define _ASM_EXTABLE_EX (from, to) \ _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext) -# define _ASM_EXTABLE_REFCOUNT (from, to) \ +#define _ASM_EXTABLE_REFCOUNT (from, to) \ _ASM_EXTABLE_HANDLE(from, to, ex_handler_refcount) +/* Exception table entry */ +#ifdef __ASSEMBLY__ + +.macro ASM_EXTABLE_HANDLE from:req to:req handler:req + .pushsection "__ex_table","a" + .balign 4 + .long (\from) - . + .long (\to) - . + .long (\handler) - . + .popsection +.endm +# define _ASM_NOKPROBE (entry) \ .pushsection "_kprobe_blacklist","aw" ; \ _ASM_ALIGN ; \
@@ -169,29 +185,6 @@_ASM_EXTABLE (101b ,103b ) .endm -#else -# define _EXPAND_EXTABLE_HANDLE (x) #x -# define _ASM_EXTABLE_HANDLE (from, to, handler) \ - " .pushsection \"__ex_table\",\"a\"\n" \ - " .balign 4\n" \ - " .long (" #from ") - .\n" \ - " .long (" #to ") - .\n" \ - " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n" \ - " .popsection\n" - -# define _ASM_EXTABLE (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_default) - -# define _ASM_EXTABLE_FAULT (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault) - -# define _ASM_EXTABLE_EX (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext) - -# define _ASM_EXTABLE_REFCOUNT (from, to) \ - _ASM_EXTABLE_HANDLE(from, to, ex_handler_refcount) - -/* For C file, we already have NOKPROBE_SYMBOL macro */ #endif #ifndef __ASSEMBLY__
arch/x86/kernel/macros.S +1 -0
@@ -11,3 +11,4 @@ #include <asm/alternative-asm.h> #include <asm/bug.h> #include <asm/paravirt.h> +#include <asm/asm.h>
Signature · 1 line
2.17.1
PATCH v9 9/10 x86: cpufeature: use macros instead of inline assembly
In reply to Nadav AmitUse assembly macros for static_cpu_has() and call them from inline assembly. This not only makes the code more readable, but also improves compilation decision, specifically inline decisions which GCC base on the number of new lines in inline assembly.
The patch slightly increases the kernel size:
text data bss dec hex filename
18162879 10226256 2957312 31346447 1de4f0f ./vmlinux before 18163528 10226300 2957312 31347140 1de51c4 ./vmlinux after (+693)
And enables the inlining of function such as free_ldt_pgtables().
--- arch/x86/include/asm/cpufeature.h | 82 ++++++++++++++++++------------- arch/x86/kernel/macros.S | 1 + 2 files changed, 48 insertions(+), 35 deletions(-)
arch/x86/include/asm/cpufeature.h +47 -35
@@ -2,10 +2,10 @@#ifndef _ASM_X86_CPUFEATURE_H#define _ASM_X86_CPUFEATURE_H -#include <asm/processor.h> - -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#include <asm/processor.h> #include <asm/asm.h> #include <linux/bitops.h>
@@ -161,37 +161,10 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);*/ static __always_inline __pure bool _static_cpu_has(u16 bit) { - asm_volatile_goto("1: jmp 6f\n" - "2:\n" - ".skip -(((5f-4f) - (2b-1b)) > 0) * " - "((5f-4f) - (2b-1b)),0x90\n" - "3:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 4f - .\n" /* repl offset */ - " .word %P[always]\n" /* always replace */ - " .byte 3b - 1b\n" /* src len */ - " .byte 5f - 4f\n" /* repl len */ - " .byte 3b - 2b\n" /* pad len */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "4: jmp %l[t_no]\n" - "5:\n" - ".previous\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 0\n" /* no replacement */ - " .word %P[feature]\n" /* feature bit */ - " .byte 3b - 1b\n" /* src len */ - " .byte 0\n" /* repl len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .altinstr_aux,\"ax\"\n" - "6:\n" - " testb %[bitnum],%[cap_byte]\n" - " jnz %l[t_yes]\n" - " jmp %l[t_no]\n" - ".previous\n" + asm_volatile_goto("STATIC_CPU_HAS bitnum=%[bitnum] " + "cap_byte=\"%[cap_byte]\" " + "feature=%P[feature] t_yes=%l[t_yes] " + "t_no=%l[t_no] always=%P[always]" : : [feature] "i" (bit), [always] "i" (X86_FEATURE_ALWAYS), [bitnum] "i" (1 << (bit & 7)),
@@ -226,5 +199,44 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ boot_cpu_data.x86_model -#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ +#else /* __ASSEMBLY__ */ + +.macro STATIC_CPU_HAS bitnum:req cap_byte:req feature:req t_yes:req t_no:req always:req +1: + jmp 6f +2: + .skip -(((5f-4f) - (2b-1b)) > 0) * ((5f-4f) - (2b-1b)),0x90 +3: + .section .altinstructions,"a" + .long 1b - . /* src offset */ + .long 4f - . /* repl offset */ + .word \always /* always replace */ + .byte 3b - 1b /* src len */ + .byte 5f - 4f /* repl len */ + .byte 3b - 2b /* pad len */ + .previous + .section .altinstr_replacement,"ax" +4: + jmp \t_no +5: + .previous + .section .altinstructions,"a" + .long 1b - . /* src offset */ + .long 0 /* no replacement */ + .word \feature /* feature bit */ + .byte 3b - 1b /* src len */ + .byte 0 /* repl len */ + .byte 0 /* pad len */ + .previous + .section .altinstr_aux,"ax" +6: + testb \bitnum,\cap_byte + jnz \t_yes + jmp \t_no + .previous +.endm + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ #endif /* _ASM_X86_CPUFEATURE_H */
arch/x86/kernel/macros.S +1 -0
@@ -12,3 +12,4 @@ #include <asm/bug.h> #include <asm/paravirt.h> #include <asm/asm.h> +#include <asm/cpufeature.h>
Signature · 1 line
2.17.1
PATCH v9 10/10 x86: jump-labels: use macros instead of inline assembly
In reply to Nadav AmitUse assembly macros for jump-labels and call them from inline assembly. This not only makes the code more readable, but also improves compilation decision, specifically inline decisions which GCC base on the number of new lines in inline assembly.
As a result the code size is slightly increased.
text data bss dec hex filename
18163528 10226300 2957312 31347140 1de51c4 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+1128)
And functions such as intel_pstate_adjust_policy_max(), kvm_cpu_accept_dm_intr(), kvm_register_readl() are inlined.
--- arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/jump_label.h | 77 +++++++++++-------------------- arch/x86/kernel/macros.S | 1 + 3 files changed, 30 insertions(+), 50 deletions(-)
arch/x86/entry/calling.h +1 -1
@@ -338,7 +338,7 @@ For 32-bit we have the following conventions - kernel is built with .macro CALL_enter_from_user_mode#ifdef CONFIG_CONTEXT_TRACKING #ifdef HAVE_JUMP_LABEL - STATIC_JUMP_IF_FALSE .Lafter_call_\@, context_tracking_enabled, def=0 + STATIC_BRANCH_JMP l_yes=.Lafter_call_\@, key=context_tracking_enabled, branch=1#endif call enter_from_user_mode .Lafter_call_\@:
arch/x86/include/asm/jump_label.h +28 -49
113 lines not on this page · raw message
arch/x86/kernel/macros.S +1 -0
@@ -13,3 +13,4 @@ #include <asm/paravirt.h> #include <asm/asm.h> #include <asm/cpufeature.h> +#include <asm/jump_label.h>
Signature · 1 line
2.17.1
Borislav Petkov
maintainerPROPOSAL: Extend inline asm syntax with size spec
In reply to Nadav AmitHi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost estimation heuristic which counts lines, I think, for example like in this here macro:
the resulting code ends up not inlining the functions themselves which use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));
with which user can tell gcc what the size of that inline asm statement is and thus allow for more precise cost estimation and in the end better inlining.
And FWIW 3) looks pretty straight-forward to me because attributes are pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thx.
Quoted 148 lines · Nadav Amit
This patch-set deals with an interesting yet stupid problem: kernel code that does not get inlined despite its simplicity. There are several causes for this behavior: "cold" attribute on
__init, different function optimization levels; conditional constant computations based on__builtin_constant_p(); and finally large inline assembly blocks.This patch-set deals with the inline assembly problem. I separated these patches from the others (that were sent in the RFC) for easier inclusion. I also separated the removal of unnecessary new-lines which would be sent separately.
The problem with inline assembly is that inline assembly is often used by the kernel for things that are other than code - for example, assembly directives and data. GCC however is oblivious to the content of the blocks and assumes their cost in space and time is proportional to the number of the perceived assembly "instruction", according to the number of newlines and semicolons. Alternatives, paravirt and other mechanisms are affected, causing code not to be inlined, and degrading compilation quality in general.
The solution that this patch-set carries for this problem is to create an assembly macro, and then call it from the inline assembly block. As a result, the compiler sees a single "instruction" and assigns the more appropriate cost to the code.
To avoid uglification of the code, as many noted, the macros are first precompiled into an assembly file, which is later assembled together with the C files. This also enables to avoid duplicate implementation that was set before for the asm and C code. This can be seen in the exception table changes.
Overall this patch-set slightly increases the kernel size (my build was done using my Ubuntu 18.04 config + localyesconfig for the record):
text data bss dec hex filename
18140829 10224724 2957312 31322865 1ddf2f1 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+0.1%)The number of static functions in the image is reduced by 379, but actually inlining is even better, which does not always shows in these
numbers: a function may be inlined causing the calling function not to be inlined.I ran some limited number of benchmarks, and in general the performance impact is not very notable. You can still see >10 cycles shaved off some syscalls that manipulate page-tables (e.g.,
mprotect()), in which paravirt caused many functions not to be inlined. In addition this patch-set can prevent issues such as [1], and improves code readability and maintainability.Update: Rasmus recently caused me (inadvertently) to become paranoid about the dependencies. To clarify: if any of the headers changes, any c file which uses macros that are included in
macros.Swould be fine as long as it includes the header as well (as it should). Adding an assertion to check this is done might become slightly ugly, and nobody else is concerned about it. Another minor issue is that changes ofmacros.Swould not trigger a global rebuild, but that is pretty similar to changes of theMakefilethat do not trigger a rebuild.[1] https://patchwork.kernel.org/patch/10450037/
v8->v9: * Restoring the '-pipe' parameter (Rasmus)
* Adding Kees's tested-by tag (Kees)
v7->v8: * Add acks (Masahiro, Max)
* Rebase on 4.19 (Ingo)
v6->v7: * Fix context switch tracking (Ingo)
* Fix xtensa build error (Ingo)
* Rebase on 4.18-rc8
v5->v6: * Removing more code from jump-labels (PeterZ)
* Fix build issue on i386 (0-day, PeterZ)
v4->v5: *Makefilefixes (Masahiro, Sam)
v3->v4: * Changed naming of macros in 2 patches (PeterZ)
* Minor cleanup of the paravirt patch
v2->v3: * Several build issues resolved (0-day)
* Wrong comments fix (Josh)
* Change asm vs C order in refcount (Kees)
v1->v2: * Compiling the macros into a separate .s file, improving
readability (Linus)
* Improving assembly formatting, applying most of the comments according to my judgment (Jan)
* Adding exception-table, cpufeature and jump-labels
* Removing new-line cleanup; to be submitted separatelyCc Masahiro Yamada <[email protected]>Cc Sam Ravnborg <[email protected]>Cc Alok Kataria <[email protected]>Cc Christopher Li <[email protected]>Cc Greg Kroah-Hartman <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Ingo Molnar <[email protected]>Cc Jan Beulich <[email protected]>Cc Josh Poimboeuf <[email protected]>Cc Juergen Gross <[email protected]>Cc Kate Stewart <[email protected]>Cc Kees Cook <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Philippe Ombredanne <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Linus Torvalds <[email protected]>Cc Chris Zankel <[email protected]>Cc Max Filippov <[email protected]>Nadav Amit (10):
xtensa: definingLINKER_SCRIPTfor the linker script
Makefile: Prepare for using macros for inline asm
x86: objtool: use asm macro for better compiler decisions
x86: refcount: prevent gcc distortions
x86: alternatives: macrofy locks for better inlining
x86: bug: prevent gcc distortions
x86: prevent inline distortion by paravirt ops
x86: extable: use macros instead of inline assembly
x86: cpufeature: use macros instead of inline assembly
x86: jump-labels: use macros instead of inline assemblyMakefile | 9 ++- arch/x86/Makefile | 7 ++ arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/alternative-asm.h | 20 ++++-- arch/x86/include/asm/alternative.h | 11 +-- arch/x86/include/asm/asm.h | 61 +++++++--------- arch/x86/include/asm/bug.h | 98 +++++++++++++++----------- arch/x86/include/asm/cpufeature.h | 82 ++++++++++++--------- arch/x86/include/asm/jump_label.h | 77 ++++++++------------ arch/x86/include/asm/paravirt_types.h | 56 +++++++-------- arch/x86/include/asm/refcount.h | 74 +++++++++++-------- arch/x86/kernel/macros.S | 16 +++++ arch/xtensa/kernel/Makefile | 4 +- include/asm-generic/bug.h | 8 +-- include/linux/compiler.h | 56 +++++++++++---- scripts/Kbuild.include | 4 +- scripts/mod/Makefile | 2 + 17 files changed, 331 insertions(+), 256 deletions(-) create mode 100644 arch/x86/kernel/macros.SSignature · 1 line
2.17.1
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 3 lines · Borislav Petkov
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
GCC already estimates the *size* of inline asm, and this is required *for correctness*. So any workaround that works against this will only end in tears.
Taking size as an estimate of cost is not very good. But in your motivating example you actually *do* care mostly about size, namely, for the inlining decisions.
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
Quoted 3 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
Quoted 1 line
2) asm ("..." : : : : <size-expr>)
This potentially conflicts with the syntax for asm goto.
Quoted 1 line
3) asm ("...") __attribute__((asm_size(<size-expr>)));
Eww.
Quoted 3 lines
with which user can tell gcc what the size of that inline asm statement is and thus allow for more precise cost estimation and in the end better inlining.
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Quoted 2 lines
And FWIW 3) looks pretty straight-forward to me because attributes are pretty common anyways.
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
Segher
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 2 lines · Segher Boessenkool
GCC already estimates the *size* of inline asm, and this is required *for correctness*.
I didn't say it didn't - but the heuristic could use improving.
Quoted 3 lines
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
Well, the size thing could be just a "parameter" or "hint" of sorts, to tell gcc to inline the function X which is inlining the asm statement into the function Y which is calling function X. If you look at the patchset, it is moving everything to asm macros where gcc is apparently able to do better inlining.
Quoted 3 lines
Quoted 1 line
3) asm ("...") __attribute__((asm_size(<size-expr>)));
Eww.
Why?
Quoted 2 lines
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Yes.
Another option would be if gcc parses the inline asm directly and does a more precise size estimation. Which is a lot more involved and complicated solution so I guess we wanna look at the simpler ones first.
:-)
Quoted 3 lines
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
Or simply "this asm statement has a size of 1" to mean, inline it everywhere. Which has the same caveats as above.
Quoted 3 lines
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
I'm afraid they're more than a few and this should work automatically, if possible.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 5 lines · Borislav Petkov
Quoted 2 lines · Segher Boessenkool
GCC already estimates the *size* of inline asm, and this is required *for correctness*.
I didn't say it didn't - but the heuristic could use improving.
How? It is as sharp an estimate as can be *already*: number of insns times maximum size per insn.
If you get this wrong, conditional branches (and similar things, but conditional branches usually hit first, and hurt most) will stop working correctly, unless binutils uses relaxation for those on your architecture (most don't).
Quoted 9 lines
Quoted 3 lines
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
Well, the size thing could be just a "parameter" or "hint" of sorts, to tell gcc to inline the function X which is inlining the asm statement into the function Y which is calling function X. If you look at the patchset, it is moving everything to asm macros where gcc is apparently able to do better inlining.
Yes, that will cause fewer problems I think: do not override size _at all_, but give a hint to the inliner.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
3) asm ("...") __attribute__((asm_size(<size-expr>)));
Eww.
Why?
Attributes are clumsy and clunky and kludgy.
It never is well-defined how attributes interact, and the more attributes we define and use, the more that matters.
Quoted 10 lines
Quoted 2 lines
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Yes.
Another option would be if gcc parses the inline asm directly and does a more precise size estimation. Which is a lot more involved and complicated solution so I guess we wanna look at the simpler ones first.
:-)
Which is *impossible* to do. Inline assembler is free-form text.
Quoted 6 lines
Quoted 3 lines
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
Or simply "this asm statement has a size of 1" to mean, inline it everywhere. Which has the same caveats as above.
"Has minimum length" then (size 1 cannot work on most archs).
Quoted 6 lines
Quoted 3 lines
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
I'm afraid they're more than a few and this should work automatically, if possible.
Would counting *all* asms as having minimum length for inlining decisions work? Will that give bad side effects?
Or since this problem is quite specific to x86, maybe some target hook is wanted? Things work quite well elsewhere as-is, degrading that is not a good idea.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 5 lines · Segher Boessenkool
Quoted 5 lines
Quoted 2 lines
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Yes.
Quoted 7 lines
Quoted 5 lines
Another option would be if gcc parses the inline asm directly and does a more precise size estimation. Which is a lot more involved and complicated solution so I guess we wanna look at the simpler ones first.
:-)
Which is *impossible* to do. Inline assembler is free-form text.
"Impossible" is false: only under GCC's model and semantics of inline asm that is, and only under the (false) assumption that the semantics of the asm statement (which is a GCC extension to begin with) cannot be changed like it has been changed multiple times in the past.
"Difficult", "not worth our while", perhaps.
Thanks,
Ingo
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 12 lines · Ingo Molnar
Quoted 11 lines · Segher Boessenkool
Quoted 10 lines
Quoted 2 lines
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Yes.
Another option would be if gcc parses the inline asm directly and does a more precise size estimation. Which is a lot more involved and complicated solution so I guess we wanna look at the simpler ones first.
:-)
Quoted 8 lines
Quoted 1 line
Which is *impossible* to do. Inline assembler is free-form text.
"Impossible" is false: only under GCC's model and semantics of inline asm that is, and only under the (false) assumption that the semantics of the asm statement (which is a GCC extension to begin with) cannot be changed like it has been changed multiple times in the past.
"Difficult", "not worth our while", perhaps.
If we throw out our current definition of inline assembler, and of the internal backend interfaces, then sure you can do it. This of course invalidates all code that uses GCC inline assembler, and all GCC backends (both in-tree and out-of-tree, both current and historical).
If other compilers think everyone should rewrite all of their code because those compiler do inline asm wro^H^H^Hdifferently, that is their problem; GCC should not deny all history and screw over all its users.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 5 lines · Segher Boessenkool
Quoted 5 lines
Quoted 2 lines
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Yes.
Quoted 7 lines
Quoted 5 lines
Another option would be if gcc parses the inline asm directly and does a more precise size estimation. Which is a lot more involved and complicated solution so I guess we wanna look at the simpler ones first.
:-)
Which is *impossible* to do. Inline assembler is free-form text.
"Impossible" is false: only under GCC's model and semantics of inline asm that is, and only under the (false) assumption that the semantics of the asm statement (which is a GCC extension to begin with) cannot be changed like it has been changed multiple times in the past.
"Difficult", "not worth our while", perhaps.
Thanks,
Ingo
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 2 lines · Segher Boessenkool
GCC already estimates the *size* of inline asm, and this is required *for correctness*.
I didn't say it didn't - but the heuristic could use improving.
Quoted 3 lines
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
Well, the size thing could be just a "parameter" or "hint" of sorts, to tell gcc to inline the function X which is inlining the asm statement into the function Y which is calling function X. If you look at the patchset, it is moving everything to asm macros where gcc is apparently able to do better inlining.
Quoted 3 lines
Quoted 1 line
3) asm ("...") __attribute__((asm_size(<size-expr>)));
Eww.
Why?
Quoted 2 lines
More precise *size* estimates, yes. And if the user lies he should not be surprised to get assembler errors, etc.
Yes.
Another option would be if gcc parses the inline asm directly and does a more precise size estimation. Which is a lot more involved and complicated solution so I guess we wanna look at the simpler ones first.
:-)
Quoted 3 lines
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
Or simply "this asm statement has a size of 1" to mean, inline it everywhere. Which has the same caveats as above.
Quoted 3 lines
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
I'm afraid they're more than a few and this should work automatically, if possible.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolHi Segher,
Quoted 8 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
GCC already estimates the *size* of inline asm, and this is required *for correctness*. So any workaround that works against this will only end in tears.
You're right and wrong. GCC can't even estimate the size of mildly complicated inline asms right now, so your claim of it being necessary for correctness can't be true in this absolute form. I know what you try to say, but still, consider inline asms like this:
insn1
.section bla
insn2
.previous
or
invoke_asm_macro foo,bar
in both cases GCCs size estimate will be wrong however you want to count it. This is actually the motivating example for the kernel guys, the games they play within their inline asms make the estimates be wildly wrong to a point it interacts with the inliner.
Quoted 3 lines
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
No, see above, even if we were to improve the size estimates (e.g. based on some average instruction size) the kernel examples would still be off because they switch sections back and forth, use asm macros and computed .fill directives and maybe further stuff. GCC will never be able to accurately calculate these sizes (without an built-in assembler which hopefully noone proposes).
So, there is a case for extending the inline-asm facility to say "size is complicated here, assume this for inline decisions".
Quoted 5 lines
Quoted 3 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
Quoted 3 lines
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
TBH, I like the inline asm (...) suggestion most currently, but what if we want to add more attributes to asms? We could add further special keywords to the clobber list:
asm ("...." : : : "cc,memory,inline");
sure, it might seem strange to "clobber" inline, but if we reinterpret the clobber list as arbitrary set of attributes for this asm, it'd be fine.
Quoted 3 lines
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
I think the examples I saw from Boris were all indirect inlines:
static inline void foo() { asm("large-looking-but-small-asm"); } static void bar1() { ... foo() ... }
static void bar2() { ... foo() ... }
void goo (void) { bar1(); } // bar1 should have been inlined
So, while the immediate asm user was marked as always inline that in turn caused users of it to become non-inlined. I'm assuming the kernel guys did proper measurements that they _really_ get some non-trivial speed benefit by inlining bar1/bar2, but for some reasons (I didn't inquire) didn't want to mark them all as inline as well.
Ciao,
Michael.
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 1 line · Michael Matz
(without an built-in assembler which hopefully noone proposes).
There are disadvantages (the main one is having to implement it), but a built-in assembler has numerous advantages as well:
- Better optimizations: for example -Os could more accurately estimate true instruction size.
- Better inlining: as the examples in this thread are showing.
- Better padding/alignment: right now GCC has no notion about the precise cache layout of the assembly code it generates and the code alignment options it has are crude. It got away with this so far because the x86 rule of thumb is that dense code is usually the right choice.
- Better compiler performance: it would be faster as well to immediately emit assembly instructions, just like GCC's preprocessor library use speeds up compilation *significantly* instead of creating a separate preprocessor task.
- Better future integration of assembly blocks: GCC could begin to actually understand the assembly statements in inline asm and allow more user-friendly extensions to its historically complex and difficult to master inline asm syntax.
I mean, it's a fact that the GNU project has *already* defined their own assembly syntax which departs from decades old platform assembly syntax - and how the assembler is called by the compiler is basically an implementation detail, not a conceptual choice. The random multi-process unidirectional assembler choice of the past should not be treated as orthodoxy.
Thanks,
Ingo
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 6 lines · Ingo Molnar
Quoted 1 line · Michael Matz
(without an built-in assembler which hopefully noone proposes).
There are disadvantages (the main one is having to implement it), but a built-in assembler has numerous advantages as well:
- Better optimizations: for example -Os could more accurately estimate true instruction size.
GCC already knows the exact instruction size in almost all cases, for most backends. It is an advantage to not *have to* keep track of exact insn size in all cases.
Quoted 1 line
- Better inlining: as the examples in this thread are showing.
That's a red herring, the actual issue is inlining makes some spectacularly wrong decisions for code involving asm currently. That would not be solved by outputting binary code instead of assembler code. All those decisions are done long before code is output.
Quoted 2 lines
- Better padding/alignment: right now GCC has no notion about the precise cache layout of the assembly code it generates and the code alignment options it has are crude.
This isn't true. Maybe some targets do not care.
And of course GCC only knows this as far as it knows the alignments of the sections it outputs into; for example, ASLR is a nice performance killer at times. And if your linker scripts align sections to less than a cache line things do not look rosy either, etc.
Quoted 6 lines
It got away with
this so far because the x86 rule of thumb is that dense code is usually the right choice.- Better compiler performance: it would be faster as well to immediately emit assembly instructions, just like GCC's preprocessor library use speeds up compilation *significantly* instead of creating a separate preprocessor task.
So how much faster do you think it would be? Do you have actual numbers? And no, -O0 does not count.
Quoted 3 lines
- Better future integration of assembly blocks: GCC could begin to actually understand the assembly statements in inline asm and allow more user-friendly extensions to its historically complex and difficult to master inline asm syntax.
If you want to add a different kind of inline assembler, you can already. There is no need for outputting binary code for that.
Quoted 2 lines
I mean, it's a fact that the GNU project has *already* defined their own assembly syntax which departs from decades old platform assembly syntax
GCC's asm syntax is over three decades old itself. When it was defined all other C inline assembler syntaxes were much younger than that. I don't see what your argument is here.
Quoted 2 lines
- and how the assembler is called by the
compiler is basically an implementation detail, not a conceptual choice.
But the *format* of the interface representation, in this case textual assembler code, is quite fundamental.
Quoted 2 lines
The random
multi-process unidirectional assembler choice of the past should not be treated as orthodoxy.
Then I have good news for you: no assembler works that way these days, and that has been true for decades.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Michael MatzHi!
Quoted 20 lines · Michael Matz
Quoted 8 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
GCC already estimates the *size* of inline asm, and this is required *for correctness*. So any workaround that works against this will only end in tears.
You're right and wrong. GCC can't even estimate the size of mildly complicated inline asms right now, so your claim of it being necessary for correctness can't be true in this absolute form. I know what you try to say, but still, consider inline asms like this:
insn1
.section bla
insn2
.previous
Quoted 7 lines
or
invoke_asm_macrofoo,barin both cases GCCs size estimate will be wrong however you want to count it. This is actually the motivating example for the kernel guys, the games they play within their inline asms make the estimates be wildly wrong to a point it interacts with the inliner.
Right. The manual says:
"""
Some targets require that GCC track the size of each instruction used in order to generate correct code. Because the final length of the code produced by an @code{asm} statement is only known by the assembler, GCC must make an estimate as to how big it will be. It does this by counting the number of instructions in the pattern of the @code{asm} and multiplying that by the length of the longest instruction supported by that processor. (When working out the number of instructions, it assumes that any occurrence of a newline or of whatever statement separator character is supported by the assembler -- typically @samp{;} --- indicates the end of an instruction.)
Normally, GCC's estimate is adequate to ensure that correct code is generated, but it is possible to confuse the compiler if you use pseudo instructions or assembler macros that expand into multiple real instructions, or if you use assembler directives that expand to more space in the object file than is needed for a single instruction. If this happens then the assembler may produce a diagnostic saying that a label is unreachable.
"""
It *is* necessary for correctness, except you can do things that can confuse the compiler and then you are on your own anyway.
Quoted 9 lines
Quoted 3 lines
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
No, see above, even if we were to improve the size estimates (e.g. based on some average instruction size) the kernel examples would still be off because they switch sections back and forth, use asm macros and computed .fill directives and maybe further stuff. GCC will never be able to accurately calculate these sizes
What *is* such a size, anyway? If it can be spread over multiple sections (some of which support section merging), and you can have huge alignments, etc. What is needed here is not knowing the maximum size of the binary output (however you want to define that), but some way for the compiler to understand how bad it is to inline some assembler. Maybe manual direction, maybe just the current jeuristics can be tweaked a bit, maybe we need to invent some attribute or two.
Quoted 1 line
(without an built-in assembler which hopefully noone proposes).
Not me, that's for sure.
Quoted 2 lines
So, there is a case for extending the inline-asm facility to say "size is complicated here, assume this for inline decisions".
Yeah, that's an option. It may be too complicated though, or just not useful in its generality, so that everyone will use "1" (or "1 normal size instruction"), and then we are better off just making something for _that_ (or making it the default).
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 10 lines
Quoted 3 lines
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
TBH, I like the inline asm (...) suggestion most currently, but what if we want to add more attributes to asms? We could add further special keywords to the clobber list:
asm ("...." : : : "cc,memory,inline");
sure, it might seem strange to "clobber" inline, but if we reinterpret the clobber list as arbitrary set of attributes for this asm, it'd be fine.
All of a targets register names and alternative register names are allowed in the clobber list. Will that never conflict with an attribute name? We already *have* syntax for specifying attributes on an asm (on *any* statement even), so mixing these two things has no advantage.
Both "cc" and "memory" have their own problems of course, adding more things to this just feels bad. It may not be so bad ;-)
Quoted 11 lines
Quoted 3 lines
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
I think the examples I saw from Boris were all indirect inlines:
static inline void
foo(){asm("large-looking-but-small-asm"); } static voidbar1(){ ...foo()... }
static voidbar2(){ ...foo()... }
void goo (void) {bar1(); } // bar1 should have been inlined
Quoted 5 lines
So, while the immediate asm user was marked as always inline that in turn caused users of it to become non-inlined. I'm assuming the kernel guys did proper measurements that they _really_ get some non-trivial speed benefit by inlining bar1/bar2, but for some reasons (I didn't inquire) didn't want to mark them all as inline as well.
Yeah that makes sense, like if this happens with the fixup stuff, it will quickly spiral out of control.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 89 lines · Segher Boessenkool
Hi!
Quoted 20 lines · Michael Matz
Quoted 8 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
GCC already estimates the *size* of inline asm, and this is required *for correctness*. So any workaround that works against this will only end in tears.
You're right and wrong. GCC can't even estimate the size of mildly complicated inline asms right now, so your claim of it being necessary for correctness can't be true in this absolute form. I know what you try to say, but still, consider inline asms like this:
insn1
.section bla
insn2
.previousQuoted 7 lines
or
invoke_asm_macrofoo,barin both cases GCCs size estimate will be wrong however you want to count it. This is actually the motivating example for the kernel guys, the games they play within their inline asms make the estimates be wildly wrong to a point it interacts with the inliner.
Right. The manual says:
"""
Some targets require that GCC track the size of each instruction used in order to generate correct code. Because the final length of the code produced by an @code{asm} statement is only known by the assembler, GCC must make an estimate as to how big it will be. It does this by counting the number of instructions in the pattern of the @code{asm} and multiplying that by the length of the longest instruction supported by that processor. (When working out the number of instructions, it assumes that any occurrence of a newline or of whatever statement separator character is supported by the assembler -- typically @samp{;} --- indicates the end of an instruction.)Normally, GCC's estimate is adequate to ensure that correct code is generated, but it is possible to confuse the compiler if you use pseudo instructions or assembler macros that expand into multiple real instructions, or if you use assembler directives that expand to more space in the object file than is needed for a single instruction. If this happens then the assembler may produce a diagnostic saying that a label is unreachable.
"""It *is* necessary for correctness, except you can do things that can confuse the compiler and then you are on your own anyway.
Quoted 9 lines
Quoted 3 lines
So I guess the real issue is that the inline asm size estimate for x86 isn't very good (since it has to be pessimistic, and x86 insns can be huge)?
No, see above, even if we were to improve the size estimates (e.g. based on some average instruction size) the kernel examples would still be off because they switch sections back and forth, use asm macros and computed .fill directives and maybe further stuff. GCC will never be able to accurately calculate these sizes
What *is* such a size, anyway? If it can be spread over multiple sections (some of which support section merging), and you can have huge alignments, etc. What is needed here is not knowing the maximum size of the binary output (however you want to define that), but some way for the compiler to understand how bad it is to inline some assembler. Maybe manual direction, maybe just the current jeuristics can be tweaked a bit, maybe we need to invent some attribute or two.
Quoted 1 line
(without an built-in assembler which hopefully noone proposes).
Not me, that's for sure.
Quoted 2 lines
So, there is a case for extending the inline-asm facility to say "size is complicated here, assume this for inline decisions".
Yeah, that's an option. It may be too complicated though, or just not useful in its generality, so that everyone will use "1" (or "1 normal size instruction"), and then we are better off just making something for _that_ (or making it the default).
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Now, Richard suggested doing something like:
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
Quoted 11 lines
Quoted 10 lines
Quoted 3 lines
I don't like 2) either. But 1) looks interesting, depends what its semantics would be? "Don't count this insn's size for inlining decisions", maybe?
TBH, I like the inline asm (...) suggestion most currently, but what if we want to add more attributes to asms? We could add further special keywords to the clobber list:
asm ("...." : : : "cc,memory,inline");
sure, it might seem strange to "clobber" inline, but if we reinterpret the clobber list as arbitrary set of attributes for this asm, it'd be fine.
Quoted 4 lines
All of a targets register names and alternative register names are allowed in the clobber list. Will that never conflict with an attribute name? We already *have* syntax for specifying attributes on an asm (on *any* statement even), so mixing these two things has no advantage.
Heh, but I failed to make an example with attribute synatx working. IIRC attributes do not work on stmts. What could work is to use a #pragma though.
Richard.
Quoted 22 lines
Both "cc" and "memory" have their own problems of course, adding more things to this just feels bad. It may not be so bad ;-)
Quoted 11 lines
Quoted 3 lines
Another option is to just force inlining for those few functions where GCC currently makes an inlining decision you don't like. Or are there more than a few?
I think the examples I saw from Boris were all indirect inlines:
static inline void
foo(){asm("large-looking-but-small-asm"); } static voidbar1(){ ...foo()... }
static voidbar2(){ ...foo()... }
void goo (void) {bar1(); } // bar1 should have been inlinedQuoted 5 lines
So, while the immediate asm user was marked as always inline that in turn caused users of it to become non-inlined. I'm assuming the kernel guys did proper measurements that they _really_ get some non-trivial speed benefit by inlining bar1/bar2, but for some reasons (I didn't inquire) didn't want to mark them all as inline as well.
Yeah that makes sense, like if this happens with the fixup stuff, it will quickly spiral out of control.
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 8 lines · Richard Biener
Quoted 4 lines
All of a targets register names and alternative register names are allowed in the clobber list. Will that never conflict with an attribute name? We already *have* syntax for specifying attributes on an asm (on *any* statement even), so mixing these two things has no advantage.
Heh, but I failed to make an example with attribute synatx working. IIRC attributes do not work on stmts. What could work is to use a #pragma though.
Apparently statement attributes currently(?) only work for null statements. Oh well.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Richard BienerQuoted 10 lines · Richard Biener
Quoted 9 lines · Segher Boessenkool
Quoted 8 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Segher
gcc/c/c-parser.c +10 -2
@@ -6287,7 +6287,7 @@ static tree c_parser_asm_statement (c_parser *parser) {tree quals, str, outputs, inputs, clobbers, labels, ret; -bool simple, is_goto; +bool simple, is_goto, is_inline;location_t asm_loc =c_parser_peek_token (parser)->location;int section, nsections;
@@ -6318,6 +6318,13 @@ c_parser_asm_statement (c_parser *parser) is_goto = true; } + is_inline = false; +if (c_parser_next_token_is_keyword (parser,RID_INLINE )) + { +c_parser_consume_token (parser); + is_inline = true; + } +/* ??? Follow the C++ parser rather than using the lex_untranslated_string kludge. */ parser->lex_untranslated_string = true;
@@ -6393,7 +6400,8 @@ c_parser_asm_statement (c_parser *parser)c_parser_skip_to_end_of_block_or_statement (parser); ret =build_asm_stmt (quals,build_asm_expr (asm_loc, str, outputs, inputs, - clobbers, labels, simple)); + clobbers, labels, simple, + is_inline)); error: parser->lex_untranslated_string = false;
gcc/c/c-tree.h +2 -1
@@ -677,7 +677,8 @@ extern tree build_compound_literal (location_t, tree, tree, bool,extern void check_compound_literal_type (location_t ,struct c_type_name *);extern tree c_start_case (location_t ,location_t ,tree ,bool );extern void c_finish_case (tree ,tree ); -extern tree build_asm_expr (location_t ,tree ,tree ,tree ,tree ,tree ,bool ); +extern tree build_asm_expr (location_t ,tree ,tree ,tree ,tree ,tree ,bool , +bool );extern tree build_asm_stmt (tree ,tree );extern int c_types_compatible_p (tree ,tree );extern tree c_begin_compound_stmt (bool );
gcc/c/c-typeck.c +2 -1
@@ -10064,7 +10064,7 @@ build_asm_stmt (tree cv_qualifier, tree args)are subtly different. We use a ASM_EXPR node to represent this. */ tree build_asm_expr (location_t loc,tree string,tree outputs,tree inputs, -tree clobbers,tree labels,bool simple) +tree clobbers,tree labels,bool simple,bool is_inline) {tree tail;tree args;
@@ -10182,6 +10182,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,as volatile. */ ASM_INPUT_P (args) = simple;ASM_VOLATILE_P (args) = (noutputs ==0 ); +ASM_INLINE_P (args) = is_inline;return args; }
gcc/gimple-pretty-print.c +2 -0
@@ -2019,6 +2019,8 @@ dump_gimple_asm (pretty_printer *buffer, gasm *gs, int spc, dump_flags_t flags)pp_string (buffer,"__asm__" );if (gimple_asm_volatile_p (gs))pp_string (buffer," __volatile__" ); +if (gimple_asm_inline_p (gs)) +pp_string (buffer," __inline__" );if (gimple_asm_nlabels (gs))pp_string (buffer," goto" );pp_string (buffer,"(\"" );
gcc/gimple.h +23 -1
@@ -137,6 +137,7 @@ enum gimple_rhs_classenum gf_mask {GF_ASM_INPUT =1 <<0 ,GF_ASM_VOLATILE =1 <<1 , +GF_ASM_INLINE =1 <<2 ,GF_CALL_FROM_THUNK =1 <<0 ,GF_CALL_RETURN_SLOT_OPT =1 <<1 ,GF_CALL_TAILCALL =1 <<2 ,
@@ -3911,7 +3912,7 @@ gimple_asm_volatile_p (const gasm *asm_stmt) } -/* If VOLATLE_P is true, mark asm statement ASM_STMT as volatile. */ +/* If VOLATILE_P is true, mark asm statement ASM_STMT as volatile. */ static inline void gimple_asm_set_volatile (gasm *asm_stmt,bool volatile_p)
@@ -3923,6 +3924,27 @@ gimple_asm_set_volatile (gasm *asm_stmt, bool volatile_p) } +/* Return true ASM_STMT ASM_STMT is an asm statement marked inline. */ + +static inline bool +gimple_asm_inline_p (const gasm *asm_stmt) +{ +return (asm_stmt->subcode &GF_ASM_INLINE ) !=0 ; +} + + +/* If INLINE_P is true, mark asm statement ASM_STMT as inline. */ + +static inline void +gimple_asm_set_inline (gasm *asm_stmt,bool inline_p) +{ +if (inline_p) + asm_stmt->subcode |=GF_ASM_INLINE ; +else + asm_stmt->subcode &= ~GF_ASM_INLINE ; +} + +/* If INPUT_P is true, mark asm ASM_STMT as an ASM_INPUT. */ static inline void
gcc/gimplify.c +1 -0
@@ -6315,6 +6315,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)gimple_asm_set_volatile (stmt,ASM_VOLATILE_P (expr) || noutputs ==0 );gimple_asm_set_input (stmt,ASM_INPUT_P (expr)); +gimple_asm_set_inline (stmt,ASM_INLINE_P (expr));gimplify_seq_add_stmt (pre_p, stmt); }
gcc/ipa-icf-gimple.c +3 -0
@@ -993,6 +993,9 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)if (gimple_asm_input_p (g1) !=gimple_asm_input_p (g2))return false; +if (gimple_asm_inline_p (g1) !=gimple_asm_inline_p (g2)) +return false; +if (gimple_asm_ninputs (g1) !=gimple_asm_ninputs (g2))return false;
gcc/tree-inline.c +2 -0
@@ -4108,6 +4108,8 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)with very long asm statements. */ if (count >1000 ) count =1000 ; + if (gimple_asm_inline_p (as_a <gasm *> (stmt))) + count = !!count;return MAX (1 , count); }
gcc/tree.h +3 -0
@@ -1245,6 +1245,9 @@ extern tree maybe_wrap_with_location (tree, location_t);ASM_OPERAND with no operands. */ #define ASM_INPUT_P (NODE ) (ASM_EXPR_CHECK (NODE)->base.static_flag)#define ASM_VOLATILE_P (NODE ) (ASM_EXPR_CHECK (NODE)->base.public_flag) +/* Nonzero if we want to consider this asm as minimum length and cost +for inlining decisions. */ +#define ASM_INLINE_P (NODE ) (ASM_EXPR_CHECK (NODE)->base.protected_flag)/* COND_EXPR accessors. */ #define COND_EXPR_COND (NODE ) (TREE_OPERAND (COND_EXPR_CHECK (NODE), 0))
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 16 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Cool, thanks for implementing this!
In the kernel we'd likely wrap this in some "asm_inline()" type of construct to be compatible with older toolchains and other compilers.
Thanks,
Ingo
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 16 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Looks good. A few nits - you need to document this in extend.texi, the tree flag use needs documenting in tree-core.h, and we need a testcase (I'd suggest one that shows we inline a function with "large" asm inline () even at -Os).
Oh, and I don't think we want C and C++ to diverge - so you need to cook up C++ support as well.
Can kernel folks give this a second and third thought please so we don't implement sth that in the end won't satisfy you guys?
Thanks for doing this,
Richard.
Quoted 194 lines
Segher
gcc/c/c-parser.c +10
-2@@ -6287,7 +6287,7 @@ static tree c_parser_asm_statement (c_parser *parser) {tree quals, str, outputs, inputs, clobbers, labels, ret; -bool simple, is_goto; +bool simple, is_goto, is_inline;location_t asm_loc =c_parser_peek_token (parser)->location;int section, nsections;@@ -6318,6 +6318,13 @@ c_parser_asm_statement (c_parser *parser) is_goto = true; } + is_inline = false; +if (c_parser_next_token_is_keyword (parser,RID_INLINE )) + { +c_parser_consume_token (parser); + is_inline = true; + } +/* ??? Follow the C++ parser rather than using the lex_untranslated_string kludge. */ parser->lex_untranslated_string = true;@@ -6393,7 +6400,8 @@ c_parser_asm_statement (c_parser *parser)c_parser_skip_to_end_of_block_or_statement (parser); ret =build_asm_stmt (quals,build_asm_expr (asm_loc, str, outputs, inputs, - clobbers, labels, simple)); + clobbers, labels, simple, + is_inline)); error: parser->lex_untranslated_string = false;gcc/c/c-tree.h +2
-1@@ -677,7 +677,8 @@ extern tree build_compound_literal (location_t, tree, tree, bool,extern void check_compound_literal_type (location_t ,struct c_type_name *);extern tree c_start_case (location_t ,location_t ,tree ,bool );extern void c_finish_case (tree ,tree ); -extern tree build_asm_expr (location_t ,tree ,tree ,tree ,tree ,tree ,bool ); +extern tree build_asm_expr (location_t ,tree ,tree ,tree ,tree ,tree ,bool , +bool );extern tree build_asm_stmt (tree ,tree );extern int c_types_compatible_p (tree ,tree );extern tree c_begin_compound_stmt (bool );gcc/c/c-typeck.c +2
-1@@ -10064,7 +10064,7 @@ build_asm_stmt (tree cv_qualifier, tree args)are subtly different. We use a ASM_EXPR node to represent this. */ tree build_asm_expr (location_t loc,tree string,tree outputs,tree inputs, -tree clobbers,tree labels,bool simple) +tree clobbers,tree labels,bool simple,bool is_inline) {tree tail;tree args;@@ -10182,6 +10182,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,as volatile. */ ASM_INPUT_P (args) = simple;ASM_VOLATILE_P (args) = (noutputs ==0 ); +ASM_INLINE_P (args) = is_inline;return args; }gcc/gimple-pretty-print.c +2
-0@@ -2019,6 +2019,8 @@ dump_gimple_asm (pretty_printer *buffer, gasm *gs, int spc, dump_flags_t flags)pp_string (buffer,"__asm__" );if (gimple_asm_volatile_p (gs))pp_string (buffer," __volatile__" ); +if (gimple_asm_inline_p (gs)) +pp_string (buffer," __inline__" );if (gimple_asm_nlabels (gs))pp_string (buffer," goto" );pp_string (buffer,"(\"" );gcc/gimple.h +23
-1@@ -137,6 +137,7 @@ enum gimple_rhs_classenum gf_mask {GF_ASM_INPUT =1 <<0 ,GF_ASM_VOLATILE =1 <<1 , +GF_ASM_INLINE =1 <<2 ,GF_CALL_FROM_THUNK =1 <<0 ,GF_CALL_RETURN_SLOT_OPT =1 <<1 ,GF_CALL_TAILCALL =1 <<2 ,@@ -3911,7 +3912,7 @@ gimple_asm_volatile_p (const gasm *asm_stmt) } -/* If VOLATLE_P is true, mark asm statement ASM_STMT as volatile. */ +/* If VOLATILE_P is true, mark asm statement ASM_STMT as volatile. */ static inline void gimple_asm_set_volatile (gasm *asm_stmt,bool volatile_p)@@ -3923,6 +3924,27 @@ gimple_asm_set_volatile (gasm *asm_stmt, bool volatile_p) } +/* Return true ASM_STMT ASM_STMT is an asm statement marked inline. */ + +static inline bool +gimple_asm_inline_p (const gasm *asm_stmt) +{ +return (asm_stmt->subcode &GF_ASM_INLINE ) !=0 ; +} + + +/* If INLINE_P is true, mark asm statement ASM_STMT as inline. */ + +static inline void +gimple_asm_set_inline (gasm *asm_stmt,bool inline_p) +{ +if (inline_p) + asm_stmt->subcode |=GF_ASM_INLINE ; +else + asm_stmt->subcode &= ~GF_ASM_INLINE ; +} + +/* If INPUT_P is true, mark asm ASM_STMT as an ASM_INPUT. */ static inline voidgcc/gimplify.c +1
-0@@ -6315,6 +6315,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)gimple_asm_set_volatile (stmt,ASM_VOLATILE_P (expr) || noutputs ==0 );gimple_asm_set_input (stmt,ASM_INPUT_P (expr)); +gimple_asm_set_inline (stmt,ASM_INLINE_P (expr));gimplify_seq_add_stmt (pre_p, stmt); }gcc/ipa-icf-gimple.c +3
-0@@ -993,6 +993,9 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)if (gimple_asm_input_p (g1) !=gimple_asm_input_p (g2))return false; +if (gimple_asm_inline_p (g1) !=gimple_asm_inline_p (g2)) +return false; +if (gimple_asm_ninputs (g1) !=gimple_asm_ninputs (g2))return false;gcc/tree-inline.c +2
-0@@ -4108,6 +4108,8 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)with very long asm statements. */ if (count >1000 ) count =1000 ; + if (gimple_asm_inline_p (as_a <gasm *> (stmt))) + count = !!count;return MAX (1 , count); }gcc/tree.h +3
-0@@ -1245,6 +1245,9 @@ extern tree maybe_wrap_with_location (tree, location_t);ASM_OPERAND with no operands. */ #define ASM_INPUT_P (NODE ) (ASM_EXPR_CHECK (NODE)->base.static_flag)#define ASM_VOLATILE_P (NODE ) (ASM_EXPR_CHECK (NODE)->base.public_flag) +/* Nonzero if we want to consider this asm as minimum length and cost +for inlining decisions. */ +#define ASM_INLINE_P (NODE ) (ASM_EXPR_CHECK (NODE)->base.protected_flag)/* COND_EXPR accessors. */ #define COND_EXPR_COND (NODE ) (TREE_OPERAND (COND_EXPR_CHECK (NODE), 0))
Signature · 2 lines
Richard Biener <[email protected]> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 2 lines · Richard Biener
Can kernel folks give this a second and third thought please so we don't implement sth that in the end won't satisfy you guys?
So this basically passes '0 size' to the inliner, which should be better than passing in the explicit size, as we'd inevitably get it wrong in cases.
I also like 'size 0' for the reason that we tend to write assembly code and mark it 'inline' if we really think it matters to performance, so making it more likely to be inlined when used within another inline function is a plus as well.
Does anyone have any concerns about this?
Thanks,
Ingo
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 7 lines · Ingo Molnar
Quoted 2 lines · Richard Biener
Can kernel folks give this a second and third thought please so we don't implement sth that in the end won't satisfy you guys?
So this basically passes '0 size' to the inliner, which should be better than passing in the explicit size, as we'd inevitably get it wrong in cases.
The code immediately after this makes it size 1, even for things like asm(""), I suppose this works better for the inliner. But that's a detail (and it might change); the description says "consider this asm as minimum length and cost for inlining decisions", which works for either 0 or 1.
Quoted 4 lines
I also like 'size 0' for the reason that we tend to write assembly code and mark it 'inline' if we really think it matters to performance, so making it more likely to be inlined when used within another inline function is a plus as well.
You can think of it as meaning "we want this asm inlined always", and then whether that actually happens depends on if the function around it is inlined or not.
Segher
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 4 lines · Segher Boessenkool
The code immediately after this makes it size 1, even for things like
asm(""), I suppose this works better for the inliner. But that's a detail (and it might change); the description says "consider this asm as minimum length and cost for inlining decisions", which works for either 0 or 1.
Thanks for implementing this, much appreciated. If you need people to test stuff, lemme know.
Quoted 3 lines
You can think of it as meaning "we want this asm inlined always", and then whether that actually happens depends on if the function around it is inlined or not.
My only concern is how we would catch the other extremity where the inline asm grows too big and we end up inlining it everywhere and thus getting fat. The 0day bot already builds tinyconfigs but we should be looking at vmlinux size growth too.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 9 lines · Borislav Petkov
Quoted 4 lines · Segher Boessenkool
The code immediately after this makes it size 1, even for things like
asm(""), I suppose this works better for the inliner. But that's a detail (and it might change); the description says "consider this asm as minimum length and cost for inlining decisions", which works for either 0 or 1.Thanks for implementing this, much appreciated. If you need people to test stuff, lemme know.
Quoted 8 lines
Quoted 3 lines
You can think of it as meaning "we want this asm inlined always", and then whether that actually happens depends on if the function around it is inlined or not.
My only concern is how we would catch the other extremity where the inline asm grows too big and we end up inlining it everywhere and thus getting fat. The 0day bot already builds tinyconfigs but we should be looking at vmlinux size growth too.
Well, it's like always-inline functions, you have to be careful and _not_ put it everywhere... It's also somewhat different to always-inline functions as those lose their special-ness once inlined (the inlined body is properly accounted for size).
Richard.
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Borislav PetkovQuoted 8 lines · Borislav Petkov
Quoted 4 lines · Segher Boessenkool
The code immediately after this makes it size 1, even for things like
asm(""), I suppose this works better for the inliner. But that's a detail (and it might change); the description says "consider this asm as minimum length and cost for inlining decisions", which works for either 0 or 1.Thanks for implementing this, much appreciated. If you need people to test stuff, lemme know.
It would be great to hear from kernel people if it works adequately for what you guys want it for :-)
Quoted 8 lines
Quoted 3 lines
You can think of it as meaning "we want this asm inlined always", and then whether that actually happens depends on if the function around it is inlined or not.
My only concern is how we would catch the other extremity where the inline asm grows too big and we end up inlining it everywhere and thus getting fat. The 0day bot already builds tinyconfigs but we should be looking at vmlinux size growth too.
But this isn't really different from other always_inline concerns afaics? So you should be able to catch it the same way, too.
Segher
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 2 lines · Segher Boessenkool
It would be great to hear from kernel people if it works adequately for what you guys want it for :-)
Sure, ping me when you have the final version and I'll try to build gcc with it and do some size comparisons.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Ok,
with Segher's help I've been playing with his patch ontop of bleeding edge gcc 9 and here are my observations. Please double-check me for booboos so that they can be addressed while there's time.
So here's what I see ontop of 4.19-rc7:
First marked the alternative asm() as inline and undeffed the "inline" keyword. I need to do that because of the funky games we do with "inline" redefinitions in include/linux/compiler_types.h.
And Segher hinted at either doing:
asm volatile inline(...
or
asm volatile __inline__(...
but both "inline" variants are defined as macros in that file.
Which means we either need to #undef inline before using it in asm() or come up with something cleverer.
Anyway, did this:
---
arch/x86/include/asm/alternative.h +4 -2
@@ -165,11 +165,13 @@ static inline int alternatives_text_reserved(void *start, void *end)* For non barrier like inlines please define new variants * without volatile and memory clobber. */ + +#undef inline#define alternative (oldinstr, newinstr, feature) \ - asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory") + asm volatile inline(ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")#define alternative_2 (oldinstr, newinstr1, feature1, newinstr2, feature2) \ - asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory") + asm volatile inline(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")/* * Alternative inline assembly with input.
---
Build failed at link time with:
arch/x86/boot/compressed/cmdline.o: In function `native_save_fl':
cmdline.c:(.text+0x0): multiple definition of native_save_fl' arch/x86/boot/compressed/misc.o:misc.c:(.text+0x1e0): first defined here arch/x86/boot/compressed/cmdline.o: In function native_restore_fl':
cmdline.c:(.text+0x10): multiple definition of native_restore_fl' arch/x86/boot/compressed/misc.o:misc.c:(.text+0x1f0): first defined here arch/x86/boot/compressed/error.o: In function native_save_fl':
error.c:(.text+0x0): multiple definition of `native_save_fl'
which I had to fix with this:
---
arch/x86/include/asm/irqflags.h +1 -3
@@ -14,8 +14,7 @@*/ /* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */ -extern inline unsigned long native_save_fl (void ); -extern inline unsigned long native_save_fl (void ) +static inline unsigned long native_save_fl (void ) {unsigned long flags;
@@ -33,8 +32,7 @@ ex ---
That "extern inline" declaration looks fishy to me anyway, maybe not really needed ? Apparently, gcc < 4.9 complains with -Werror=missing-prototypes...
Then the build worked and the results look like this:
text data bss dec hex filename
17287384 5040656 2019532 24347572 17383b4 vmlinux-before 17288020 5040656 2015436 24344112 1737630 vmlinux-2nd-version
so some inlining must be happening.
Then I did this:
---
arch/x86/lib/usercopy_64.c +1 -1
@@ -20,7 +20,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)/* no memory constraint because it doesn't change any memory gcc knows about */ stac (); - asmvolatile ( + asmvolatile inline (" testq %[size8],%[size8]\n" " jz 4f\n" "0: movq $0,(%[dst])\n"
---
to force inlining of a somewhat bigger asm() statement. And yap, more got inlined:
text data bss dec hex filename
17287384 5040656 2019532 24347572 17383b4 vmlinux-before 17288020 5040656 2015436 24344112 1737630 vmlinux-2nd-version 17288076 5040656 2015436 24344168 1737668 vmlinux-2nd-version__clear_user
so more stuff gets inlined.
Looking at the asm output, it had before:
---clear_user:
# ./arch/x86/include/asm/current.h:15: return this_cpu_read_stable(current_task); #APP
# 15 "./arch/x86/include/asm/current.h" 1
movq %gs:current_task,%rax #, pfo_ret__
# 0 "" 2
# arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
#NO_APP
movq 2520(%rax), %rdx # pfo_ret___12->thread.addr_limit.seg, _1
movq %rdi, %rax # to, tmp93
addq %rsi, %rax # n, tmp93
jc .L3 #,# arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
cmpq %rax, %rdx # tmp93, _1
jb .L3 #,
# arch/x86/lib/usercopy_64.c:52: return __clear_user(to, n);
jmp __clear_user #
---
note the JMP to __clear_user. After marking the asm() in __clear_user() as inline, clear_user() inlines __clear_user() directly:
---clear_user:
# ./arch/x86/include/asm/current.h:15: return this_cpu_read_stable(current_task); #APP
# 15 "./arch/x86/include/asm/current.h" 1
movq %gs:current_task,%rax #, pfo_ret__
# 0 "" 2
# arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
#NO_APP
movq 2520(%rax), %rdx # pfo_ret___12->thread.addr_limit.seg, _1
movq %rdi, %rax # to, tmp95
addq %rsi, %rax # n, tmp95
jc .L8 #,# arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
cmpq %rax, %rdx # tmp95, _1
jb .L8 #,
# ./arch/x86/include/asm/smap.h:58: alternative("", __stringify(__ASM_STAC), X86_FEATURE_SMAP);
...
this last line is the stac() macro which gets inlined due to the alternative() inlined macro above.
So I guess this all looks like what we wanted.
And if this lands in gcc9, we would need to do a asm_volatile() macro which is defined differently based on the compiler used.
Thoughts, suggestions, etc are most welcome.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: PROPOSAL: Extend inline asm syntax with size spec
Hi,
Quoted 2 lines · Borislav Petkov
Thoughts, suggestions, etc are most welcome.
I apologize for coming in late here with an alternative proposal, but would you be happy if GCC gave you a way to designate a portion of the asm template string that shouldn't be counted as its cost because it doesn't go into the .text section? This wouldn't interact with your redefinitions of the inline keyword, and you could do something like (assuming we go with % ... % delimiters)
[if gcc-9 or compatible]
#define ASM_NONTEXT_START "%`\n"
#define ASM_NONTEXT_END "%`\n"
[else]
#define ASM_NONTEXT_START "\n"
#define ASM_NONTEXT_END "\n"
[endif]
#define _BUG_FLAGS(ins, flags) \
do { \
asm volatile("1:\t" ins "\n" \
ASM_NONTEXT_START \
".pushsection __bug_table,\"aw\"\n" \
"2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \
"\t.word %c0" "\t# bug_entry::flags\n" \
"\t.org 2b+%c1\n" \
".popsection" \
ASM_NONTEXT_END \
: : "i" (flags), \
"i" (sizeof(struct bug_entry))); \
} while (0)I think it's nicer because it also allows the compiler to estimate asm length for branch range optimization more accurately.
Alexander
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 6 lines · Alexander Monakov
I apologize for coming in late here with an alternative proposal, but would you be happy if GCC gave you a way to designate a portion of the asm template string that shouldn't be counted as its cost because it doesn't go into the .text section? This wouldn't interact with your redefinitions of the inline keyword, and you could do something like (assuming we go with %
... %delimiters)
I don't mind it but I see you guys are still discussing what would be the better solution here, on the gcc ML. And we, as one user, are a happy camper as long as it does what it is meant to do. But how the feature looks like syntactically is something for gcc folk to decide as they're going to support it for the foreseeable future and I'm very well aware of how important it is for a supportable feature to be designed properly.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Borislav PetkovPing.
This is a good point in time, methinks, where kernel folk on CC here should have a look at this and speak up whether it is useful for us in this form.
Frankly, I'm a bit unsure on the aspect of us using this and supporting old compilers which don't have it and new compilers which do. Because the old compilers should get to see the now upstreamed assembler macros and the new compilers will simply inline the "asm volatile inline" constructs. And how ugly that would become...
I guess we can try this with smaller macros first and keep them all nicely hidden in header files.
Quoted 181 lines · Borislav Petkov
Ok,
with Segher's help I've been playing with his patch ontop of bleeding edge gcc 9 and here are my observations. Please double-check me for booboos so that they can be addressed while there's time.
So here's what I see ontop of 4.19-rc7:
First marked the alternative
asm()as inline and undeffed the "inline" keyword. I need to do that because of the funky games we do with "inline" redefinitions ininclude/linux/compiler_types.h.And Segher hinted at either doing:
asm volatile inline(...
or
asm volatile __inline__(...
but both "inline" variants are defined as macros in that file.
Which means we either need to #undef inline before using it in
asm()or come up with something cleverer.Anyway, did this:
---
arch/x86/include/asm/alternative.h +4
-3@@ -165,11 +165,13 @@ static inline int alternatives_text_reserved(void *start, void *end)* For non barrier like inlines please define new variants * without volatile and memory clobber. */ + +#undef inline#define alternative (oldinstr, newinstr, feature) \ - asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory") + asm volatile inline(ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")#define alternative_2 (oldinstr, newinstr1, feature1, newinstr2, feature2) \ - asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory") + asm volatile inline(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")/* * Alternative inline assembly with input. --- Build failed at link time with:
arch/x86/boot/compressed/cmdline.o: In function `native_save_fl':
cmdline.c:(.text+0x0): multiple definition ofnative_save_fl' arch/x86/boot/compressed/misc.o:misc.c:(.text+0x1e0): first defined here arch/x86/boot/compressed/cmdline.o: In functionnative_restore_fl':
cmdline.c:(.text+0x10): multiple definition ofnative_restore_fl' arch/x86/boot/compressed/misc.o:misc.c:(.text+0x1f0): first defined here arch/x86/boot/compressed/error.o: In functionnative_save_fl':
error.c:(.text+0x0): multiple definition of `native_save_fl'which I had to fix with this:
---
arch/x86/include/asm/irqflags.h +1
-3@@ -14,8 +14,7 @@*/ /* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */ -extern inline unsigned long native_save_fl (void ); -extern inline unsigned long native_save_fl (void ) +static inline unsigned long native_save_fl (void ) {unsigned long flags;@@ -33,8 +32,7 @@ ex ---That "extern inline" declaration looks fishy to me anyway, maybe not really needed ? Apparently, gcc < 4.9 complains with -Werror=missing-prototypes...
Then the build worked and the results look like this:
text data bss dec hex filename
17287384 5040656 2019532 24347572 17383b4 vmlinux-before 17288020 5040656 2015436 24344112 1737630 vmlinux-2nd-versionso some inlining must be happening.
Then I did this:
---
arch/x86/lib/usercopy_64.c +1
-2@@ -20,7 +20,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)/* no memory constraint because it doesn't change any memory gcc knows about */ stac (); - asmvolatile ( + asmvolatile inline (" testq %[size8],%[size8]\n" " jz 4f\n" "0: movq $0,(%[dst])\n" ---to force inlining of a somewhat bigger
asm()statement. And yap, more got inlined:text data bss dec hex filename
17287384 5040656 2019532 24347572 17383b4 vmlinux-before 17288020 5040656 2015436 24344112 1737630 vmlinux-2nd-version 17288076 5040656 2015436 24344168 1737668 vmlinux-2nd-version__clear_userso more stuff gets inlined.
Looking at the asm output, it had before:
---
clear_user:
#./arch/x86/include/asm/current.h:15: returnthis_cpu_read_stable(current_task); #APP
# 15 "./arch/x86/include/asm/current.h" 1
movq %gs:current_task,%rax #,pfo_ret__
# 0 "" 2
#arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
#NO_APPmovq 2520(%rax), %rdx # pfo_ret___12->thread.addr_limit.seg, _1 movq %rdi, %rax # to, tmp93 addq %rsi, %rax # n, tmp93 jc .L3 #,#
arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
cmpq %rax, %rdx # tmp93, _1
jb .L3 #,
#arch/x86/lib/usercopy_64.c:52: return__clear_user(to, n);
jmp__clear_user#
---note the JMP to
__clear_user. After marking theasm()in__clear_user()as inline,clear_user()inlines__clear_user()directly:---
clear_user:
#./arch/x86/include/asm/current.h:15: returnthis_cpu_read_stable(current_task); #APP
# 15 "./arch/x86/include/asm/current.h" 1
movq %gs:current_task,%rax #,pfo_ret__
# 0 "" 2
#arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
#NO_APPmovq 2520(%rax), %rdx # pfo_ret___12->thread.addr_limit.seg, _1 movq %rdi, %rax # to, tmp95 addq %rsi, %rax # n, tmp95 jc .L8 #,#
arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
cmpq %rax, %rdx # tmp95, _1
jb .L8 #,
#./arch/x86/include/asm/smap.h:58:alternative("", __stringify(__ASM_STAC), X86_FEATURE_SMAP);
...this last line is the
stac()macro which gets inlined due to thealternative()inlined macro above.So I guess this all looks like what we wanted.
And if this lands in gcc9, we would need to do a
asm_volatile()macro which is defined differently based on the compiler used.Thoughts, suggestions, etc are most welcome.
Thx.
Signature · 4 lines
Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.
Signature · 5 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Borislav PetkovPing.
This is a good point in time, methinks, where kernel folk on CC here should have a look at this and speak up whether it is useful for us in this form.
Frankly, I'm a bit unsure on the aspect of us using this and supporting old compilers which don't have it and new compilers which do. Because the old compilers should get to see the now upstreamed assembler macros and the new compilers will simply inline the "asm volatile inline" constructs. And how ugly that would become...
I guess we can try this with smaller macros first and keep them all nicely hidden in header files.
Quoted 181 lines · Borislav Petkov
Ok,
with Segher's help I've been playing with his patch ontop of bleeding edge gcc 9 and here are my observations. Please double-check me for booboos so that they can be addressed while there's time.
So here's what I see ontop of 4.19-rc7:
First marked the alternative
asm()as inline and undeffed the "inline" keyword. I need to do that because of the funky games we do with "inline" redefinitions ininclude/linux/compiler_types.h.And Segher hinted at either doing:
asm volatile inline(...
or
asm volatile __inline__(...
but both "inline" variants are defined as macros in that file.
Which means we either need to #undef inline before using it in
asm()or come up with something cleverer.Anyway, did this:
---
arch/x86/include/asm/alternative.h +4
-3@@ -165,11 +165,13 @@ static inline int alternatives_text_reserved(void *start, void *end)* For non barrier like inlines please define new variants * without volatile and memory clobber. */ + +#undef inline#define alternative (oldinstr, newinstr, feature) \ - asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory") + asm volatile inline(ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")#define alternative_2 (oldinstr, newinstr1, feature1, newinstr2, feature2) \ - asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory") + asm volatile inline(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")/* * Alternative inline assembly with input. --- Build failed at link time with:
arch/x86/boot/compressed/cmdline.o: In function `native_save_fl':
cmdline.c:(.text+0x0): multiple definition ofnative_save_fl' arch/x86/boot/compressed/misc.o:misc.c:(.text+0x1e0): first defined here arch/x86/boot/compressed/cmdline.o: In functionnative_restore_fl':
cmdline.c:(.text+0x10): multiple definition ofnative_restore_fl' arch/x86/boot/compressed/misc.o:misc.c:(.text+0x1f0): first defined here arch/x86/boot/compressed/error.o: In functionnative_save_fl':
error.c:(.text+0x0): multiple definition of `native_save_fl'which I had to fix with this:
---
arch/x86/include/asm/irqflags.h +1
-3@@ -14,8 +14,7 @@*/ /* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */ -extern inline unsigned long native_save_fl (void ); -extern inline unsigned long native_save_fl (void ) +static inline unsigned long native_save_fl (void ) {unsigned long flags;@@ -33,8 +32,7 @@ ex ---That "extern inline" declaration looks fishy to me anyway, maybe not really needed ? Apparently, gcc < 4.9 complains with -Werror=missing-prototypes...
Then the build worked and the results look like this:
text data bss dec hex filename
17287384 5040656 2019532 24347572 17383b4 vmlinux-before 17288020 5040656 2015436 24344112 1737630 vmlinux-2nd-versionso some inlining must be happening.
Then I did this:
---
arch/x86/lib/usercopy_64.c +1
-2@@ -20,7 +20,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)/* no memory constraint because it doesn't change any memory gcc knows about */ stac (); - asmvolatile ( + asmvolatile inline (" testq %[size8],%[size8]\n" " jz 4f\n" "0: movq $0,(%[dst])\n" ---to force inlining of a somewhat bigger
asm()statement. And yap, more got inlined:text data bss dec hex filename
17287384 5040656 2019532 24347572 17383b4 vmlinux-before 17288020 5040656 2015436 24344112 1737630 vmlinux-2nd-version 17288076 5040656 2015436 24344168 1737668 vmlinux-2nd-version__clear_userso more stuff gets inlined.
Looking at the asm output, it had before:
---
clear_user:
#./arch/x86/include/asm/current.h:15: returnthis_cpu_read_stable(current_task); #APP
# 15 "./arch/x86/include/asm/current.h" 1
movq %gs:current_task,%rax #,pfo_ret__
# 0 "" 2
#arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
#NO_APPmovq 2520(%rax), %rdx # pfo_ret___12->thread.addr_limit.seg, _1 movq %rdi, %rax # to, tmp93 addq %rsi, %rax # n, tmp93 jc .L3 #,#
arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
cmpq %rax, %rdx # tmp93, _1
jb .L3 #,
#arch/x86/lib/usercopy_64.c:52: return__clear_user(to, n);
jmp__clear_user#
---note the JMP to
__clear_user. After marking theasm()in__clear_user()as inline,clear_user()inlines__clear_user()directly:---
clear_user:
#./arch/x86/include/asm/current.h:15: returnthis_cpu_read_stable(current_task); #APP
# 15 "./arch/x86/include/asm/current.h" 1
movq %gs:current_task,%rax #,pfo_ret__
# 0 "" 2
#arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
#NO_APPmovq 2520(%rax), %rdx # pfo_ret___12->thread.addr_limit.seg, _1 movq %rdi, %rax # to, tmp95 addq %rsi, %rax # n, tmp95 jc .L8 #,#
arch/x86/lib/usercopy_64.c:51: if (access_ok(VERIFY_WRITE, to, n))
cmpq %rax, %rdx # tmp95, _1
jb .L8 #,
#./arch/x86/include/asm/smap.h:58:alternative("", __stringify(__ASM_STAC), X86_FEATURE_SMAP);
...this last line is the
stac()macro which gets inlined due to thealternative()inlined macro above.So I guess this all looks like what we wanted.
And if this lands in gcc9, we would need to do a
asm_volatile()macro which is defined differently based on the compiler used.Thoughts, suggestions, etc are most welcome.
Thx.
Signature · 4 lines
Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.
Signature · 5 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--Peter Zijlstra
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Borislav PetkovQuoted 16 lines · Borislav Petkov
Ok,
with Segher's help I've been playing with his patch ontop of bleeding edge gcc 9 and here are my observations. Please double-check me for booboos so that they can be addressed while there's time.
So here's what I see ontop of 4.19-rc7:
First marked the alternative
asm()as inline and undeffed the "inline" keyword. I need to do that because of the funky games we do with "inline" redefinitions ininclude/linux/compiler_types.h.And Segher hinted at either doing:
asm volatile inline(...
Quoted 8 lines
or
asm volatile __inline__(...
but both "inline" variants are defined as macros in that file.
Which means we either need to #undef inline before using it in
asm()or come up with something cleverer.
# git grep -e "\<__inline__\>" | wc -l 488 # git grep -e "\<__inline\>" | wc -l 56 # git grep -e "\<inline\>" | wc -l 69598
And we already have scripts/checkpatch.pl:
# Check for __inline__ and __inline, prefer inline
Which suggests we do:
git grep -l "\<__inline\(\|__\)\>" | while read file do
sed -i -e 's/\<__inline\(\|__\)\>/inline/g' $file
done
and get it over with.
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinux
Which shows we inline more (look for asm_volatile for the actual changes).
So yes, this seems like something we could work with.
--- Documentation/trace/tracepoint-analysis.rst | 2 +- Documentation/translations/ja_JP/SubmittingPatches | 4 +-- Documentation/translations/zh_CN/SubmittingPatches | 4 +-- arch/alpha/include/asm/atomic.h | 12 +++---- arch/alpha/include/asm/bitops.h | 6 ++-- arch/alpha/include/asm/compiler.h | 4 +-- arch/alpha/include/asm/dma.h | 22 ++++++------ arch/alpha/include/asm/floppy.h | 4 +-- arch/alpha/include/asm/irq.h | 2 +- arch/alpha/include/asm/local.h | 4 +-- arch/alpha/include/asm/smp.h | 2 +- arch/arm/mach-iop32x/include/mach/uncompress.h | 2 +- arch/arm/mach-iop33x/include/mach/uncompress.h | 2 +- arch/arm/mach-ixp4xx/include/mach/uncompress.h | 2 +- arch/ia64/hp/common/sba_iommu.c | 2 +- arch/ia64/hp/sim/simeth.c | 2 +- arch/ia64/include/asm/atomic.h | 8 ++--- arch/ia64/include/asm/bitops.h | 34 +++++++++--------- arch/ia64/include/asm/delay.h | 14 ++++---- arch/ia64/include/asm/irq.h | 2 +- arch/ia64/include/asm/page.h | 2 +- arch/ia64/include/asm/sn/leds.h | 2 +- arch/ia64/include/asm/uaccess.h | 4 +-- arch/ia64/include/uapi/asm/rse.h | 12 +++---- arch/ia64/include/uapi/asm/swab.h | 6 ++-- arch/ia64/oprofile/backtrace.c | 4 +-- arch/m68k/include/asm/blinken.h | 2 +- arch/m68k/include/asm/checksum.h | 2 +- arch/m68k/include/asm/dma.h | 32 ++++++++--------- arch/m68k/include/asm/floppy.h | 8 ++--- arch/m68k/include/asm/nettel.h | 8 ++--- arch/m68k/mac/iop.c | 14 ++++---- arch/mips/include/asm/atomic.h | 16 ++++----- arch/mips/include/asm/checksum.h | 2 +- arch/mips/include/asm/dma.h | 20 +++++------ arch/mips/include/asm/jazz.h | 2 +- arch/mips/include/asm/local.h | 4 +-- arch/mips/include/asm/string.h | 8 ++--- arch/mips/kernel/binfmt_elfn32.c | 2 +- arch/nds32/include/asm/swab.h | 4 +-- arch/parisc/include/asm/atomic.h | 20 +++++------ arch/parisc/include/asm/bitops.h | 18 +++++----- arch/parisc/include/asm/checksum.h | 4 +-- arch/parisc/include/asm/compat.h | 2 +- arch/parisc/include/asm/delay.h | 2 +- arch/parisc/include/asm/dma.h | 20 +++++------ arch/parisc/include/asm/ide.h | 8 ++--- arch/parisc/include/asm/irq.h | 2 +- arch/parisc/include/asm/spinlock.h | 12 +++---- arch/powerpc/include/asm/atomic.h | 40 +++++++++++----------- arch/powerpc/include/asm/bitops.h | 28 +++++++-------- arch/powerpc/include/asm/dma.h | 20 +++++------ arch/powerpc/include/asm/edac.h | 2 +- arch/powerpc/include/asm/irq.h | 2 +- arch/powerpc/include/asm/local.h | 14 ++++---- arch/sh/include/asm/pgtable_64.h | 2 +- arch/sh/include/asm/processor_32.h | 4 +-- arch/sh/include/cpu-sh3/cpu/dac.h | 6 ++-- arch/x86/include/asm/alternative.h | 14 ++++---- arch/x86/um/asm/checksum.h | 4 +-- arch/x86/um/asm/checksum_32.h | 4 +-- arch/xtensa/include/asm/checksum.h | 14 ++++---- arch/xtensa/include/asm/cmpxchg.h | 4 +-- arch/xtensa/include/asm/irq.h | 2 +- block/partitions/amiga.c | 2 +- drivers/atm/he.c | 6 ++-- drivers/atm/idt77252.c | 6 ++-- drivers/gpu/drm/mga/mga_drv.h | 2 +- drivers/gpu/drm/mga/mga_state.c | 14 ++++---- drivers/gpu/drm/r128/r128_drv.h | 2 +- drivers/gpu/drm/r128/r128_state.c | 14 ++++---- drivers/gpu/drm/via/via_irq.c | 2 +- drivers/gpu/drm/via/via_verifier.c | 30 ++++++++-------- drivers/isdn/hardware/eicon/platform.h | 14 ++++---- drivers/isdn/i4l/isdn_net.c | 14 ++++---- drivers/isdn/i4l/isdn_net.h | 8 ++--- drivers/media/pci/ivtv/ivtv-ioctl.c | 2 +- drivers/net/ethernet/sun/sungem.c | 8 ++--- drivers/net/ethernet/sun/sunhme.c | 6 ++-- drivers/net/hamradio/baycom_ser_fdx.c | 2 +- drivers/net/wan/lapbether.c | 2 +- drivers/net/wan/n2.c | 4 +-- drivers/parisc/led.c | 4 +-- drivers/parisc/sba_iommu.c | 2 +- drivers/parport/parport_gsc.c | 2 +- drivers/parport/parport_gsc.h | 4 +-- drivers/parport/parport_pc.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 2 +- drivers/scsi/pcmcia/sym53c500_cs.c | 4 +-- drivers/scsi/qla2xxx/qla_inline.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 4 +-- drivers/staging/rtl8723bs/core/rtw_pwrctrl.c | 4 +-- drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 2 +- drivers/staging/rtl8723bs/include/drv_types.h | 6 ++-- drivers/staging/rtl8723bs/include/ieee80211.h | 6 ++-- drivers/staging/rtl8723bs/include/osdep_service.h | 10 +++--- .../rtl8723bs/include/osdep_service_linux.h | 14 ++++---- drivers/staging/rtl8723bs/include/rtw_mlme.h | 14 ++++---- drivers/staging/rtl8723bs/include/rtw_recv.h | 16 ++++----- drivers/staging/rtl8723bs/include/sta_info.h | 2 +- drivers/staging/rtl8723bs/include/wifi.h | 14 ++++---- drivers/staging/rtl8723bs/include/wlan_bssdef.h | 2 +- drivers/tty/amiserial.c | 2 +- drivers/tty/serial/ip22zilog.c | 2 +- drivers/tty/serial/sunsab.c | 4 +-- drivers/tty/serial/sunzilog.c | 2 +- drivers/video/fbdev/core/fbcon.c | 20 +++++------ drivers/video/fbdev/ffb.c | 2 +- drivers/video/fbdev/intelfb/intelfbdrv.c | 10 +++--- drivers/video/fbdev/intelfb/intelfbhw.c | 2 +- drivers/w1/masters/matrox_w1.c | 4 +-- fs/coda/coda_linux.h | 6 ++-- fs/freevxfs/vxfs_inode.c | 2 +- fs/nfsd/nfsfh.h | 4 +-- include/acpi/platform/acgcc.h | 2 +- include/acpi/platform/acintel.h | 2 +- include/asm-generic/ide_iops.h | 8 ++--- include/linux/atalk.h | 4 +-- include/linux/ceph/messenger.h | 2 +- include/linux/compiler_types.h | 4 +-- include/linux/hdlc.h | 4 +-- include/linux/inetdevice.h | 8 ++--- include/linux/parport.h | 4 +-- include/linux/parport_pc.h | 22 ++++++------ include/net/ax25.h | 2 +- include/net/checksum.h | 2 +- include/net/dn_nsp.h | 16 ++++----- include/net/ip.h | 2 +- include/net/ip6_checksum.h | 2 +- include/net/ipx.h | 10 +++--- include/net/llc_c_ev.h | 4 +-- include/net/llc_conn.h | 4 +-- include/net/llc_s_ev.h | 2 +- include/net/netrom.h | 8 ++--- include/net/scm.h | 14 ++++---- include/net/udplite.h | 2 +- include/net/x25.h | 8 ++--- include/net/xfrm.h | 18 +++++----- include/uapi/linux/atm.h | 4 +-- include/uapi/linux/atmsap.h | 2 +- include/uapi/linux/map_to_7segment.h | 2 +- include/uapi/linux/netfilter_arp/arp_tables.h | 2 +- include/uapi/linux/netfilter_bridge/ebtables.h | 2 +- include/uapi/linux/netfilter_ipv4/ip_tables.h | 2 +- include/uapi/linux/netfilter_ipv6/ip6_tables.h | 2 +- include/video/newport.h | 12 +++---- lib/zstd/mem.h | 2 +- net/appletalk/atalk_proc.c | 4 +-- net/appletalk/ddp.c | 2 +- net/core/neighbour.c | 2 +- net/core/scm.c | 2 +- net/decnet/dn_nsp_in.c | 2 +- net/decnet/dn_nsp_out.c | 2 +- net/decnet/dn_route.c | 2 +- net/decnet/dn_table.c | 4 +-- net/ipv4/igmp.c | 2 +- net/ipv6/af_inet6.c | 2 +- net/ipv6/icmp.c | 4 +-- net/ipv6/udp.c | 4 +-- net/lapb/lapb_iface.c | 4 +-- net/llc/llc_input.c | 2 +- scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +-- sound/sparc/amd7930.c | 6 ++-- 165 files changed, 547 insertions(+), 547 deletions(-)
Documentation/trace/tracepoint-analysis.rst +1 -1
@@ -315,7 +315,7 @@ To see where within the function pixmanFillsse2 things are going wrong: 0.00 : 34eeb: 0f 18 08 prefetcht0 (%eax) : } : - : extern __inline void __attribute__((__gnu_inline__, __always_inline__, _ + : extern inline void __attribute__((__gnu_inline__, __always_inline__, _ : _mm_store_si128 (__m128i *__P, __m128i __B) : { : *__P = __B; 12.40 : 34eee: 66 0f 7f 80 40 ff ff movdqa %xmm0,-0xc0(%eax)
Documentation/translations/ja_JP/SubmittingPatches +2 -2
@@ -676,8 +676,8 @@ gcc においては、マクロと同じくらい軽いです。 いくつかの特定のケース)や「 static inline 」関数を使うことができないような 場所(マクロの引数の文字列連結のような)にだけ使われるべきです。 -「 static inline 」は「 static __inline__ 」や「 extern inline 」や -「 extern __inline__ 」よりも適切です。 +「 static inline 」は「 static inline 」や「 extern inline 」や +「 extern inline 」よりも適切です。 4) 設計に凝りすぎるな
Documentation/translations/zh_CN/SubmittingPatches +2 -2
@@ -377,8 +377,8 @@ Static inline 函数相比宏来说,是好得多的选择。Static inline 函 宏只在 static inline 函数不是最优的时候[在 fast paths 里有很少的独立的 案例],或者不可能用 static inline 函数的时候[例如字符串分配]。 -应该用 'static inline' 而不是 'static __inline__', 'extern inline' 和 -'extern __inline__' 。 +应该用 'static inline' 而不是 'static inline', 'extern inline' 和 +'extern inline' 。 4) 不要过度设计
arch/alpha/include/asm/atomic.h +6 -6
@@ -40,7 +40,7 @@*/ #define ATOMIC_OP (op, asm_op) \ -static __inline__ void atomic_##op(int i, atomic_t * v) \ +static inline void atomic_##op(int i, atomic_t * v) \ { \ unsigned long temp; \ __asm__ __volatile__( \
@@ -93,7 +93,7 @@ static inline int atomic_fetch_##op##_relaxed(int i, atomic_t *v) \ }#define ATOMIC64_OP (op, asm_op) \ -static __inline__ void atomic64_##op(long i, atomic64_t * v) \ +static inline void atomic64_##op(long i, atomic64_t * v) \ { \ unsigned long temp; \ __asm__ __volatile__( \
@@ -109,7 +109,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ } \#define ATOMIC64_OP_RETURN (op, asm_op) \ -static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ +static inline long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ { \ long temp, result; \ __asm__ __volatile__( \
@@ -128,7 +128,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ }#define ATOMIC64_FETCH_OP (op, asm_op) \ -static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ +static inline long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ { \ long temp, result; \ __asm__ __volatile__( \
@@ -214,7 +214,7 @@ ATOMIC_OPS(xor, xor)* Atomically adds @a to @v, so long as it was not @u. * Returns the old value of @v. */ -static __inline__int atomic_fetch_add_unless (atomic_t *v,int a,int u) +static inline int atomic_fetch_add_unless (atomic_t *v,int a,int u) {int c, new, old;smp_mb ();
@@ -246,7 +246,7 @@ static __inline__ int atomic_fetch_add_unless(atomic_t *v, int a, int u)* Atomically adds @a to @v, so long as it was not @u. * Returns the old value of @v. */ -static __inline__long atomic64_fetch_add_unless (atomic64_t *v,long a,long u) +static inline long atomic64_fetch_add_unless (atomic64_t *v,long a,long u) {long c, new, old;smp_mb ();
arch/alpha/include/asm/bitops.h +3 -3
@@ -82,7 +82,7 @@ clear_bit_unlock(unsigned long nr, volatile void * addr)/* * WARNING: non atomic version. */ -static __inline__void +static inline void __clear_bit (unsigned long nr,volatile void * addr) {int *m = ((int *) addr) + (nr >>5 );
@@ -118,7 +118,7 @@ change_bit(unsigned long nr, volatile void * addr)/* * WARNING: non atomic version. */ -static __inline__void +static inline void __change_bit (unsigned long nr,volatile void * addr) {int *m = ((int *) addr) + (nr >>5 );
@@ -272,7 +272,7 @@ test_and_change_bit(unsigned long nr, volatile void * addr)/* * WARNING: non atomic version. */ -static __inline__int +static inline int __test_and_change_bit (unsigned long nr,volatile void * addr) {unsigned long mask =1 << (nr &0x1f );
arch/alpha/include/asm/compiler.h +2 -2
@@ -10,8 +10,8 @@#include <linux/compiler.h> #undef inline -#undef __inline__ -#undef __inline +#undef inline +#undef inline#undef __always_inline#define __always_inline inline __attribute__((always_inline))
arch/alpha/include/asm/dma.h +11 -11
@@ -198,20 +198,20 @@extern spinlock_t dma_spin_lock; -static __inline__unsigned long claim_dma_lock (void ) +static inline unsigned long claim_dma_lock (void ) {unsigned long flags;spin_lock_irqsave (&dma_spin_lock, flags);return flags; } -static __inline__void release_dma_lock (unsigned long flags) +static inline void release_dma_lock (unsigned long flags) {spin_unlock_irqrestore (&dma_spin_lock, flags); }/* enable/disable a specific DMA channel */ -static __inline__void enable_dma (unsigned int dmanr) +static inline void enable_dma (unsigned int dmanr) {if (dmanr<=3 )dma_outb (dmanr,DMA1_MASK_REG );
@@ -219,7 +219,7 @@ static __inline__ void enable_dma(unsigned int dmanr)dma_outb (dmanr &3 ,DMA2_MASK_REG ); } -static __inline__void disable_dma (unsigned int dmanr) +static inline void disable_dma (unsigned int dmanr) {if (dmanr<=3 )dma_outb (dmanr |4 ,DMA1_MASK_REG );
@@ -234,7 +234,7 @@ static __inline__ void disable_dma(unsigned int dmanr)* --- In order to do that, the DMA routines below should --- * --- only be used while interrupts are disabled! --- */ -static __inline__void clear_dma_ff (unsigned int dmanr) +static inline void clear_dma_ff (unsigned int dmanr) {if (dmanr<=3 )dma_outb (0 ,DMA1_CLEAR_FF_REG );
@@ -243,7 +243,7 @@ static __inline__ void clear_dma_ff(unsigned int dmanr) }/* set mode (above) for a specific DMA channel */ -static __inline__void set_dma_mode (unsigned int dmanr,char mode) +static inline void set_dma_mode (unsigned int dmanr,char mode) {if (dmanr<=3 )dma_outb (mode | dmanr,DMA1_MODE_REG );
@@ -252,7 +252,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode) }/* set extended mode for a specific DMA channel */ -static __inline__void set_dma_ext_mode (unsigned int dmanr,char ext_mode) +static inline void set_dma_ext_mode (unsigned int dmanr,char ext_mode) {if (dmanr<=3 )dma_outb (ext_mode | dmanr,DMA1_EXT_MODE_REG );
@@ -264,7 +264,7 @@ static __inline__ void set_dma_ext_mode(unsigned int dmanr, char ext_mode)* This is used for successive transfers when we know the contents of * the lower 16 bits of the DMA current address register. */ -static __inline__void set_dma_page (unsigned int dmanr,unsigned int pagenr) +static inline void set_dma_page (unsigned int dmanr,unsigned int pagenr) {switch (dmanr) {case 0 :
@@ -302,7 +302,7 @@ static __inline__ void set_dma_page(unsigned int dmanr, unsigned int pagenr)/* Set transfer address & page bits for specific DMA channel. * Assumes dma flipflop is clear. */ -static __inline__void set_dma_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_addr (unsigned int dmanr,unsigned int a) {if (dmanr <=3 ) {dma_outb ( a &0xff , ((dmanr&3 )<<1 ) +IO_DMA1_BASE );
@@ -323,7 +323,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)* Assumes dma flip-flop is clear. * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. */ -static __inline__void set_dma_count (unsigned int dmanr,unsigned int count) +static inline void set_dma_count (unsigned int dmanr,unsigned int count) { count--;if (dmanr <=3 ) {
@@ -344,7 +344,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)* * Assumes DMA flip-flop is clear. */ -static __inline__int get_dma_residue (unsigned int dmanr) +static inline int get_dma_residue (unsigned int dmanr) {unsigned int io_port = (dmanr<=3 )? ((dmanr&3 )<<1 ) +1 +IO_DMA1_BASE : ((dmanr&3 )<<2 ) +2 +IO_DMA2_BASE ;
arch/alpha/include/asm/floppy.h +2 -2
@@ -34,7 +34,7 @@#define fd_dma_setup (addr,size,mode,io) alpha_fd_dma_setup(addr,size,mode,io) -static __inline__int +static inline int alpha_fd_dma_setup (char *addr,unsigned long size,int mode,int io) {static unsigned long prev_size;
@@ -72,7 +72,7 @@ alpha_fd_dma_setup(char *addr, unsigned long size, int mode, int io)#endif /* CONFIG_PCI */ -__inline__void virtual_dma_init (void ) +inline void virtual_dma_init (void ) {/* Nothing to do on an Alpha */ }
arch/alpha/include/asm/irq.h +1 -1
@@ -77,7 +77,7 @@# define NR_IRQS 16#endif -static __inline__int irq_canonicalize (int irq) +static inline int irq_canonicalize (int irq) {/* * XXX is this true for all Alpha's? The old serial driver
arch/alpha/include/asm/local.h +2 -2
@@ -18,7 +18,7 @@ typedef struct#define local_add (i,l) atomic_long_add((i),(&(l)->a))#define local_sub (i,l) atomic_long_sub((i),(&(l)->a)) -static __inline__long local_add_return (long i,local_t * l) +static inline long local_add_return (long i,local_t * l) {long temp, result; __asm__ __volatile__(
@@ -35,7 +35,7 @@ static __inline__ long local_add_return(long i, local_t * l)return result; } -static __inline__long local_sub_return (long i,local_t * l) +static inline long local_sub_return (long i,local_t * l) {long temp, result; __asm__ __volatile__(
arch/alpha/include/asm/smp.h +1 -1
@@ -9,7 +9,7 @@/* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */ -static __inline__unsigned char +static inline unsigned char __hard_smp_processor_id (void ) { registerunsigned char __r0 __asm__("$0" );
arch/arm/mach-iop32x/include/mach/uncompress.h +1 -1
@@ -23,7 +23,7 @@ static inline void flush(void) { } -static __inline__void __arch_decomp_setup (unsigned long arch_id) +static inline void __arch_decomp_setup (unsigned long arch_id) {if (machine_is_iq80321 ()) uart_base = (volatile u8 *)IQ80321_UART ;
arch/arm/mach-iop33x/include/mach/uncompress.h +1 -1
@@ -23,7 +23,7 @@ static inline void flush(void) { } -static __inline__void __arch_decomp_setup (unsigned long arch_id) +static inline void __arch_decomp_setup (unsigned long arch_id) {if (machine_is_iq80331 () ||machine_is_iq80332 ()) uart_base = (volatile u32 *)IOP33X_UART0_PHYS ;
arch/arm/mach-ixp4xx/include/mach/uncompress.h +1 -1
@@ -35,7 +35,7 @@ static void flush(void) { } -static __inline__void __arch_decomp_setup (unsigned long arch_id) +static inline void __arch_decomp_setup (unsigned long arch_id) {/* * Some boards are using UART2 as console
arch/ia64/hp/common/sba_iommu.c +1 -1
@@ -107,7 +107,7 @@ extern int swiotlb_late_init_with_default_size (size_t size);#error FULL_VALID_PDIR and ASSERT_PDIR_SANITY are mutually exclusive#endif -#define SBA_INLINE __inline__ +#define SBA_INLINE inline/* #define SBA_INLINE */ #ifdef DEBUG_SBA_INIT
arch/ia64/hp/sim/simeth.c +1 -1
@@ -246,7 +246,7 @@ simeth_open(struct net_device *dev) }/* copied from lapbether.c */ -static __inline__int dev_is_ethdev (struct net_device *dev) +static inline int dev_is_ethdev (struct net_device *dev) {return ( dev->type ==ARPHRD_ETHER &&strncmp (dev->name,"dummy" ,5 )); }
arch/ia64/include/asm/atomic.h +4 -4
@@ -29,7 +29,7 @@#define atomic64_set (v,i) WRITE_ONCE(((v)->counter), (i))#define ATOMIC_OP (op, c_op) \ -static __inline__ int \ +static inline int \ ia64_atomic_##op (int i, atomic_t *v) \ { \ __s32 old, new; \
@@ -44,7 +44,7 @@ ia64_atomic_##op (int i, atomic_t *v) \ }#define ATOMIC_FETCH_OP (op, c_op) \ -static __inline__ int \ +static inline int \ ia64_atomic_fetch_##op (int i, atomic_t *v) \ { \ __s32 old, new; \
@@ -124,7 +124,7 @@ ATOMIC_FETCH_OP(xor, ^)#undef ATOMIC_OP#define ATOMIC64_OP (op, c_op) \ -static __inline__ long \ +static inline long \ ia64_atomic64_##op (__s64 i, atomic64_t *v) \ { \ __s64 old, new; \
@@ -139,7 +139,7 @@ ia64_atomic64_##op (__s64 i, atomic64_t *v) \ }#define ATOMIC64_FETCH_OP (op, c_op) \ -static __inline__ long \ +static inline long \ ia64_atomic64_fetch_##op (__s64 i, atomic64_t *v) \ { \ __s64 old, new; \
arch/ia64/include/asm/bitops.h +17 -17
@@ -36,7 +36,7 @@* * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). */ -static __inline__void +static inline void set_bit (int nr,volatile void *addr) {__u32 bit, old, new;
@@ -61,7 +61,7 @@ set_bit (int nr, volatile void *addr)* If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static __inline__void +static inline void __set_bit (int nr,volatile void *addr) { *((__u32 *) addr + (nr >>5 )) |= (1 << (nr &31 ));
@@ -77,7 +77,7 @@ __set_bit (int nr, volatile void *addr)* you should call smp_mb__before_atomic() and/or smp_mb__after_atomic() * in order to ensure changes are visible on other processors. */ -static __inline__void +static inline void clear_bit (int nr,volatile void *addr) {__u32 mask, old, new;
@@ -101,7 +101,7 @@ clear_bit (int nr, volatile void *addr)* clear_bit_unlock() is atomic and may not be reordered. It does * contain a memory barrier suitable for unlock type operations. */ -static __inline__void +static inline void clear_bit_unlock (int nr,volatile void *addr) {__u32 mask, old, new;
@@ -125,7 +125,7 @@ clear_bit_unlock (int nr, volatile void *addr)* Similarly to clear_bit_unlock, the implementation uses a store * with release semantics. See also arch_spin_unlock(). */ -static __inline__void +static inline void __clear_bit_unlock (int nr,void *addr) {__u32 *const m = (__u32 *) addr + (nr >>5 );
@@ -143,7 +143,7 @@ __clear_bit_unlock(int nr, void *addr)* If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static __inline__void +static inline void __clear_bit (int nr,volatile void *addr) { *((__u32 *) addr + (nr >>5 )) &= ~(1 << (nr &31 ));
@@ -158,7 +158,7 @@ __clear_bit (int nr, volatile void *addr)* Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static __inline__void +static inline void change_bit (int nr,volatile void *addr) {__u32 bit, old, new;
@@ -183,7 +183,7 @@ change_bit (int nr, volatile void *addr)* If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static __inline__void +static inline void __change_bit (int nr,volatile void *addr) { *((__u32 *) addr + (nr >>5 )) ^= (1 << (nr &31 ));
@@ -197,7 +197,7 @@ __change_bit (int nr, volatile void *addr)* This operation is atomic and cannot be reordered. * It also implies the acquisition side of the memory barrier. */ -static __inline__int +static inline int test_and_set_bit (int nr,volatile void *addr) {__u32 bit, old, new;
@@ -232,7 +232,7 @@ test_and_set_bit (int nr, volatile void *addr)* If two examples of this operation race, one can appear to succeed * but actually fail. You must protect multiple accesses with a lock. */ -static __inline__int +static inline int __test_and_set_bit (int nr,volatile void *addr) {__u32 *p = (__u32 *) addr + (nr >>5 );
@@ -251,7 +251,7 @@ __test_and_set_bit (int nr, volatile void *addr)* This operation is atomic and cannot be reordered. * It also implies the acquisition side of the memory barrier. */ -static __inline__int +static inline int test_and_clear_bit (int nr,volatile void *addr) {__u32 mask, old, new;
@@ -277,7 +277,7 @@ test_and_clear_bit (int nr, volatile void *addr)* If two examples of this operation race, one can appear to succeed * but actually fail. You must protect multiple accesses with a lock. */ -static __inline__int +static inline int __test_and_clear_bit (int nr,volatile void * addr) {__u32 *p = (__u32 *) addr + (nr >>5 );
@@ -296,7 +296,7 @@ __test_and_clear_bit(int nr, volatile void * addr)* This operation is atomic and cannot be reordered. * It also implies the acquisition side of the memory barrier. */ -static __inline__int +static inline int test_and_change_bit (int nr,volatile void *addr) {__u32 bit, old, new;
@@ -320,7 +320,7 @@ test_and_change_bit (int nr, volatile void *addr)* * This operation is non-atomic and can be reordered. */ -static __inline__int +static inline int __test_and_change_bit (int nr,void *addr) {__u32 old, bit = (1 << (nr &31 ));
@@ -331,7 +331,7 @@ __test_and_change_bit (int nr, void *addr)return (old & bit) !=0 ; } -static __inline__int +static inline int test_bit (int nr,const volatile void *addr) {return 1 & (((const volatile __u32 *) addr)[nr >>5 ] >> (nr &31 ));
@@ -359,7 +359,7 @@ ffz (unsigned long x)* * Undefined if no bit exists, so code should check against 0 first. */ -static __inline__unsigned long +static inline unsigned long __ffs (unsigned long x) {unsigned long result;
@@ -427,7 +427,7 @@ __fls (unsigned long x)* hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */ -static __inline__unsigned long __arch_hweight64 (unsigned long x) +static inline unsigned long __arch_hweight64 (unsigned long x) {unsigned long result; result =ia64_popcnt (x);
arch/ia64/include/asm/delay.h +7 -7
@@ -20,14 +20,14 @@#include <asm/intrinsics.h> #include <asm/processor.h> -static __inline__void +static inline void ia64_set_itm (unsigned long val) {ia64_setreg (_IA64_REG_CR_ITM, val);ia64_srlz_d (); } -static __inline__unsigned long +static inline unsigned long ia64_get_itm (void ) {unsigned long result;
@@ -37,27 +37,27 @@ ia64_get_itm (void)return result; } -static __inline__void +static inline void ia64_set_itv (unsigned long val) {ia64_setreg (_IA64_REG_CR_ITV, val);ia64_srlz_d (); } -static __inline__unsigned long +static inline unsigned long ia64_get_itv (void ) {return ia64_getreg (_IA64_REG_CR_ITV); } -static __inline__void +static inline void ia64_set_itc (unsigned long val) {ia64_setreg (_IA64_REG_AR_ITC, val);ia64_srlz_d (); } -static __inline__unsigned long +static inline unsigned long ia64_get_itc (void ) {unsigned long result;
@@ -75,7 +75,7 @@ ia64_get_itc (void)extern void ia64_delay_loop (unsigned long loops); -static __inline__void +static inline void __delay (unsigned long loops) {if (unlikely (loops <1 ))
arch/ia64/include/asm/irq.h +1 -1
@@ -16,7 +16,7 @@#include <linux/cpumask.h> #include <generated/nr-irqs.h> -static __inline__int +static inline int irq_canonicalize (int irq) {/*
arch/ia64/include/asm/page.h +1 -1
@@ -154,7 +154,7 @@ typedef union ia64_va {extern unsigned int hpage_shift;#endif -static __inline__int +static inline int get_order (unsigned long size) {long double d = size -1 ;
arch/ia64/include/asm/sn/leds.h +1 -1
@@ -22,7 +22,7 @@* Basic macros for flashing the LEDS on an SGI SN. */ -static __inline__void +static inline void set_led_bits (u8 value,u8 mask) { pda->led_state = (pda->led_state & ~mask) | (value & mask);
arch/ia64/include/asm/uaccess.h +2 -2
@@ -259,7 +259,7 @@ extern unsigned long __strnlen_user (const char __user *, long); })#define ARCH_HAS_TRANSLATE_MEM_PTR 1 -static __inline__void * +static inline void *xlate_dev_mem_ptr (phys_addr_t p) {struct page *page;
@@ -277,7 +277,7 @@ xlate_dev_mem_ptr(phys_addr_t p)/* * Convert a virtual cached kernel memory pointer to an uncached pointer */ -static __inline__void * +static inline void *xlate_dev_kmem_ptr (void *p) {struct page *page;
arch/ia64/include/uapi/asm/rse.h +6 -6
@@ -8,11 +8,11 @@* * Register stack engine related helper functions. This file may be * used in applications, so be careful about the name-space and give -* some consideration to non-GNU C compilers (though __inline__ is +* some consideration to non-GNU C compilers (though inline is * fine). */ -static __inline__unsigned long +static inline unsigned long ia64_rse_slot_num (unsigned long *addr) {return (((unsigned long ) addr) >>3 ) &0x3f ;
@@ -21,7 +21,7 @@ ia64_rse_slot_num (unsigned long *addr)/* * Return TRUE if ADDR is the address of an RNAT slot. */ -static __inline__unsigned long +static inline unsigned long ia64_rse_is_rnat_slot (unsigned long *addr) {return ia64_rse_slot_num (addr) ==0x3f ;
@@ -31,7 +31,7 @@ ia64_rse_is_rnat_slot (unsigned long *addr)* Returns the address of the RNAT slot that covers the slot at * address SLOT_ADDR. */ -static __inline__unsigned long * +static inline unsigned long *ia64_rse_rnat_addr (unsigned long *slot_addr) {return (unsigned long *) ((unsigned long ) slot_addr | (0x3f <<3 ));
@@ -42,7 +42,7 @@ ia64_rse_rnat_addr (unsigned long *slot_addr)* ending at BSP. This isn't simply (BSP-BSPSTORE)/8 because every 64th slot stores * ar.rnat. */ -static __inline__unsigned long +static inline unsigned long ia64_rse_num_regs (unsigned long *bspstore,unsigned long *bsp) {unsigned long slots = (bsp - bspstore);
@@ -54,7 +54,7 @@ ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)* The inverse of the above: given bspstore and the number of * registers, calculate ar.bsp. */ -static __inline__unsigned long * +static inline unsigned long *ia64_rse_skip_regs (unsigned long *addr,long num_regs) {long delta =ia64_rse_slot_num (addr) + num_regs;
arch/ia64/include/uapi/asm/swab.h +3 -3
@@ -11,7 +11,7 @@#include <asm/intrinsics.h> #include <linux/compiler.h> -static __inline__ __attribute_const__ __u64 __arch_swab64(__u64 x) +static inline __attribute_const__ __u64 __arch_swab64(__u64 x) {__u64 result;
@@ -20,13 +20,13 @@ static __inline__ __attribute_const__ __u64 __arch_swab64(__u64 x) }#define __arch_swab64 __arch_swab64 -static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 x) +static inline __attribute_const__ __u32 __arch_swab32(__u32 x) {return __arch_swab64 (x) >>32 ; }#define __arch_swab32 __arch_swab32 -static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 x) +static inline __attribute_const__ __u16 __arch_swab16(__u16 x) {return __arch_swab64 (x) >>48 ; }
arch/ia64/oprofile/backtrace.c +2 -2
@@ -32,7 +32,7 @@ typedef struct } ia64_backtrace_t;/* Returns non-zero if the PC is in the Interrupt Vector Table */ -static __inline__int in_ivt_code (unsigned long pc) +static inline int in_ivt_code (unsigned long pc) {extern char ia64_ivt[];return (pc >= (u_long )ia64_ivt && pc < (u_long )ia64_ivt+32768 );
@@ -41,7 +41,7 @@ static __inline__ int in_ivt_code(unsigned long pc)/* * Unwind to next stack frame. */ -static __inline__int next_frame (ia64_backtrace_t *bt) +static inline int next_frame (ia64_backtrace_t *bt) {/* * Avoid unsightly console message from unw_unwind() when attempting
arch/m68k/include/asm/blinken.h +1 -1
@@ -19,7 +19,7 @@extern unsigned char hp300_ledstate; -static __inline__void blinken_leds (int on,int off) +static inline void blinken_leds (int on,int off) {if (MACH_IS_HP300 ) {
arch/m68k/include/asm/checksum.h +1 -1
@@ -116,7 +116,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) }#define _HAVE_ARCH_IPV6_CSUM -static __inline____sum16 +static inline __sum16 csum_ipv6_magic (const struct in6_addr *saddr,const struct in6_addr *daddr,__u32 len,__u8 proto,__wsum sum) {
arch/m68k/include/asm/dma.h +16 -16
@@ -123,7 +123,7 @@ extern unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];#if !defined(CONFIG_M5272 )/* enable/disable a specific DMA channel */ -static __inline__void enable_dma (unsigned int dmanr) +static inline void enable_dma (unsigned int dmanr) {volatile unsigned short *dmawp;
@@ -135,7 +135,7 @@ static __inline__ void enable_dma(unsigned int dmanr) dmawp[MCFDMA_DCR ] |=MCFDMA_DCR_EEXT ; } -static __inline__void disable_dma (unsigned int dmanr) +static inline void disable_dma (unsigned int dmanr) {volatile unsigned short *dmawp;volatile unsigned char *dmapb;
@@ -162,12 +162,12 @@ static __inline__ void disable_dma(unsigned int dmanr)* * This is a NOP for ColdFire. Provide a stub for compatibility. */ -static __inline__void clear_dma_ff (unsigned int dmanr) +static inline void clear_dma_ff (unsigned int dmanr) { }/* set mode (above) for a specific DMA channel */ -static __inline__void set_dma_mode (unsigned int dmanr,char mode) +static inline void set_dma_mode (unsigned int dmanr,char mode) {volatile unsigned char *dmabp;
@@ -210,7 +210,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode) }/* Set transfer address for specific DMA channel */ -static __inline__void set_dma_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_addr (unsigned int dmanr,unsigned int a) {volatile unsigned short *dmawp;volatile unsigned int *dmalp;
@@ -247,7 +247,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)* Specific for Coldfire - sets device address. * Should be called after the mode set call, and before set DMA address. */ -static __inline__void set_dma_device_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_device_addr (unsigned int dmanr,unsigned int a) {#ifdef DMA_DEBUG printk ("set_dma_device_addr(dmanr=%d,a=%x)\n" , dmanr, a);
@@ -259,7 +259,7 @@ static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)/* * NOTE 2: "count" represents _bytes_. */ -static __inline__void set_dma_count (unsigned int dmanr,unsigned int count) +static inline void set_dma_count (unsigned int dmanr,unsigned int count) {volatile unsigned short *dmawp;
@@ -277,7 +277,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)* still in progress will return unpredictable results. * Otherwise, it returns the number of _bytes_ left to transfer. */ -static __inline__int get_dma_residue (unsigned int dmanr) +static inline int get_dma_residue (unsigned int dmanr) {volatile unsigned short *dmawp;unsigned short count;
@@ -316,7 +316,7 @@ static __inline__ int get_dma_residue(unsigned int dmanr)*/ /* enable/disable a specific DMA channel */ -static __inline__void enable_dma (unsigned int dmanr) +static inline void enable_dma (unsigned int dmanr) {volatile unsigned int *dmalp;
@@ -328,7 +328,7 @@ static __inline__ void enable_dma(unsigned int dmanr) dmalp[MCFDMA_DMR ] |=MCFDMA_DMR_EN ; } -static __inline__void disable_dma (unsigned int dmanr) +static inline void disable_dma (unsigned int dmanr) {volatile unsigned int *dmalp;
@@ -353,12 +353,12 @@ static __inline__ void disable_dma(unsigned int dmanr)* * This is a NOP for ColdFire. Provide a stub for compatibility. */ -static __inline__void clear_dma_ff (unsigned int dmanr) +static inline void clear_dma_ff (unsigned int dmanr) { }/* set mode (above) for a specific DMA channel */ -static __inline__void set_dma_mode (unsigned int dmanr,char mode) +static inline void set_dma_mode (unsigned int dmanr,char mode) {volatile unsigned int *dmalp;
@@ -396,7 +396,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode) }/* Set transfer address for specific DMA channel */ -static __inline__void set_dma_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_addr (unsigned int dmanr,unsigned int a) {volatile unsigned int *dmalp;
@@ -431,7 +431,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)* Specific for Coldfire - sets device address. * Should be called after the mode set call, and before set DMA address. */ -static __inline__void set_dma_device_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_device_addr (unsigned int dmanr,unsigned int a) {#ifdef DMA_DEBUG printk ("set_dma_device_addr(dmanr=%d,a=%x)\n" , dmanr, a);
@@ -445,7 +445,7 @@ static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a)* * NOTE 3: While a 32-bit register, "count" is only a maximum 24-bit value. */ -static __inline__void set_dma_count (unsigned int dmanr,unsigned int count) +static inline void set_dma_count (unsigned int dmanr,unsigned int count) {volatile unsigned int *dmalp;
@@ -463,7 +463,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)* still in progress will return unpredictable results. * Otherwise, it returns the number of _bytes_ left to transfer. */ -static __inline__int get_dma_residue (unsigned int dmanr) +static inline int get_dma_residue (unsigned int dmanr) {volatile unsigned int *dmalp;unsigned int count;
arch/m68k/include/asm/floppy.h +4 -4
@@ -50,20 +50,20 @@ static int doing_pdma=0;extern spinlock_t dma_spin_lock; -static __inline__unsigned long claim_dma_lock (void ) +static inline unsigned long claim_dma_lock (void ) {unsigned long flags;spin_lock_irqsave (&dma_spin_lock, flags);return flags; } -static __inline__void release_dma_lock (unsigned long flags) +static inline void release_dma_lock (unsigned long flags) {spin_unlock_irqrestore (&dma_spin_lock, flags); } -static __inline__unsigned char fd_inb (int port) +static inline unsigned char fd_inb (int port) {if (MACH_IS_Q40 )return inb_p (port);
@@ -72,7 +72,7 @@ static __inline__ unsigned char fd_inb(int port)return 0 ; } -static __inline__void fd_outb (unsigned char value,int port) +static inline void fd_outb (unsigned char value,int port) {if (MACH_IS_Q40 )outb_p (value, port);
arch/m68k/include/asm/nettel.h +4 -4
@@ -47,14 +47,14 @@ extern volatile unsigned short ppdata;* These functions defined to give quasi generic access to the * PPIO bits used for DTR/DCD. */ -static __inline__unsigned int mcf_getppdata (void ) +static inline unsigned int mcf_getppdata (void ) {volatile unsigned short *pp; pp = (volatile unsigned short *)MCFSIM_PADAT ;return ((unsigned int ) *pp); } -static __inline__void mcf_setppdata (unsigned int mask,unsigned int bits) +static inline void mcf_setppdata (unsigned int mask,unsigned int bits) {volatile unsigned short *pp; pp = (volatile unsigned short *)MCFSIM_PADAT ;
@@ -86,12 +86,12 @@ static __inline__ void mcf_setppdata(unsigned int mask, unsigned int bits)* These functions defined to give quasi generic access to the * PPIO bits used for DTR/DCD. */ -static __inline__unsigned int mcf_getppdata (void ) +static inline unsigned int mcf_getppdata (void ) {return readw (MCFSIM_PBDAT ); } -static __inline__void mcf_setppdata (unsigned int mask,unsigned int bits) +static inline void mcf_setppdata (unsigned int mask,unsigned int bits) {writew ((readw (MCFSIM_PBDAT ) & ~mask) | bits,MCFSIM_PBDAT ); }
arch/m68k/mac/iop.c +7 -7
@@ -161,42 +161,42 @@ irqreturn_t iop_ism_irq(int, void *);* Private access functions */ -static __inline__void iop_loadaddr (volatile struct mac_iop *iop,__u16 addr) +static inline void iop_loadaddr (volatile struct mac_iop *iop,__u16 addr) { iop->ram_addr_lo = addr; iop->ram_addr_hi = addr >>8 ; } -static __inline____u8 iop_readb (volatile struct mac_iop *iop,__u16 addr) +static inline __u8 iop_readb (volatile struct mac_iop *iop,__u16 addr) { iop->ram_addr_lo = addr; iop->ram_addr_hi = addr >>8 ;return iop->ram_data; } -static __inline__void iop_writeb (volatile struct mac_iop *iop,__u16 addr,__u8 data) +static inline void iop_writeb (volatile struct mac_iop *iop,__u16 addr,__u8 data) { iop->ram_addr_lo = addr; iop->ram_addr_hi = addr >>8 ; iop->ram_data = data; } -static __inline__void iop_stop (volatile struct mac_iop *iop) +static inline void iop_stop (volatile struct mac_iop *iop) { iop->status_ctrl &= ~IOP_RUN ; } -static __inline__void iop_start (volatile struct mac_iop *iop) +static inline void iop_start (volatile struct mac_iop *iop) { iop->status_ctrl =IOP_RUN |IOP_AUTOINC ; } -static __inline__void iop_bypass (volatile struct mac_iop *iop) +static inline void iop_bypass (volatile struct mac_iop *iop) { iop->status_ctrl |=IOP_BYPASS ; } -static __inline__void iop_interrupt (volatile struct mac_iop *iop) +static inline void iop_interrupt (volatile struct mac_iop *iop) { iop->status_ctrl |=IOP_IRQ ; }
arch/mips/include/asm/atomic.h +8 -8
@@ -53,7 +53,7 @@#define atomic_set (v, i) WRITE_ONCE((v)->counter, (i))#define ATOMIC_OP (op, c_op, asm_op) \ -static __inline__ void atomic_##op(int i, atomic_t * v) \ +static inline void atomic_##op(int i, atomic_t * v) \ { \ if (kernel_uses_llsc) { \ int temp; \
@@ -77,7 +77,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ }#define ATOMIC_OP_RETURN (op, c_op, asm_op) \ -static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v) \ +static inline int atomic_##op##_return_relaxed(int i, atomic_t * v) \ { \ int result; \ \
@@ -109,7 +109,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v) \ }#define ATOMIC_FETCH_OP (op, c_op, asm_op) \ -static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \ +static inline int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \ { \ int result; \ \
@@ -178,7 +178,7 @@ ATOMIC_OPS(xor, ^=, xor)* Atomically test @v and subtract @i if @v is greater or equal than @i. * The function returns the old value of @v minus @i. */ -static __inline__int atomic_sub_if_positive (int i,atomic_t * v) +static inline int atomic_sub_if_positive (int i,atomic_t * v) {int result;
@@ -246,7 +246,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)#define atomic64_set (v, i) WRITE_ONCE((v)->counter, (i))#define ATOMIC64_OP (op, c_op, asm_op) \ -static __inline__ void atomic64_##op(long i, atomic64_t * v) \ +static inline void atomic64_##op(long i, atomic64_t * v) \ { \ if (kernel_uses_llsc) { \ long temp; \
@@ -270,7 +270,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ }#define ATOMIC64_OP_RETURN (op, c_op, asm_op) \ -static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ +static inline long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ { \ long result; \ \
@@ -302,7 +302,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \ }#define ATOMIC64_FETCH_OP (op, c_op, asm_op) \ -static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ +static inline long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \ { \ long result; \ \
@@ -372,7 +372,7 @@ ATOMIC64_OPS(xor, ^=, xor)* Atomically test @v and subtract @i if @v is greater or equal than @i. * The function returns the old value of @v minus @i. */ -static __inline__long atomic64_sub_if_positive (long i,atomic64_t * v) +static inline long atomic64_sub_if_positive (long i,atomic64_t * v) {long result;
arch/mips/include/asm/checksum.h +1 -1
@@ -215,7 +215,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) }#define _HAVE_ARCH_IPV6_CSUM -static __inline____sum16 csum_ipv6_magic (const struct in6_addr *saddr, +static inline __sum16 csum_ipv6_magic (const struct in6_addr *saddr,const struct in6_addr *daddr,__u32 len,__u8 proto,__wsum sum)
arch/mips/include/asm/dma.h +10 -10
@@ -157,20 +157,20 @@extern spinlock_t dma_spin_lock; -static __inline__unsigned long claim_dma_lock (void ) +static inline unsigned long claim_dma_lock (void ) {unsigned long flags;spin_lock_irqsave (&dma_spin_lock, flags);return flags; } -static __inline__void release_dma_lock (unsigned long flags) +static inline void release_dma_lock (unsigned long flags) {spin_unlock_irqrestore (&dma_spin_lock, flags); }/* enable/disable a specific DMA channel */ -static __inline__void enable_dma (unsigned int dmanr) +static inline void enable_dma (unsigned int dmanr) {if (dmanr<=3 )dma_outb (dmanr,DMA1_MASK_REG );
@@ -178,7 +178,7 @@ static __inline__ void enable_dma(unsigned int dmanr)dma_outb (dmanr &3 ,DMA2_MASK_REG ); } -static __inline__void disable_dma (unsigned int dmanr) +static inline void disable_dma (unsigned int dmanr) {if (dmanr<=3 )dma_outb (dmanr |4 ,DMA1_MASK_REG );
@@ -193,7 +193,7 @@ static __inline__ void disable_dma(unsigned int dmanr)* --- In order to do that, the DMA routines below should --- * --- only be used while holding the DMA lock ! --- */ -static __inline__void clear_dma_ff (unsigned int dmanr) +static inline void clear_dma_ff (unsigned int dmanr) {if (dmanr<=3 )dma_outb (0 ,DMA1_CLEAR_FF_REG );
@@ -202,7 +202,7 @@ static __inline__ void clear_dma_ff(unsigned int dmanr) }/* set mode (above) for a specific DMA channel */ -static __inline__void set_dma_mode (unsigned int dmanr,char mode) +static inline void set_dma_mode (unsigned int dmanr,char mode) {if (dmanr<=3 )dma_outb (mode | dmanr,DMA1_MODE_REG );
@@ -215,7 +215,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)* the lower 16 bits of the DMA current address register, but a 64k boundary * may have been crossed. */ -static __inline__void set_dma_page (unsigned int dmanr,char pagenr) +static inline void set_dma_page (unsigned int dmanr,char pagenr) {switch (dmanr) {case 0 :
@@ -246,7 +246,7 @@ static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)/* Set transfer address & page bits for specific DMA channel. * Assumes dma flipflop is clear. */ -static __inline__void set_dma_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_addr (unsigned int dmanr,unsigned int a) {set_dma_page (dmanr, a>>16 );if (dmanr <=3 ) {
@@ -267,7 +267,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)* Assumes dma flip-flop is clear. * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. */ -static __inline__void set_dma_count (unsigned int dmanr,unsigned int count) +static inline void set_dma_count (unsigned int dmanr,unsigned int count) { count--;if (dmanr <=3 ) {
@@ -288,7 +288,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)* * Assumes DMA flip-flop is clear. */ -static __inline__int get_dma_residue (unsigned int dmanr) +static inline int get_dma_residue (unsigned int dmanr) {unsigned int io_port = (dmanr<=3 )? ((dmanr&3 )<<1 ) +1 +IO_DMA1_BASE : ((dmanr&3 )<<2 ) +2 +IO_DMA2_BASE ;
arch/mips/include/asm/jazz.h +1 -1
@@ -72,7 +72,7 @@#ifndef __ASSEMBLY__ -static __inline__void pica_set_led (unsigned int bits) +static inline void pica_set_led (unsigned int bits) {volatile unsigned int *led_register = (unsigned int *)PICA_LED ;
arch/mips/include/asm/local.h +2 -2
@@ -27,7 +27,7 @@ typedef struct/* * Same as above, but return the result value */ -static __inline__long local_add_return (long i,local_t * l) +static inline long local_add_return (long i,local_t * l) {unsigned long result;
@@ -72,7 +72,7 @@ static __inline__ long local_add_return(long i, local_t * l)return result; } -static __inline__long local_sub_return (long i,local_t * l) +static inline long local_sub_return (long i,local_t * l) {unsigned long result;
arch/mips/include/asm/string.h +4 -4
@@ -20,7 +20,7 @@#ifndef IN_STRING_C #define __HAVE_ARCH_STRCPY -static __inline__ char *strcpy(char *__dest, __const__ char *__src) +static inline char *strcpy(char *__dest, __const__ char *__src) {char *__xdest = __dest;
@@ -42,7 +42,7 @@ static __inline__ char *strcpy(char *__dest, __const__ char *__src) }#define __HAVE_ARCH_STRNCPY -static __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n) +static inline char *strncpy(char *__dest, __const__ char *__src, size_t __n) {char *__xdest = __dest;
@@ -70,7 +70,7 @@ static __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n) }#define __HAVE_ARCH_STRCMP -static __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct) +static inline int strcmp(__const__ char *__cs, __const__ char *__ct) {int __res;
@@ -100,7 +100,7 @@ static __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct)#endif /* !defined(IN_STRING_C) */ #define __HAVE_ARCH_STRNCMP -static __inline__int +static inline int strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count) {int __res;
arch/mips/kernel/binfmt_elfn32.c +1 -1
@@ -82,7 +82,7 @@ struct elf_prpsinfo32#define init_elf_binfmt init_elfn32_binfmt#define jiffies_to_timeval jiffies_to_old_timeval32 -static __inline__void +static inline void jiffies_to_old_timeval32 (unsigned long jiffies,struct old_timeval32 *value) {/*
arch/nds32/include/asm/swab.h +2 -2
@@ -7,7 +7,7 @@#include <linux/types.h> #include <linux/compiler.h> -static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __asm__("wsbh %0, %0\n\t" /* word swap byte within halfword */ "rotri %0, %0, #16\n"
@@ -16,7 +16,7 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)return x; } -static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) { __asm__("wsbh %0, %0\n" /* word swap byte within halfword */ :"=r"(x)
arch/parisc/include/asm/atomic.h +10 -10
@@ -56,7 +56,7 @@ extern arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;* are atomic, so a reader never sees inconsistent values. */ -static __inline__void atomic_set (atomic_t *v,int i) +static inline void atomic_set (atomic_t *v,int i) {unsigned long flags;_atomic_spin_lock_irqsave (v, flags);
@@ -68,7 +68,7 @@ static __inline__ void atomic_set(atomic_t *v, int i)#define atomic_set_release (v, i) atomic_set((v), (i)) -static __inline__int atomic_read (const atomic_t *v) +static inline int atomic_read (const atomic_t *v) {return READ_ONCE ((v)->counter); }
@@ -78,7 +78,7 @@ static __inline__ int atomic_read(const atomic_t *v)#define atomic_xchg (v, new) (xchg(&((v)->counter), new))#define ATOMIC_OP (op, c_op) \ -static __inline__ void atomic_##op(int i, atomic_t *v) \ +static inline void atomic_##op(int i, atomic_t *v) \ { \ unsigned long flags; \ \
@@ -88,7 +88,7 @@ static __inline__ void atomic_##op(int i, atomic_t *v) \ } \#define ATOMIC_OP_RETURN (op, c_op) \ -static __inline__ int atomic_##op##_return(int i, atomic_t *v) \ +static inline int atomic_##op##_return(int i, atomic_t *v) \ { \ unsigned long flags; \ int ret; \
@@ -101,7 +101,7 @@ static __inline__ int atomic_##op##_return(int i, atomic_t *v) \ }#define ATOMIC_FETCH_OP (op, c_op) \ -static __inline__ int atomic_fetch_##op(int i, atomic_t *v) \ +static inline int atomic_fetch_##op(int i, atomic_t *v) \ { \ unsigned long flags; \ int ret; \
@@ -143,7 +143,7 @@ ATOMIC_OPS(xor, ^=)#define ATOMIC64_INIT (i) { (i) }#define ATOMIC64_OP (op, c_op) \ -static __inline__ void atomic64_##op(s64 i, atomic64_t *v) \ +static inline void atomic64_##op(s64 i, atomic64_t *v) \ { \ unsigned long flags; \ \
@@ -153,7 +153,7 @@ static __inline__ void atomic64_##op(s64 i, atomic64_t *v) \ } \#define ATOMIC64_OP_RETURN (op, c_op) \ -static __inline__ s64 atomic64_##op##_return(s64 i, atomic64_t *v) \ +static inline s64 atomic64_##op##_return(s64 i, atomic64_t *v) \ { \ unsigned long flags; \ s64 ret; \
@@ -166,7 +166,7 @@ static __inline__ s64 atomic64_##op##_return(s64 i, atomic64_t *v) \ }#define ATOMIC64_FETCH_OP (op, c_op) \ -static __inline__ s64 atomic64_fetch_##op(s64 i, atomic64_t *v) \ +static inline s64 atomic64_fetch_##op(s64 i, atomic64_t *v) \ { \ unsigned long flags; \ s64 ret; \
@@ -201,7 +201,7 @@ ATOMIC64_OPS(xor, ^=)#undef ATOMIC64_OP_RETURN#undef ATOMIC64_OP -static __inline__void +static inline void atomic64_set (atomic64_t *v,s64 i) {unsigned long flags;
@@ -212,7 +212,7 @@ atomic64_set(atomic64_t *v, s64 i)_atomic_spin_unlock_irqrestore (v, flags); } -static __inline__s64 +static inline s64 atomic64_read (const atomic64_t *v) {return READ_ONCE ((v)->counter);
arch/parisc/include/asm/bitops.h +9 -9
@@ -33,7 +33,7 @@* __*_bit() are "relaxed" and don't use spinlock or volatile. */ -static __inline__void set_bit (int nr,volatile unsigned long * addr) +static inline void set_bit (int nr,volatile unsigned long * addr) {unsigned long mask =1UL <<CHOP_SHIFTCOUNT (nr);unsigned long flags;
@@ -44,7 +44,7 @@ static __inline__ void set_bit(int nr, volatile unsigned long * addr)_atomic_spin_unlock_irqrestore (addr, flags); } -static __inline__void clear_bit (int nr,volatile unsigned long * addr) +static inline void clear_bit (int nr,volatile unsigned long * addr) {unsigned long mask = ~(1UL <<CHOP_SHIFTCOUNT (nr));unsigned long flags;
@@ -55,7 +55,7 @@ static __inline__ void clear_bit(int nr, volatile unsigned long * addr)_atomic_spin_unlock_irqrestore (addr, flags); } -static __inline__void change_bit (int nr,volatile unsigned long * addr) +static inline void change_bit (int nr,volatile unsigned long * addr) {unsigned long mask =1UL <<CHOP_SHIFTCOUNT (nr);unsigned long flags;
@@ -66,7 +66,7 @@ static __inline__ void change_bit(int nr, volatile unsigned long * addr)_atomic_spin_unlock_irqrestore (addr, flags); } -static __inline__int test_and_set_bit (int nr,volatile unsigned long * addr) +static inline int test_and_set_bit (int nr,volatile unsigned long * addr) {unsigned long mask =1UL <<CHOP_SHIFTCOUNT (nr);unsigned long old;
@@ -84,7 +84,7 @@ static __inline__ int test_and_set_bit(int nr, volatile unsigned long * addr)return set; } -static __inline__int test_and_clear_bit (int nr,volatile unsigned long * addr) +static inline int test_and_clear_bit (int nr,volatile unsigned long * addr) {unsigned long mask =1UL <<CHOP_SHIFTCOUNT (nr);unsigned long old;
@@ -102,7 +102,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile unsigned long * addr)return set; } -static __inline__int test_and_change_bit (int nr,volatile unsigned long * addr) +static inline int test_and_change_bit (int nr,volatile unsigned long * addr) {unsigned long mask =1UL <<CHOP_SHIFTCOUNT (nr);unsigned long oldbit;
@@ -140,7 +140,7 @@ static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr)* cycles for each mispredicted branch. */ -static __inline__unsigned long __ffs (unsigned long x) +static inline unsigned long __ffs (unsigned long x) {unsigned long ret;
@@ -178,7 +178,7 @@ static __inline__ unsigned long __ffs(unsigned long x)* This is defined the same way as the libc and compiler builtin * ffs routines, therefore differs in spirit from the above ffz (man ffs). */ -static __inline__int ffs (int x) +static inline int ffs (int x) {return x ? (__ffs ((unsigned long )x) +1 ) :0 ; }
@@ -188,7 +188,7 @@ static __inline__ int ffs(int x)* fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */ -static __inline__int fls (int x) +static inline int fls (int x) {int ret;if (!x)
arch/parisc/include/asm/checksum.h +2 -2
@@ -121,7 +121,7 @@ static inline __sum16 ip_compute_csum(const void *buf, int len)#define _HAVE_ARCH_IPV6_CSUM -static __inline____sum16 csum_ipv6_magic (const struct in6_addr *saddr, +static inline __sum16 csum_ipv6_magic (const struct in6_addr *saddr,const struct in6_addr *daddr,__u32 len,__u8 proto,__wsum sum)
@@ -189,7 +189,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,* Copy and checksum to user */ #define HAVE_CSUM_COPY_USER -static __inline____wsum csum_and_copy_to_user (const void *src, +static inline __wsum csum_and_copy_to_user (const void *src,void __user *dst,int len,__wsum sum,int *err_ptr)
arch/parisc/include/asm/compat.h +1 -1
@@ -190,7 +190,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)return (u32 )(unsigned long )uptr; } -static __inline__void __user *arch_compat_alloc_user_space (long len) +static inline void __user *arch_compat_alloc_user_space (long len) {struct pt_regs *regs = ¤t->thread.regs;return (void __user *)regs->gr[30 ];
arch/parisc/include/asm/delay.h +1 -1
@@ -2,7 +2,7 @@#ifndef _ASM_PARISC_DELAY_H#define _ASM_PARISC_DELAY_H -static __inline__void __delay (unsigned long loops) { +static inline void __delay (unsigned long loops) { asmvolatile (" .balignl 64,0x34000034\n" " addib,UV -1,%0,.\n"
arch/parisc/include/asm/dma.h +10 -10
@@ -71,12 +71,12 @@#define DMA2_MASK_ALL_REG 0xDE/* all-channels mask (w) */ #define DMA2_EXT_MODE_REG (0x400 | DMA2_MODE_REG) -static __inline__unsigned long claim_dma_lock (void ) +static inline unsigned long claim_dma_lock (void ) {return 0 ; } -static __inline__void release_dma_lock (unsigned long flags) +static inline void release_dma_lock (unsigned long flags) { }
@@ -89,7 +89,7 @@ static __inline__ void release_dma_lock(unsigned long flags)* * Assumes DMA flip-flop is clear. */ -static __inline__int get_dma_residue (unsigned int dmanr) +static inline int get_dma_residue (unsigned int dmanr) {unsigned int io_port = (dmanr<=3 )? ((dmanr&3 )<<1 ) +1 +IO_DMA1_BASE : ((dmanr&3 )<<2 ) +2 +IO_DMA2_BASE ;
@@ -104,7 +104,7 @@ static __inline__ int get_dma_residue(unsigned int dmanr) }/* enable/disable a specific DMA channel */ -static __inline__void enable_dma (unsigned int dmanr) +static inline void enable_dma (unsigned int dmanr) {#ifdef CONFIG_SUPERIO if (dmanr<=3 )
@@ -114,7 +114,7 @@ static __inline__ void enable_dma(unsigned int dmanr)#endif } -static __inline__void disable_dma (unsigned int dmanr) +static inline void disable_dma (unsigned int dmanr) {#ifdef CONFIG_SUPERIO if (dmanr<=3 )
@@ -134,12 +134,12 @@ static __inline__ void disable_dma(unsigned int dmanr)* --- In order to do that, the DMA routines below should --- * --- only be used while holding the DMA lock ! --- */ -static __inline__void clear_dma_ff (unsigned int dmanr) +static inline void clear_dma_ff (unsigned int dmanr) { }/* set mode (above) for a specific DMA channel */ -static __inline__void set_dma_mode (unsigned int dmanr,char mode) +static inline void set_dma_mode (unsigned int dmanr,char mode) { }
@@ -148,7 +148,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)* the lower 16 bits of the DMA current address register, but a 64k boundary * may have been crossed. */ -static __inline__void set_dma_page (unsigned int dmanr,char pagenr) +static inline void set_dma_page (unsigned int dmanr,char pagenr) { }
@@ -156,7 +156,7 @@ static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)/* Set transfer address & page bits for specific DMA channel. * Assumes dma flipflop is clear. */ -static __inline__void set_dma_addr (unsigned int dmanr,unsigned int a) +static inline void set_dma_addr (unsigned int dmanr,unsigned int a) { }
@@ -169,7 +169,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)* Assumes dma flip-flop is clear. * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. */ -static __inline__void set_dma_count (unsigned int dmanr,unsigned int count) +static inline void set_dma_count (unsigned int dmanr,unsigned int count) { }
arch/parisc/include/asm/ide.h +4 -4
@@ -21,7 +21,7 @@#define __ide_outsw outsw#define __ide_outsl outsl -static __inline__void __ide_mm_insw (void __iomem *port,void *addr,u32 count) +static inline void __ide_mm_insw (void __iomem *port,void *addr,u32 count) {while (count--) { *(u16 *)addr =__raw_readw (port);
@@ -29,7 +29,7 @@ static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count) } } -static __inline__void __ide_mm_insl (void __iomem *port,void *addr,u32 count) +static inline void __ide_mm_insl (void __iomem *port,void *addr,u32 count) {while (count--) { *(u32 *)addr =__raw_readl (port);
@@ -37,7 +37,7 @@ static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count) } } -static __inline__void __ide_mm_outsw (void __iomem *port,void *addr,u32 count) +static inline void __ide_mm_outsw (void __iomem *port,void *addr,u32 count) {while (count--) {__raw_writew (*(u16 *)addr, port);
@@ -45,7 +45,7 @@ static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count) } } -static __inline__void __ide_mm_outsl (void __iomem *port,void *addr,u32 count) +static inline void __ide_mm_outsl (void __iomem *port,void *addr,u32 count) {while (count--) {__raw_writel (*(u32 *)addr, port);
arch/parisc/include/asm/irq.h +1 -1
@@ -27,7 +27,7 @@#define NR_IRQS (CPU_IRQ_MAX + 1) -static __inline__int irq_canonicalize (int irq) +static inline int irq_canonicalize (int irq) {return (irq ==2 ) ?9 : irq; }
arch/parisc/include/asm/spinlock.h +6 -6
@@ -66,7 +66,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *x)/* Note that we have to ensure interrupts are disabled in case we're * interrupted by some other code that wants to grab the same read lock */ -static __inline__void arch_read_lock (arch_rwlock_t *rw) +static inline void arch_read_lock (arch_rwlock_t *rw) {unsigned long flags;local_irq_save (flags);
@@ -78,7 +78,7 @@ static __inline__ void arch_read_lock(arch_rwlock_t *rw)/* Note that we have to ensure interrupts are disabled in case we're * interrupted by some other code that wants to grab the same read lock */ -static __inline__void arch_read_unlock (arch_rwlock_t *rw) +static inline void arch_read_unlock (arch_rwlock_t *rw) {unsigned long flags;local_irq_save (flags);
@@ -90,7 +90,7 @@ static __inline__ void arch_read_unlock(arch_rwlock_t *rw)/* Note that we have to ensure interrupts are disabled in case we're * interrupted by some other code that wants to grab the same read lock */ -static __inline__int arch_read_trylock (arch_rwlock_t *rw) +static inline int arch_read_trylock (arch_rwlock_t *rw) {unsigned long flags; retry:
@@ -116,7 +116,7 @@ static __inline__ int arch_read_trylock(arch_rwlock_t *rw)/* Note that we have to ensure interrupts are disabled in case we're * interrupted by some other code that wants to read_trylock() this lock */ -static __inline__void arch_write_lock (arch_rwlock_t *rw) +static inline void arch_write_lock (arch_rwlock_t *rw) {unsigned long flags; retry:
@@ -138,7 +138,7 @@ static __inline__ void arch_write_lock(arch_rwlock_t *rw)local_irq_restore (flags); } -static __inline__void arch_write_unlock (arch_rwlock_t *rw) +static inline void arch_write_unlock (arch_rwlock_t *rw) { rw->counter =0 ;arch_spin_unlock (&rw->lock);
@@ -146,7 +146,7 @@ static __inline__ void arch_write_unlock(arch_rwlock_t *rw)/* Note that we have to ensure interrupts are disabled in case we're * interrupted by some other code that wants to read_trylock() this lock */ -static __inline__int arch_write_trylock (arch_rwlock_t *rw) +static inline int arch_write_trylock (arch_rwlock_t *rw) {unsigned long flags;int result =0 ;
arch/powerpc/include/asm/atomic.h +20 -20
@@ -25,7 +25,7 @@#define __atomic_release_fence () \ __asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory") -static __inline__int atomic_read (const atomic_t *v) +static inline int atomic_read (const atomic_t *v) {int t;
@@ -34,13 +34,13 @@ static __inline__ int atomic_read(const atomic_t *v)return t; } -static __inline__void atomic_set (atomic_t *v,int i) +static inline void atomic_set (atomic_t *v,int i) { __asm__ __volatile__("stw%U0%X0 %1,%0" :"=m" (v->counter) :"r" (i)); }#define ATOMIC_OP (op, asm_op) \ -static __inline__ void atomic_##op(int a, atomic_t *v) \ +static inline void atomic_##op(int a, atomic_t *v) \ { \ int t; \ \
@@ -123,7 +123,7 @@ ATOMIC_OPS(xor, xor)#undef ATOMIC_OP_RETURN_RELAXED#undef ATOMIC_OP -static __inline__void atomic_inc (atomic_t *v) +static inline void atomic_inc (atomic_t *v) {int t;
@@ -139,7 +139,7 @@ static __inline__ void atomic_inc(atomic_t *v) }#define atomic_inc atomic_inc -static __inline__int atomic_inc_return_relaxed (atomic_t *v) +static inline int atomic_inc_return_relaxed (atomic_t *v) {int t;
@@ -156,7 +156,7 @@ static __inline__ int atomic_inc_return_relaxed(atomic_t *v)return t; } -static __inline__void atomic_dec (atomic_t *v) +static inline void atomic_dec (atomic_t *v) {int t;
@@ -172,7 +172,7 @@ static __inline__ void atomic_dec(atomic_t *v) }#define atomic_dec atomic_dec -static __inline__int atomic_dec_return_relaxed (atomic_t *v) +static inline int atomic_dec_return_relaxed (atomic_t *v) {int t;
@@ -210,7 +210,7 @@ static __inline__ int atomic_dec_return_relaxed(atomic_t *v)* Atomically adds @a to @v, so long as it was not @u. * Returns the old value of @v. */ -static __inline__int atomic_fetch_add_unless (atomic_t *v,int a,int u) +static inline int atomic_fetch_add_unless (atomic_t *v,int a,int u) {int t;
@@ -241,7 +241,7 @@ static __inline__ int atomic_fetch_add_unless(atomic_t *v, int a, int u)* Atomically increments @v by 1, so long as @v is non-zero. * Returns non-zero if @v was non-zero, and zero otherwise. */ -static __inline__int atomic_inc_not_zero (atomic_t *v) +static inline int atomic_inc_not_zero (atomic_t *v) {int t1, t2;
@@ -270,7 +270,7 @@ static __inline__ int atomic_inc_not_zero(atomic_t *v)* The function returns the old value of *v minus 1, even if * the atomic variable, v, was not decremented. */ -static __inline__int atomic_dec_if_positive (atomic_t *v) +static inline int atomic_dec_if_positive (atomic_t *v) {int t;
@@ -297,7 +297,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)#define ATOMIC64_INIT (i) { (i) } -static __inline__long atomic64_read (const atomic64_t *v) +static inline long atomic64_read (const atomic64_t *v) {long t;
@@ -306,13 +306,13 @@ static __inline__ long atomic64_read(const atomic64_t *v)return t; } -static __inline__void atomic64_set (atomic64_t *v,long i) +static inline void atomic64_set (atomic64_t *v,long i) { __asm__ __volatile__("std%U0%X0 %1,%0" :"=m" (v->counter) :"r" (i)); }#define ATOMIC64_OP (op, asm_op) \ -static __inline__ void atomic64_##op(long a, atomic64_t *v) \ +static inline void atomic64_##op(long a, atomic64_t *v) \ { \ long t; \ \
@@ -394,7 +394,7 @@ ATOMIC64_OPS(xor, xor)#undef ATOMIC64_OP_RETURN_RELAXED#undef ATOMIC64_OP -static __inline__void atomic64_inc (atomic64_t *v) +static inline void atomic64_inc (atomic64_t *v) {long t;
@@ -409,7 +409,7 @@ static __inline__ void atomic64_inc(atomic64_t *v) }#define atomic64_inc atomic64_inc -static __inline__long atomic64_inc_return_relaxed (atomic64_t *v) +static inline long atomic64_inc_return_relaxed (atomic64_t *v) {long t;
@@ -425,7 +425,7 @@ static __inline__ long atomic64_inc_return_relaxed(atomic64_t *v)return t; } -static __inline__void atomic64_dec (atomic64_t *v) +static inline void atomic64_dec (atomic64_t *v) {long t;
@@ -440,7 +440,7 @@ static __inline__ void atomic64_dec(atomic64_t *v) }#define atomic64_dec atomic64_dec -static __inline__long atomic64_dec_return_relaxed (atomic64_t *v) +static inline long atomic64_dec_return_relaxed (atomic64_t *v) {long t;
@@ -463,7 +463,7 @@ static __inline__ long atomic64_dec_return_relaxed(atomic64_t *v)* Atomically test *v and decrement if it is greater than 0. * The function returns the old value of *v minus 1. */ -static __inline__long atomic64_dec_if_positive (atomic64_t *v) +static inline long atomic64_dec_if_positive (atomic64_t *v) {long t;
@@ -502,7 +502,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)* Atomically adds @a to @v, so long as it was not @u. * Returns the old value of @v. */ -static __inline__long atomic64_fetch_add_unless (atomic64_t *v,long a,long u) +static inline long atomic64_fetch_add_unless (atomic64_t *v,long a,long u) {long t;
@@ -532,7 +532,7 @@ static __inline__ long atomic64_fetch_add_unless(atomic64_t *v, long a, long u)* Atomically increments @v by 1, so long as @v is non-zero. * Returns non-zero if @v was non-zero, and zero otherwise. */ -static __inline__int atomic64_inc_not_zero (atomic64_t *v) +static inline int atomic64_inc_not_zero (atomic64_t *v) {long t1, t2;
arch/powerpc/include/asm/bitops.h +14 -14
@@ -68,7 +68,7 @@/* Macro for generating the ***_bits() functions */ #define DEFINE_BITOP (fn, op, prefix) \ -static __inline__ void fn(unsigned long mask, \ +static inline void fn(unsigned long mask, \ volatile unsigned long *_p) \ { \ unsigned long old; \
@@ -90,22 +90,22 @@ DEFINE_BITOP(clear_bits, andc, "") DEFINE_BITOP(clear_bits_unlock, andc, PPC_RELEASE_BARRIER) DEFINE_BITOP(change_bits, xor, "") -static __inline__void set_bit (int nr,volatile unsigned long *addr) +static inline void set_bit (int nr,volatile unsigned long *addr) {set_bits (BIT_MASK (nr), addr +BIT_WORD (nr)); } -static __inline__void clear_bit (int nr,volatile unsigned long *addr) +static inline void clear_bit (int nr,volatile unsigned long *addr) {clear_bits (BIT_MASK (nr), addr +BIT_WORD (nr)); } -static __inline__void clear_bit_unlock (int nr,volatile unsigned long *addr) +static inline void clear_bit_unlock (int nr,volatile unsigned long *addr) {clear_bits_unlock (BIT_MASK (nr), addr +BIT_WORD (nr)); } -static __inline__void change_bit (int nr,volatile unsigned long *addr) +static inline void change_bit (int nr,volatile unsigned long *addr) {change_bits (BIT_MASK (nr), addr +BIT_WORD (nr)); }
@@ -113,7 +113,7 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr)/* Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output * operands. */ #define DEFINE_TESTOP (fn, op, prefix, postfix, eh) \ -static __inline__ unsigned long fn( \ +static inline unsigned long fn( \ unsigned long mask, \ volatile unsigned long *_p) \ { \
@@ -142,33 +142,33 @@ DEFINE_TESTOP(test_and_clear_bits, andc, PPC_ATOMIC_ENTRY_BARRIER,DEFINE_TESTOP (test_and_change_bits, xor,PPC_ATOMIC_ENTRY_BARRIER , PPC_ATOMIC_EXIT_BARRIER, 0) -static __inline__int test_and_set_bit (unsigned long nr, +static inline int test_and_set_bit (unsigned long nr,volatile unsigned long *addr) {return test_and_set_bits (BIT_MASK (nr), addr +BIT_WORD (nr)) !=0 ; } -static __inline__int test_and_set_bit_lock (unsigned long nr, +static inline int test_and_set_bit_lock (unsigned long nr,volatile unsigned long *addr) {return test_and_set_bits_lock (BIT_MASK (nr), addr +BIT_WORD (nr)) !=0 ; } -static __inline__int test_and_clear_bit (unsigned long nr, +static inline int test_and_clear_bit (unsigned long nr,volatile unsigned long *addr) {return test_and_clear_bits (BIT_MASK (nr), addr +BIT_WORD (nr)) !=0 ; } -static __inline__int test_and_change_bit (unsigned long nr, +static inline int test_and_change_bit (unsigned long nr,volatile unsigned long *addr) {return test_and_change_bits (BIT_MASK (nr), addr +BIT_WORD (nr)) !=0 ; }#ifdef CONFIG_PPC64 -static __inline__unsigned long clear_bit_unlock_return_word (int nr, +static inline unsigned long clear_bit_unlock_return_word (int nr,volatile unsigned long *addr) {unsigned long old, t;
@@ -197,7 +197,7 @@ static __inline__ unsigned long clear_bit_unlock_return_word(int nr,#include <asm-generic/bitops/non-atomic.h> -static __inline__void __clear_bit_unlock (int nr,volatile unsigned long *addr) +static inline void __clear_bit_unlock (int nr,volatile unsigned long *addr) { __asm__ __volatile__(PPC_RELEASE_BARRIER "" :::"memory" );__clear_bit (nr, addr);
@@ -219,14 +219,14 @@ static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr)* fls: find last (most-significant) bit set. * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */ -static __inline__int fls (unsigned int x) +static inline int fls (unsigned int x) {return 32 -__builtin_clz (x); }#include <asm-generic/bitops/builtin-__fls.h> -static __inline__int fls64 (__u64 x) +static inline int fls64 (__u64 x) {return 64 -__builtin_clzll (x); }
arch/powerpc/include/asm/dma.h +10 -10
@@ -166,20 +166,20 @@extern spinlock_t dma_spin_lock; -static __inline__unsigned long claim_dma_lock (void ) +static inline unsigned long claim_dma_lock (void ) {unsigned long flags;spin_lock_irqsave (&dma_spin_lock, flags);return flags; } -static __inline__void release_dma_lock (unsigned long flags) +static inline void release_dma_lock (unsigned long flags) {spin_unlock_irqrestore (&dma_spin_lock, flags); }/* enable/disable a specific DMA channel */ -static __inline__void enable_dma (unsigned int dmanr) +static inline void enable_dma (unsigned int dmanr) {unsigned char ucDmaCmd =0x00 ;
@@ -195,7 +195,7 @@ static __inline__ void enable_dma(unsigned int dmanr) } } -static __inline__void disable_dma (unsigned int dmanr) +static inline void disable_dma (unsigned int dmanr) {if (dmanr <=3 )dma_outb (dmanr |4 ,DMA1_MASK_REG );
@@ -210,7 +210,7 @@ static __inline__ void disable_dma(unsigned int dmanr)* --- In order to do that, the DMA routines below should --- * --- only be used while interrupts are disabled! --- */ -static __inline__void clear_dma_ff (unsigned int dmanr) +static inline void clear_dma_ff (unsigned int dmanr) {if (dmanr <=3 )dma_outb (0 ,DMA1_CLEAR_FF_REG );
@@ -219,7 +219,7 @@ static __inline__ void clear_dma_ff(unsigned int dmanr) }/* set mode (above) for a specific DMA channel */ -static __inline__void set_dma_mode (unsigned int dmanr,char mode) +static inline void set_dma_mode (unsigned int dmanr,char mode) {if (dmanr <=3 )dma_outb (mode | dmanr,DMA1_MODE_REG );
@@ -232,7 +232,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)* the lower 16 bits of the DMA current address register, but a 64k boundary * may have been crossed. */ -static __inline__void set_dma_page (unsigned int dmanr,int pagenr) +static inline void set_dma_page (unsigned int dmanr,int pagenr) {switch (dmanr) {case 0 :
@@ -269,7 +269,7 @@ static __inline__ void set_dma_page(unsigned int dmanr, int pagenr)/* Set transfer address & page bits for specific DMA channel. * Assumes dma flipflop is clear. */ -static __inline__void set_dma_addr (unsigned int dmanr,unsigned int phys) +static inline void set_dma_addr (unsigned int dmanr,unsigned int phys) {if (dmanr <=3 ) { dma_outb(phys & 0xff,
@@ -294,7 +294,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys)* Assumes dma flip-flop is clear. * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. */ -static __inline__void set_dma_count (unsigned int dmanr,unsigned int count) +static inline void set_dma_count (unsigned int dmanr,unsigned int count) { count--;if (dmanr <=3 ) {
@@ -319,7 +319,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)* * Assumes DMA flip-flop is clear. */ -static __inline__int get_dma_residue (unsigned int dmanr) +static inline int get_dma_residue (unsigned int dmanr) {unsigned int io_port = (dmanr <=3 ) ? ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE
arch/powerpc/include/asm/edac.h +1 -1
@@ -16,7 +16,7 @@* ECC scrubbing. It reads memory and then writes back the original * value, allowing the hardware to detect and correct memory errors. */ -static __inline__void edac_atomic_scrub (void *va,u32 size) +static inline void edac_atomic_scrub (void *va,u32 size) {unsigned int *virt_addr = va;unsigned int temp;
arch/powerpc/include/asm/irq.h +1 -1
@@ -31,7 +31,7 @@ extern atomic_t ppc_n_lost_interrupts;extern irq_hw_number_t virq_to_hw (unsigned int virq); -static __inline__int irq_canonicalize (int irq) +static inline int irq_canonicalize (int irq) {return irq; }
arch/powerpc/include/asm/local.h +7 -7
@@ -17,18 +17,18 @@ typedef struct#define LOCAL_INIT (i) { (i) } -static __inline__long local_read (local_t *l) +static inline long local_read (local_t *l) {return READ_ONCE (l->v); } -static __inline__void local_set (local_t *l,long i) +static inline void local_set (local_t *l,long i) {WRITE_ONCE (l->v, i); }#define LOCAL_OP (op, c_op) \ -static __inline__ void local_##op(long i, local_t *l) \ +static inline void local_##op(long i, local_t *l) \ { \ unsigned long flags; \ \
@@ -38,7 +38,7 @@ static __inline__ void local_##op(long i, local_t *l) \ }#define LOCAL_OP_RETURN (op, c_op) \ -static __inline__ long local_##op##_return(long a, local_t *l) \ +static inline long local_##op##_return(long a, local_t *l) \ { \ long t; \ unsigned long flags; \
@@ -76,7 +76,7 @@ LOCAL_OPS(sub, -=)#define local_sub_and_test (a, l) (local_sub_return((a), (l)) == 0)#define local_dec_and_test (l) (local_dec_return((l)) == 0) -static __inline__long local_cmpxchg (local_t *l,long o,long n) +static inline long local_cmpxchg (local_t *l,long o,long n) {long t;unsigned long flags;
@@ -90,7 +90,7 @@ static __inline__ long local_cmpxchg(local_t *l, long o, long n)return t; } -static __inline__long local_xchg (local_t *l,long n) +static inline long local_xchg (local_t *l,long n) {long t;unsigned long flags;
@@ -112,7 +112,7 @@ static __inline__ long local_xchg(local_t *l, long n)* Atomically adds @a to @l, so long as it was not @u. * Returns non-zero if @l was not @u, and zero otherwise. */ -static __inline__int local_add_unless (local_t *l,long a,long u) +static inline int local_add_unless (local_t *l,long a,long u) {unsigned long flags;int ret =0 ;
arch/sh/include/asm/pgtable_64.h +1 -1
@@ -32,7 +32,7 @@*/ #define set_pmd (pmdptr, pmdval) (*(pmdptr) = pmdval) -static __inline__void set_pte (pte_t *pteptr,pte_t pteval) +static inline void set_pte (pte_t *pteptr,pte_t pteval) {unsigned long long x = ((unsigned long long ) pteval.pte_low);unsigned long long *xp = (unsigned long long *) pteptr;
arch/sh/include/asm/processor_32.h +2 -2
@@ -141,7 +141,7 @@ extern void release_thread(struct task_struct *);* FPU lazy state save handling. */ -static __inline__void disable_fpu (void ) +static inline void disable_fpu (void ) {unsigned long __dummy;
@@ -153,7 +153,7 @@ static __inline__ void disable_fpu(void) : "r" (SR_FD)); } -static __inline__void enable_fpu (void ) +static inline void enable_fpu (void ) {unsigned long __dummy;
arch/sh/include/cpu-sh3/cpu/dac.h +3 -3
@@ -15,7 +15,7 @@#define DACR_DAE 0x20 -static __inline__void sh_dac_enable (int channel) +static inline void sh_dac_enable (int channel) {unsigned char v; v =__raw_readb (DACR );
@@ -24,7 +24,7 @@ static __inline__ void sh_dac_enable(int channel)__raw_writeb (v,DACR ); } -static __inline__void sh_dac_disable (int channel) +static inline void sh_dac_disable (int channel) {unsigned char v; v =__raw_readb (DACR );
@@ -33,7 +33,7 @@ static __inline__ void sh_dac_disable(int channel)__raw_writeb (v,DACR ); } -static __inline__void sh_dac_output (u8 value,int channel) +static inline void sh_dac_output (u8 value,int channel) {if (channel)__raw_writeb (value,DADR1 );else __raw_writeb (value,DADR0 );
arch/x86/include/asm/alternative.h +7 -7
@@ -159,10 +159,10 @@ static inline int alternatives_text_reserved(void *start, void *end)* without volatile and memory clobber. */ #define alternative (oldinstr, newinstr, feature) \ - asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory") + asm_volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")#define alternative_2 (oldinstr, newinstr1, feature1, newinstr2, feature2) \ - asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory") + asm_volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")/* * Alternative inline assembly with input.
@@ -176,7 +176,7 @@ static inline int alternatives_text_reserved(void *start, void *end)* Leaving an unused argument 0 to keep API compatibility. */ #define alternative_input(oldinstr, newinstr, feature, input...) \ - asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \ + asm_volatile (ALTERNATIVE(oldinstr, newinstr, feature) \ : : "i" (0), ## input)/*
@@ -189,18 +189,18 @@ static inline int alternatives_text_reserved(void *start, void *end)*/ #define alternative_input_2 (oldinstr, newinstr1, feature1, newinstr2, \ feature2, input...) \ - asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, \ + asm_volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, \ newinstr2, feature2) \ : : "i" (0), ## input)/* Like alternative_input, but with a single output argument */ #define alternative_io(oldinstr, newinstr, feature, output, input...) \ - asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \ + asm_volatile (ALTERNATIVE(oldinstr, newinstr, feature) \ : output : "i" (0), ## input)/* Like alternative_io, but for replacing a direct call with another one. */ #define alternative_call(oldfunc, newfunc, feature, output, input...) \ - asm volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \ + asm_volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \ : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)/*
@@ -211,7 +211,7 @@ static inline int alternatives_text_reserved(void *start, void *end)*/ #define alternative_call_2 (oldfunc, newfunc1, feature1, newfunc2, feature2, \ output, input...) \ - asm volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\ + asm_volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\ "call %P[new2]", feature2) \ : output, ASM_CALL_CONSTRAINT \ : [old] "i" (oldfunc), [new1] "i" (newfunc1), \
arch/x86/um/asm/checksum.h +2 -2
@@ -28,7 +28,7 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);* access_ok(). */ -static __inline__ +static inline __wsum csum_partial_copy_nocheck (const void *src,void *dst,int len,__wsum sum) {
@@ -44,7 +44,7 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst,* better 64-bit) boundary */ -static __inline__ +static inline __wsum csum_partial_copy_from_user (const void __user *src,void *dst,int len,__wsum sum,int *err_ptr) {
arch/x86/um/asm/checksum_32.h +2 -2
@@ -11,7 +11,7 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) }#define _HAVE_ARCH_IPV6_CSUM -static __inline____sum16 csum_ipv6_magic (const struct in6_addr *saddr, +static inline __sum16 csum_ipv6_magic (const struct in6_addr *saddr,const struct in6_addr *daddr,__u32 len,__u8 proto,__wsum sum)
@@ -39,7 +39,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,* Copy and checksum to user */ #define HAVE_CSUM_COPY_USER -static __inline____wsum csum_and_copy_to_user (const void *src, +static inline __wsum csum_and_copy_to_user (const void *src,void __user *dst,int len,__wsum sum,int *err_ptr) {
arch/xtensa/include/asm/checksum.h +7 -7
@@ -66,7 +66,7 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst,* Fold a partial checksum */ -static __inline____sum16 csum_fold (__wsum sum) +static inline __sum16 csum_fold (__wsum sum) {unsigned int __dummy; __asm__("extui %1, %0, 16, 16\n\t"
@@ -87,7 +87,7 @@ static __inline__ __sum16 csum_fold(__wsum sum)* This is a version of ip_compute_csum() optimized for IP headers, * which always checksum on 4 octet boundaries. */ -static __inline____sum16 ip_fast_csum (const void *iph,unsigned int ihl) +static inline __sum16 ip_fast_csum (const void *iph,unsigned int ihl) {unsigned int sum, tmp, endaddr;
@@ -122,7 +122,7 @@ static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)return csum_fold (sum); } -static __inline____wsum csum_tcpudp_nofold (__be32 saddr,__be32 daddr, +static inline __wsum csum_tcpudp_nofold (__be32 saddr,__be32 daddr,__u32 len,__u8 proto,__wsum sum) {
@@ -155,7 +155,7 @@ static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,* computes the checksum of the TCP/UDP pseudo-header * returns a 16-bit checksum, already complemented */ -static __inline____sum16 csum_tcpudp_magic (__be32 saddr,__be32 daddr, +static inline __sum16 csum_tcpudp_magic (__be32 saddr,__be32 daddr,__u32 len,__u8 proto,__wsum sum) {
@@ -167,13 +167,13 @@ static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,* in icmp.c */ -static __inline____sum16 ip_compute_csum (const void *buff,int len) +static inline __sum16 ip_compute_csum (const void *buff,int len) {return csum_fold (csum_partial (buff, len,0 )); }#define _HAVE_ARCH_IPV6_CSUM -static __inline____sum16 csum_ipv6_magic (const struct in6_addr *saddr, +static inline __sum16 csum_ipv6_magic (const struct in6_addr *saddr,const struct in6_addr *daddr,__u32 len,__u8 proto,__wsum sum)
@@ -239,7 +239,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,* Copy and checksum to user */ #define HAVE_CSUM_COPY_USER -static __inline____wsum csum_and_copy_to_user (const void *src, +static inline __wsum csum_and_copy_to_user (const void *src,void __user *dst,int len,__wsum sum,int *err_ptr) {
arch/xtensa/include/asm/cmpxchg.h +2 -2
@@ -52,7 +52,7 @@ __cmpxchg_u32(volatile int *p, int old, int new)extern void __cmpxchg_called_with_bad_pointer (void ); -static __inline__unsigned long +static inline unsigned long __cmpxchg (volatile void *ptr,unsigned long old,unsigned long new,int size) {switch (size) {
@@ -146,7 +146,7 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val)extern void __xchg_called_with_bad_pointer (void ); -static __inline__unsigned long +static inline unsigned long __xchg (unsigned long x,volatile void * ptr,int size) {switch (size) {
arch/xtensa/include/asm/irq.h +1 -1
@@ -23,7 +23,7 @@#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS + 1)#define XTENSA_PIC_LINUX_IRQ (hwirq) ((hwirq) + 1) -static __inline__int irq_canonicalize (int irq) +static inline int irq_canonicalize (int irq) {return (irq); }
block/partitions/amiga.c +1 -1
@@ -16,7 +16,7 @@#include "check.h" #include "amiga.h" -static __inline__u32 +static inline u32 checksum_block (__be32 *m,int size) {u32 sum =0 ;
drivers/atm/he.c +3 -3
@@ -178,7 +178,7 @@ static const struct atmdev_ops he_ops =/* section 2.12 connection memory access */ -static __inline__void +static inline void he_writel_internal (struct he_dev *he_dev,unsigned val,unsigned addr,unsigned flags) {
@@ -324,7 +324,7 @@ he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)#define he_writel_rsr7 (dev, val, cid) \ he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 7) -static __inline__struct atm_vcc * +static inline struct atm_vcc *__find_vcc (struct he_dev *he_dev,unsigned cid) {struct hlist_head *head;
@@ -2050,7 +2050,7 @@ he_irq_handler(int irq, void *dev_id) } -static __inline__void +static inline void __enqueue_tpd (struct he_dev *he_dev,struct he_tpd *tpd,unsigned cid) {struct he_tpdrq *new_tail;
drivers/atm/idt77252.c +3 -3
@@ -1783,13 +1783,13 @@ set_tct(struct idt77252_dev *card, struct vc_map *vc)/* */ /*****************************************************************************/ -static __inline__int +static inline int idt77252_fbq_level (struct idt77252_dev *card,int queue) {return (readl (SAR_REG_STAT ) >> (16 + (queue <<2 ))) &0x0f ; } -static __inline__int +static inline int idt77252_fbq_full (struct idt77252_dev *card,int queue) {return (readl (SAR_REG_STAT ) >> (16 + (queue <<2 ))) ==0x0f ;
@@ -2016,7 +2016,7 @@ idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)return idt77252_send_skb (vcc, skb,1 ); } -static __inline__unsigned int +static inline unsigned int idt77252_fls (unsigned int x) {int r =1 ;
drivers/gpu/drm/mga/mga_drv.h +1 -1
@@ -661,7 +661,7 @@ do { \/* Simple idle test. */ -static __inline__int mga_is_idle (drm_mga_private_t *dev_priv) +static inline int mga_is_idle (drm_mga_private_t *dev_priv) {u32 status =MGA_READ (MGA_STATUS ) &MGA_ENGINE_IDLE_MASK ;return (status ==MGA_ENDPRDMASTS );
drivers/gpu/drm/mga/mga_state.c +7 -7
@@ -65,7 +65,7 @@ static void mga_emit_clip_rect(drm_mga_private_t *dev_priv,ADVANCE_DMA (); } -static __inline__void mga_g200_emit_context (drm_mga_private_t *dev_priv) +static inline void mga_g200_emit_context (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -88,7 +88,7 @@ static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv)ADVANCE_DMA (); } -static __inline__void mga_g400_emit_context (drm_mga_private_t *dev_priv) +static inline void mga_g400_emit_context (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -115,7 +115,7 @@ static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv)ADVANCE_DMA (); } -static __inline__void mga_g200_emit_tex0 (drm_mga_private_t *dev_priv) +static inline void mga_g200_emit_tex0 (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0 ];
@@ -143,7 +143,7 @@ static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv)ADVANCE_DMA (); } -static __inline__void mga_g400_emit_tex0 (drm_mga_private_t *dev_priv) +static inline void mga_g400_emit_tex0 (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0 ];
@@ -183,7 +183,7 @@ static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv)ADVANCE_DMA (); } -static __inline__void mga_g400_emit_tex1 (drm_mga_private_t *dev_priv) +static inline void mga_g400_emit_tex1 (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1 ];
@@ -222,7 +222,7 @@ static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv)ADVANCE_DMA (); } -static __inline__void mga_g200_emit_pipe (drm_mga_private_t *dev_priv) +static inline void mga_g200_emit_pipe (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;unsigned int pipe = sarea_priv->warp_pipe;
@@ -249,7 +249,7 @@ static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv)ADVANCE_DMA (); } -static __inline__void mga_g400_emit_pipe (drm_mga_private_t *dev_priv) +static inline void mga_g400_emit_pipe (drm_mga_private_t *dev_priv) {drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;unsigned int pipe = sarea_priv->warp_pipe;
drivers/gpu/drm/r128/r128_drv.h +1 -1
@@ -417,7 +417,7 @@ do { \#define CCE_PACKET3 (pkt, n) (R128_CCE_PACKET3 | \ (pkt) | ((n) << 16)) -static __inline__void r128_update_ring_snapshot (drm_r128_private_t *dev_priv) +static inline void r128_update_ring_snapshot (drm_r128_private_t *dev_priv) {drm_r128_ring_buffer_t *ring = &dev_priv->ring; ring->space = (GET_RING_HEAD (dev_priv) - ring->tail) *sizeof (u32);
drivers/gpu/drm/r128/r128_state.c +7 -7
@@ -79,7 +79,7 @@ static void r128_emit_clip_rects(drm_r128_private_t *dev_priv,ADVANCE_RING (); } -static __inline__void r128_emit_core (drm_r128_private_t *dev_priv) +static inline void r128_emit_core (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -94,7 +94,7 @@ static __inline__ void r128_emit_core(drm_r128_private_t *dev_priv)ADVANCE_RING (); } -static __inline__void r128_emit_context (drm_r128_private_t *dev_priv) +static inline void r128_emit_context (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -120,7 +120,7 @@ static __inline__ void r128_emit_context(drm_r128_private_t *dev_priv)ADVANCE_RING (); } -static __inline__void r128_emit_setup (drm_r128_private_t *dev_priv) +static inline void r128_emit_setup (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -136,7 +136,7 @@ static __inline__ void r128_emit_setup(drm_r128_private_t *dev_priv)ADVANCE_RING (); } -static __inline__void r128_emit_masks (drm_r128_private_t *dev_priv) +static inline void r128_emit_masks (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -155,7 +155,7 @@ static __inline__ void r128_emit_masks(drm_r128_private_t *dev_priv)ADVANCE_RING (); } -static __inline__void r128_emit_window (drm_r128_private_t *dev_priv) +static inline void r128_emit_window (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -170,7 +170,7 @@ static __inline__ void r128_emit_window(drm_r128_private_t *dev_priv)ADVANCE_RING (); } -static __inline__void r128_emit_tex0 (drm_r128_private_t *dev_priv) +static inline void r128_emit_tex0 (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -196,7 +196,7 @@ static __inline__ void r128_emit_tex0(drm_r128_private_t *dev_priv)ADVANCE_RING (); } -static __inline__void r128_emit_tex1 (drm_r128_private_t *dev_priv) +static inline void r128_emit_tex1 (drm_r128_private_t *dev_priv) {drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1 ];
drivers/gpu/drm/via/via_irq.c +1 -1
@@ -152,7 +152,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg)return IRQ_NONE ; } -static __inline__void viadrv_acknowledge_irqs (drm_via_private_t *dev_priv) +static inline void viadrv_acknowledge_irqs (drm_via_private_t *dev_priv) {u32 status;
drivers/gpu/drm/via/via_verifier.c +15 -15
@@ -235,7 +235,7 @@ static hazard_t table1[256];static hazard_t table2[256 ];static hazard_t table3[256 ]; -static __inline__int +static inline int eat_words (const uint32_t **buf,const uint32_t *buf_end,unsigned num_words) {if ((buf_end - *buf) >= num_words) {
@@ -250,7 +250,7 @@ eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)* Partially stolen from drm_memory.h */ -static __inline__drm_local_map_t *via_drm_lookup_agp_map (drm_via_state_t *seq, +static inline drm_local_map_t *via_drm_lookup_agp_map (drm_via_state_t *seq,unsigned long offset,unsigned long size,struct drm_device *dev)
@@ -287,7 +287,7 @@ static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,* very little CPU time. */ -static __inline__int finish_current_sequence (drm_via_state_t * cur_seq) +static inline int finish_current_sequence (drm_via_state_t * cur_seq) {switch (cur_seq->unfinished) {case z_address:
@@ -344,7 +344,7 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)return 0 ; } -static __inline__int +static inline int investigate_hazard (uint32_t cmd,hazard_t hz,drm_via_state_t *cur_seq) { registeruint32_t tmp, *tmp_addr;
@@ -517,7 +517,7 @@ investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)return 2 ; } -static __inline__int +static inline int via_check_prim_list (uint32_t const **buffer,const uint32_t * buf_end,drm_via_state_t *cur_seq) {
@@ -621,7 +621,7 @@ via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,return ret; } -static __inline__verifier_state_t +static inline verifier_state_t via_check_header2 (uint32_t const **buffer,const uint32_t *buf_end,drm_via_state_t *hc_state) {
@@ -713,7 +713,7 @@ via_check_header2(uint32_t const **buffer, const uint32_t *buf_end,return state_command; } -static __inline__verifier_state_t +static inline verifier_state_t via_parse_header2 (drm_via_private_t *dev_priv,uint32_t const **buffer,const uint32_t *buf_end,int *fire_count) {
@@ -762,7 +762,7 @@ via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,return state_command; } -static __inline__int verify_mmio_address (uint32_t address) +static inline int verify_mmio_address (uint32_t address) {if ((address >0x3FF ) && (address <0xC00 )) { DRM_ERROR("Invalid VIDEO DMA command. "
@@ -780,7 +780,7 @@ static __inline__ int verify_mmio_address(uint32_t address)return 0 ; } -static __inline__int +static inline int verify_video_tail (uint32_t const **buffer,const uint32_t * buf_end,uint32_t dwords) {
@@ -800,7 +800,7 @@ verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,return 0 ; } -static __inline__verifier_state_t +static inline verifier_state_t via_check_header1 (uint32_t const **buffer,const uint32_t * buf_end) {uint32_t cmd;
@@ -832,7 +832,7 @@ via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)return ret; } -static __inline__verifier_state_t +static inline verifier_state_t via_parse_header1 (drm_via_private_t *dev_priv,uint32_t const **buffer,const uint32_t *buf_end) {
@@ -850,7 +850,7 @@ via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer,return state_command; } -static __inline__verifier_state_t +static inline verifier_state_t via_check_vheader5 (uint32_t const **buffer,const uint32_t *buf_end) {uint32_t data;
@@ -883,7 +883,7 @@ via_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end) } -static __inline__verifier_state_t +static inline verifier_state_t via_parse_vheader5 (drm_via_private_t *dev_priv,uint32_t const **buffer,const uint32_t *buf_end) {
@@ -901,7 +901,7 @@ via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer,return state_command; } -static __inline__verifier_state_t +static inline verifier_state_t via_check_vheader6 (uint32_t const **buffer,const uint32_t * buf_end) {uint32_t data;
@@ -938,7 +938,7 @@ via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)return state_command; } -static __inline__verifier_state_t +static inline verifier_state_t via_parse_vheader6 (drm_via_private_t *dev_priv,uint32_t const **buffer,const uint32_t *buf_end) {
drivers/isdn/hardware/eicon/platform.h +7 -7
@@ -159,7 +159,7 @@ void diva_xdi_didd_remove_adapter(int card);/* ** memory allocation */ -static __inline__void *diva_os_malloc (unsigned long flags,unsigned long size) +static inline void *diva_os_malloc (unsigned long flags,unsigned long size) {void *ret =NULL ;
@@ -168,7 +168,7 @@ static __inline__ void *diva_os_malloc(unsigned long flags, unsigned long size) }return (ret); } -static __inline__void diva_os_free (unsigned long flags,void *ptr) +static inline void diva_os_free (unsigned long flags,void *ptr) {vfree (ptr); }
@@ -185,11 +185,11 @@ void diva_os_free_message_buffer(diva_os_message_buffer_s *dmb);/* ** mSeconds waiting */ -static __inline__void diva_os_sleep (dword mSec) +static inline void diva_os_sleep (dword mSec) {msleep (mSec); } -static __inline__void diva_os_wait (dword mSec) +static inline void diva_os_wait (dword mSec) {mdelay (mSec); }
@@ -233,12 +233,12 @@ void diva_os_remove_irq(void *context, byte irq);*/ typedef long diva_os_spin_lock_magic_t ;typedef spinlock_t diva_os_spin_lock_t ; -static __inline__int diva_os_initialize_spin_lock (spinlock_t *lock,void *unused) { \ +static inline int diva_os_initialize_spin_lock (spinlock_t *lock,void *unused) { \spin_lock_init (lock);return (0 ); } -static __inline__void diva_os_enter_spin_lock (diva_os_spin_lock_t *a, \ +static inline void diva_os_enter_spin_lock (diva_os_spin_lock_t *a, \diva_os_spin_lock_magic_t *old_irql, \void *dbg) {spin_lock_bh (a); } -static __inline__void diva_os_leave_spin_lock (diva_os_spin_lock_t *a, \ +static inline void diva_os_leave_spin_lock (diva_os_spin_lock_t *a, \diva_os_spin_lock_magic_t *old_irql, \void *dbg) {spin_unlock_bh (a); }
drivers/isdn/i4l/isdn_net.c +7 -7
@@ -70,7 +70,7 @@* Find out if the netdevice has been ifup-ed yet. * For slaves, look at the corresponding master. */ -static __inline__int isdn_net_device_started (isdn_net_dev *n) +static inline int isdn_net_device_started (isdn_net_dev *n) {isdn_net_local *lp = n->local;struct net_device *dev;
@@ -86,7 +86,7 @@ static __inline__ int isdn_net_device_started(isdn_net_dev *n)* wake up the network -> net_device queue. * For slaves, wake the corresponding master interface. */ -static __inline__void isdn_net_device_wake_queue (isdn_net_local *lp) +static inline void isdn_net_device_wake_queue (isdn_net_local *lp) {if (lp->master)netif_wake_queue (lp->master);
@@ -98,7 +98,7 @@ static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)* stop the network -> net_device queue. * For slaves, stop the corresponding master interface. */ -static __inline__void isdn_net_device_stop_queue (isdn_net_local *lp) +static inline void isdn_net_device_stop_queue (isdn_net_local *lp) {if (lp->master)netif_stop_queue (lp->master);
@@ -111,7 +111,7 @@ static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)* master or slave) is busy. It's busy iff all (master and slave) * queues are busy */ -static __inline__int isdn_net_device_busy (isdn_net_local *lp) +static inline int isdn_net_device_busy (isdn_net_local *lp) {isdn_net_local *nlp;isdn_net_dev *nd;
@@ -138,14 +138,14 @@ static __inline__ int isdn_net_device_busy(isdn_net_local *lp)return 1 ; } -static __inline__void isdn_net_inc_frame_cnt (isdn_net_local *lp) +static inline void isdn_net_inc_frame_cnt (isdn_net_local *lp) {atomic_inc (&lp->frame_cnt);if (isdn_net_device_busy (lp))isdn_net_device_stop_queue (lp); } -static __inline__void isdn_net_dec_frame_cnt (isdn_net_local *lp) +static inline void isdn_net_dec_frame_cnt (isdn_net_local *lp) {atomic_dec (&lp->frame_cnt);
@@ -158,7 +158,7 @@ static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp) } } -static __inline__void isdn_net_zero_frame_cnt (isdn_net_local *lp) +static inline void isdn_net_zero_frame_cnt (isdn_net_local *lp) {atomic_set (&lp->frame_cnt,0 ); }
drivers/isdn/i4l/isdn_net.h +4 -4
@@ -64,7 +64,7 @@ extern void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb);/* * is this particular channel busy? */ -static __inline__int isdn_net_lp_busy (isdn_net_local *lp) +static inline int isdn_net_lp_busy (isdn_net_local *lp) {if (atomic_read (&lp->frame_cnt) <ISDN_NET_MAX_QUEUE_LENGTH )return 0 ;
@@ -76,7 +76,7 @@ static __inline__ int isdn_net_lp_busy(isdn_net_local *lp)* For the given net device, this will get a non-busy channel out of the * corresponding bundle. The returned channel is locked. */ -static __inline__isdn_net_local *isdn_net_get_locked_lp (isdn_net_dev *nd) +static inline isdn_net_local *isdn_net_get_locked_lp (isdn_net_dev *nd) {unsigned long flags;isdn_net_local *lp;
@@ -104,7 +104,7 @@ static __inline__ isdn_net_local *isdn_net_get_locked_lp(isdn_net_dev *nd)/* * add a channel to a bundle */ -static __inline__void isdn_net_add_to_bundle (isdn_net_dev *nd,isdn_net_local *nlp) +static inline void isdn_net_add_to_bundle (isdn_net_dev *nd,isdn_net_local *nlp) {isdn_net_local *lp;unsigned long flags;
@@ -125,7 +125,7 @@ static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local */* * remove a channel from the bundle it belongs to */ -static __inline__void isdn_net_rm_from_bundle (isdn_net_local *lp) +static inline void isdn_net_rm_from_bundle (isdn_net_local *lp) {isdn_net_local *master_lp = lp;unsigned long flags;
drivers/media/pci/ivtv/ivtv-ioctl.c +1 -1
@@ -1622,7 +1622,7 @@ static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder }#ifdef CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS -static __inline__void warn_deprecated_ioctl (const char *name) +static inline void warn_deprecated_ioctl (const char *name) {pr_warn_once ("warning: the %s ioctl is deprecated. Don't use it, as it will be removed soon\n" , name);
drivers/net/ethernet/sun/sungem.c +4 -4
@@ -640,7 +640,7 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_statreturn 0 ; } -static __inline__void gem_tx (struct net_device *dev,struct gem *gp,u32 gem_status) +static inline void gem_tx (struct net_device *dev,struct gem *gp,u32 gem_status) {int entry, limit;
@@ -710,7 +710,7 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st } } -static __inline__void gem_post_rxds (struct gem *gp,int limit) +static inline void gem_post_rxds (struct gem *gp,int limit) {int cluster_start, curr, count, kick;
@@ -742,7 +742,7 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit)#define ALIGNED_RX_SKB_ADDR (addr) \ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr)) -static __inline__struct sk_buff *gem_alloc_skb (struct net_device *dev,int size, +static inline struct sk_buff *gem_alloc_skb (struct net_device *dev,int size,gfp_t gfp_flags) {struct sk_buff *skb =alloc_skb (size +64 , gfp_flags);
@@ -988,7 +988,7 @@ static void gem_tx_timeout(struct net_device *dev)gem_schedule_reset (gp); } -static __inline__int gem_intme (int entry) +static inline int gem_intme (int entry) {/* Algorithm: IRQ every 1/2 of descriptors. */ if (!(entry & ((TX_RING_SIZE >>1 )-1 )))
drivers/net/ethernet/sun/sunhme.c +3 -3
@@ -108,7 +108,7 @@ struct hme_tx_logent {#define TX_LOG_LEN 128static struct hme_tx_logent tx_log[TX_LOG_LEN ];static int txlog_cur_entry; -static __inline__void tx_add_log (struct happy_meal *hp,unsigned int a,unsigned int s) +static inline void tx_add_log (struct happy_meal *hp,unsigned int a,unsigned int s) {struct hme_tx_logent *tlp;unsigned long flags;
@@ -123,7 +123,7 @@ static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigne txlog_cur_entry = (txlog_cur_entry +1 ) & (TX_LOG_LEN -1 );local_irq_restore (flags); } -static __inline__void tx_dump_log (void ) +static inline void tx_dump_log (void ) {int i, this;
@@ -136,7 +136,7 @@ static __inline__ void tx_dump_log(void) this = (this +1 ) & (TX_LOG_LEN -1 ); } } -static __inline__void tx_dump_ring (struct happy_meal *hp) +static inline void tx_dump_ring (struct happy_meal *hp) {struct hmeal_init_block *hb = hp->happy_block;struct happy_meal_txd *tp = &hb->happy_meal_txd[0 ];
drivers/net/hamradio/baycom_ser_fdx.c +1 -1
@@ -229,7 +229,7 @@ static inline unsigned int hweight8(unsigned int w)/* --------------------------------------------------------------------- */ -static __inline__void ser12_rx (struct net_device *dev,struct baycom_state *bc,struct timespec64 *ts,unsigned char curs) +static inline void ser12_rx (struct net_device *dev,struct baycom_state *bc,struct timespec64 *ts,unsigned char curs) {int timediff;int bdus8 = bc->baud_us >>3 ;
drivers/net/wan/lapbether.c +1 -1
@@ -76,7 +76,7 @@ static struct lapbethdev *lapbeth_get_x25_dev(struct net_device *dev)return NULL ; } -static __inline__int dev_is_ethdev (struct net_device *dev) +static inline int dev_is_ethdev (struct net_device *dev) {return dev->type ==ARPHRD_ETHER &&strncmp (dev->name,"dummy" ,5 ); }
drivers/net/wan/n2.c +2 -2
@@ -148,13 +148,13 @@ static card_t **new_card = &first_card; &(card)->ports[port] : NULL) -static __inline__u8 sca_get_page (card_t *card) +static inline u8 sca_get_page (card_t *card) {return inb (card->io +N2_PSR ) &PSR_PAGEBITS ; } -static __inline__void openwin (card_t *card,u8 page) +static inline void openwin (card_t *card,u8 page) {u8 psr =inb (card->io +N2_PSR );outb ((psr & ~PSR_PAGEBITS ) | page, card->io +N2_PSR );
drivers/parisc/led.c +2 -2
@@ -349,7 +349,7 @@ static void led_LCD_driver(unsigned char leds)** (analog to dev_get_info() from net/core/dev.c) ** */ -static __inline__int led_get_net_activity (void ) +static inline int led_get_net_activity (void ) {#ifndef CONFIG_NET return 0 ;
@@ -401,7 +401,7 @@ static __inline__ int led_get_net_activity(void)** calculate if there was disk-io in the system ** */ -static __inline__int led_get_diskio_activity (void ) +static inline int led_get_diskio_activity (void ) {static unsigned long last_pgpgin, last_pgpgout;unsigned long events[NR_VM_EVENT_ITEMS ];
drivers/parisc/sba_iommu.c +1 -1
@@ -89,7 +89,7 @@ #define DBG_RES(x...)#endif -#define SBA_INLINE __inline__ +#define SBA_INLINE inline#define DEFAULT_DMA_HINT_REG 0
drivers/parport/parport_gsc.c +1 -1
@@ -76,7 +76,7 @@ static int clear_epp_timeout(struct parport *pb)* Access functions. * * Most of these aren't static because they may be used by the -* parport_xxx_yyy macros. extern __inline__ versions of several +* parport_xxx_yyy macros. extern inline versions of several * of these are in parport_gsc.h. */
drivers/parport/parport_gsc.h +2 -2
@@ -41,13 +41,13 @@#define parport_readb gsc_readb#define parport_writeb gsc_writeb#else -static __inline__unsigned char parport_readb (unsigned long port ) +static inline unsigned char parport_readb (unsigned long port ) {udelay (DELAY_TIME );return gsc_readb (port); } -static __inline__void parport_writeb (unsigned char value,unsigned long port ) +static inline void parport_writeb (unsigned char value,unsigned long port ) {gsc_writeb (value,port);udelay (DELAY_TIME );
drivers/parport/parport_pc.c +1 -1
@@ -225,7 +225,7 @@ static int clear_epp_timeout(struct parport *pb)* Access functions. * * Most of these aren't static because they may be used by the -* parport_xxx_yyy macros. extern __inline__ versions of several +* parport_xxx_yyy macros. extern inline versions of several * of these are in parport_pc.h. */
drivers/scsi/lpfc/lpfc_scsi.c +1 -1
@@ -4481,7 +4481,7 @@ lpfc_info(struct Scsi_Host *host)* This routine modifies fcp_poll_timer field of @phba by cfg_poll_tmo. * The default value of cfg_poll_tmo is 10 milliseconds. **/ -static __inline__void lpfc_poll_rearm_timer (struct lpfc_hba * phba) +static inline void lpfc_poll_rearm_timer (struct lpfc_hba * phba) {unsigned long poll_tmo_expires = (jiffies +msecs_to_jiffies (phba->cfg_poll_tmo));
drivers/scsi/pcmcia/sym53c500_cs.c +2 -2
@@ -241,7 +241,7 @@ SYM53C500_int_host_reset(int io_port)chip_init (io_port); } -static __inline__int +static inline int SYM53C500_pio_read (int fast_pio,int base,unsigned char *request,unsigned int reqlen) {int i;
@@ -296,7 +296,7 @@ SYM53C500_pio_read(int fast_pio, int base, unsigned char *request, unsigned intreturn 0 ; } -static __inline__int +static inline int SYM53C500_pio_write (int fast_pio,int base,unsigned char *request,unsigned int reqlen) {int i =0 ;
drivers/scsi/qla2xxx/qla_inline.h +1 -1
@@ -39,7 +39,7 @@ qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)* Returns: * register value. */ -static __inline__uint16_t +static inline uint16_t qla2x00_debounce_register (volatile uint16_t __iomem *addr) {volatile uint16_t first;
drivers/scsi/qla2xxx/qla_os.c +2 -2
@@ -344,7 +344,7 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;* Timer routines */ -__inline__void +inline void qla2x00_start_timer (scsi_qla_host_t *vha,unsigned long interval) {timer_setup (&vha->timer, qla2x00_timer,0 );
@@ -366,7 +366,7 @@ qla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval)mod_timer (&vha->timer, jiffies + interval *HZ ); } -static __inline__void +static inline void qla2x00_stop_timer (scsi_qla_host_t *vha) {del_timer_sync (&vha->timer);
drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +2 -2
@@ -831,12 +831,12 @@ static void pwr_rpwm_timeout_handler(struct timer_list *t)_set_workitem (&pwrpriv->rpwmtimeoutwi); } -static __inlinevoid register_task_alive (struct pwrctrl_priv *pwrctrl,u32 tag) +static inline void register_task_alive (struct pwrctrl_priv *pwrctrl,u32 tag) { pwrctrl->alives |= tag; } -static __inlinevoid unregister_task_alive (struct pwrctrl_priv *pwrctrl,u32 tag) +static inline void unregister_task_alive (struct pwrctrl_priv *pwrctrl,u32 tag) { pwrctrl->alives &= ~tag; }
drivers/staging/rtl8723bs/core/rtw_wlan_util.c +1 -1
@@ -456,7 +456,7 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsignemutex_unlock (&(adapter_to_dvobj (padapter)->setch_mutex)); } -__inlineu8 *get_my_bssid (struct wlan_bssid_ex *pnetwork) +inline u8 *get_my_bssid (struct wlan_bssid_ex *pnetwork) {return pnetwork->MacAddress; }
drivers/staging/rtl8723bs/include/drv_types.h +3 -3
@@ -485,7 +485,7 @@ struct dvobj_priv#define dvobj_to_pwrctl (dvobj) (&(dvobj->pwrctl_priv))#define pwrctl_to_dvobj (pwrctl) container_of(pwrctl, struct dvobj_priv, pwrctl_priv) -__inlinestatic struct device *dvobj_to_dev (struct dvobj_priv *dvobj) +inline static struct device *dvobj_to_dev (struct dvobj_priv *dvobj) {/* todo: get interface type from dvobj and the return the dev accordingly */ #ifdef RTW_DVOBJ_CHIP_HW_TYPE
@@ -643,14 +643,14 @@ struct adapter {/* define RTW_DISABLE_FUNC(padapter, func) (atomic_add(&adapter_to_dvobj(padapter)->disable_func, (func))) */ /* define RTW_ENABLE_FUNC(padapter, func) (atomic_sub(&adapter_to_dvobj(padapter)->disable_func, (func))) */ -__inlinestatic void RTW_DISABLE_FUNC (struct adapter *padapter,int func_bit) +inline static void RTW_DISABLE_FUNC (struct adapter *padapter,int func_bit) {int df =atomic_read (&adapter_to_dvobj (padapter)->disable_func); df |= func_bit;atomic_set (&adapter_to_dvobj (padapter)->disable_func, df); } -__inlinestatic void RTW_ENABLE_FUNC (struct adapter *padapter,int func_bit) +inline static void RTW_ENABLE_FUNC (struct adapter *padapter,int func_bit) {int df =atomic_read (&adapter_to_dvobj (padapter)->disable_func); df &= ~(func_bit);
drivers/staging/rtl8723bs/include/ieee80211.h +3 -3
@@ -850,18 +850,18 @@ enum ieee80211_state {#define IP_FMT "%pI4"#define IP_ARG (x) (x) -extern __inlineint is_multicast_mac_addr (const u8 *addr) +extern inline int is_multicast_mac_addr (const u8 *addr) {return ((addr[0 ] !=0xff ) && (0x01 & addr[0 ])); } -extern __inlineint is_broadcast_mac_addr (const u8 *addr) +extern inline int is_broadcast_mac_addr (const u8 *addr) {return ((addr[0 ] ==0xff ) && (addr[1 ] ==0xff ) && (addr[2 ] ==0xff ) && \ (addr[3 ] ==0xff ) && (addr[4 ] ==0xff ) && (addr[5 ] ==0xff )); } -extern __inlineint is_zero_mac_addr (const u8 *addr) +extern inline int is_zero_mac_addr (const u8 *addr) {return ((addr[0 ] ==0x00 ) && (addr[1 ] ==0x00 ) && (addr[2 ] ==0x00 ) && \ (addr[3 ] ==0x00 ) && (addr[4 ] ==0x00 ) && (addr[5 ] ==0x00 ));
drivers/staging/rtl8723bs/include/osdep_service.h +5 -5
@@ -110,12 +110,12 @@ int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb);extern void _rtw_init_queue (struct __queue *pqueue); -static __inlinevoid thread_enter (char *name) +static inline void thread_enter (char *name) {allow_signal (SIGTERM ); } -__inlinestatic void flush_signals_thread (void ) +inline static void flush_signals_thread (void ) {if (signal_pending (current)) {
@@ -125,7 +125,7 @@ __inline static void flush_signals_thread(void)#define rtw_warn_on (condition) WARN_ON(condition) -__inlinestatic int rtw_bug_check (void *parg1,void *parg2,void *parg3,void *parg4) +inline static int rtw_bug_check (void *parg1,void *parg2,void *parg3,void *parg4) {int ret = true;
@@ -136,7 +136,7 @@ __inline static int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *p#define _RND (sz, r) ((((sz)+((r)-1))/(r))*(r))#define RND4 (x) (((x >> 2) + (((x & 3) == 0) ? 0: 1)) << 2) -__inlinestatic u32 _RND4 (u32 sz) +inline static u32 _RND4 (u32 sz) {u32 val;
@@ -147,7 +147,7 @@ __inline static u32 _RND4(u32 sz) } -__inlinestatic u32 _RND8 (u32 sz) +inline static u32 _RND8 (u32 sz) {u32 val;
drivers/staging/rtl8723bs/include/osdep_service_linux.h +7 -7
@@ -66,12 +66,12 @@typedef struct work_struct _workitem ; -__inlinestatic struct list_head *get_next (struct list_head *list) +inline static struct list_head *get_next (struct list_head *list) {return list->next; } -__inlinestatic struct list_head *get_list_head (struct __queue *queue) +inline static struct list_head *get_list_head (struct __queue *queue) {return (&(queue->queue)); }
@@ -80,28 +80,28 @@ __inline static struct list_head *get_list_head(struct __queue *queue)#define LIST_CONTAINOR (ptr, type, member) \ container_of(ptr, type, member) -__inlinestatic void _set_timer (_timer *ptimer,u32 delay_time) +inline static void _set_timer (_timer *ptimer,u32 delay_time) {mod_timer (ptimer , (jiffies+(delay_time*HZ /1000 ))); } -__inlinestatic void _cancel_timer (_timer *ptimer,u8 *bcancelled) +inline static void _cancel_timer (_timer *ptimer,u8 *bcancelled) {del_timer_sync (ptimer); *bcancelled = true;/* true == 1; false == 0 */ } -__inlinestatic void _init_workitem (_workitem *pwork,void *pfunc,void *cntx) +inline static void _init_workitem (_workitem *pwork,void *pfunc,void *cntx) {INIT_WORK (pwork, pfunc); } -__inlinestatic void _set_workitem (_workitem *pwork) +inline static void _set_workitem (_workitem *pwork) {schedule_work (pwork); } -__inlinestatic void _cancel_workitem_sync (_workitem *pwork) +inline static void _cancel_workitem_sync (_workitem *pwork) {cancel_work_sync (pwork); }
drivers/staging/rtl8723bs/include/rtw_mlme.h +7 -7
@@ -525,13 +525,13 @@ extern sint rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv);extern sint rtw_set_key (struct adapter *adapter,struct security_priv *psecuritypriv,sint keyid,u8 set_tx,bool enqueue);extern sint rtw_set_auth (struct adapter *adapter,struct security_priv *psecuritypriv); -__inlinestatic u8 *get_bssid (struct mlme_priv *pmlmepriv) +inline static u8 *get_bssid (struct mlme_priv *pmlmepriv) {/* if sta_mode:pmlmepriv->cur_network.network.MacAddress => bssid */ /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress => ibss mac address */ return pmlmepriv->cur_network.network.MacAddress; } -__inlinestatic sint check_fwstate (struct mlme_priv *pmlmepriv,sint state) +inline static sint check_fwstate (struct mlme_priv *pmlmepriv,sint state) {if (pmlmepriv->fw_state & state)return true;
@@ -539,7 +539,7 @@ __inline static sint check_fwstate(struct mlme_priv *pmlmepriv, sint state)return false; } -__inlinestatic sint get_fwstate (struct mlme_priv *pmlmepriv) +inline static sint get_fwstate (struct mlme_priv *pmlmepriv) {return pmlmepriv->fw_state; }
@@ -551,7 +551,7 @@ __inline static sint get_fwstate(struct mlme_priv *pmlmepriv)* ### NOTE:#### (!!!!) * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock */ -__inlinestatic void set_fwstate (struct mlme_priv *pmlmepriv,sint state) +inline static void set_fwstate (struct mlme_priv *pmlmepriv,sint state) { pmlmepriv->fw_state |= state;/* FOR HW integration */
@@ -560,7 +560,7 @@ __inline static void set_fwstate(struct mlme_priv *pmlmepriv, sint state) } } -__inlinestatic void _clr_fwstate_ (struct mlme_priv *pmlmepriv,sint state) +inline static void _clr_fwstate_ (struct mlme_priv *pmlmepriv,sint state) { pmlmepriv->fw_state &= ~state;/* FOR HW integration */
@@ -573,7 +573,7 @@ __inline static void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state)* No Limit on the calling context, * therefore set it to be the critical section... */ -__inlinestatic void clr_fwstate (struct mlme_priv *pmlmepriv,sint state) +inline static void clr_fwstate (struct mlme_priv *pmlmepriv,sint state) {spin_lock_bh (&pmlmepriv->lock);if (check_fwstate (pmlmepriv, state) == true)
@@ -581,7 +581,7 @@ __inline static void clr_fwstate(struct mlme_priv *pmlmepriv, sint state)spin_unlock_bh (&pmlmepriv->lock); } -__inlinestatic void set_scanned_network_val (struct mlme_priv *pmlmepriv,sint val) +inline static void set_scanned_network_val (struct mlme_priv *pmlmepriv,sint val) {spin_lock_bh (&pmlmepriv->lock); pmlmepriv->num_of_scanned = val;
drivers/staging/rtl8723bs/include/rtw_recv.h +8 -8
@@ -405,7 +405,7 @@ struct recv_buf *rtw_dequeue_recvbuf (struct __queue *queue);void rtw_reordering_ctrl_timeout_handler (struct timer_list *t); -__inlinestatic u8 *get_rxmem (union recv_frame *precvframe) +inline static u8 *get_rxmem (union recv_frame *precvframe) {/* always return rx_head... */ if (precvframe ==NULL )
@@ -414,7 +414,7 @@ __inline static u8 *get_rxmem(union recv_frame *precvframe)return precvframe->u.hdr.rx_head; } -__inlinestatic u8 *get_recvframe_data (union recv_frame *precvframe) +inline static u8 *get_recvframe_data (union recv_frame *precvframe) {/* alwasy return rx_data */
@@ -425,7 +425,7 @@ __inline static u8 *get_recvframe_data(union recv_frame *precvframe) } -__inlinestatic u8 *recvframe_pull (union recv_frame *precvframe,sint sz) +inline static u8 *recvframe_pull (union recv_frame *precvframe,sint sz) {/* rx_data += sz; move rx_data sz bytes hereafter */
@@ -450,7 +450,7 @@ __inline static u8 *recvframe_pull(union recv_frame *precvframe, sint sz) } -__inlinestatic u8 *recvframe_put (union recv_frame *precvframe,sint sz) +inline static u8 *recvframe_put (union recv_frame *precvframe,sint sz) {/* rx_tai += sz; move rx_tail sz bytes hereafter */
@@ -479,7 +479,7 @@ __inline static u8 *recvframe_put(union recv_frame *precvframe, sint sz) -__inlinestatic u8 *recvframe_pull_tail (union recv_frame *precvframe,sint sz) +inline static u8 *recvframe_pull_tail (union recv_frame *precvframe,sint sz) {/* rmv data from rx_tail (by yitsen) */
@@ -503,7 +503,7 @@ __inline static u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) } -__inlinestatic union recv_frame *rxmem_to_recvframe (u8 *rxmem) +inline static union recv_frame *rxmem_to_recvframe (u8 *rxmem) {/* due to the design of 2048 bytes alignment of recv_frame, we can reference the union recv_frame */ /* from any given member of recv_frame. */
@@ -513,13 +513,13 @@ __inline static union recv_frame *rxmem_to_recvframe(u8 *rxmem) } -__inlinestatic sint get_recvframe_len (union recv_frame *precvframe) +inline static sint get_recvframe_len (union recv_frame *precvframe) {return precvframe->u.hdr.len; } -__inlinestatic s32 translate_percentage_to_dbm (u32 SignalStrengthIndex) +inline static s32 translate_percentage_to_dbm (u32 SignalStrengthIndex) {s32 SignalPower;/* in dBm. */
drivers/staging/rtl8723bs/include/sta_info.h +1 -1
@@ -348,7 +348,7 @@ struct sta_priv { }; -__inlinestatic u32 wifi_mac_hash (u8 *mac) +inline static u32 wifi_mac_hash (u8 *mac) {u32 x;
drivers/staging/rtl8723bs/include/wifi.h +7 -7
@@ -347,7 +347,7 @@ enum WIFI_REG_DOMAIN { (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \ )
Lines of this file are not shown. View the raw message.
drivers/staging/rtl8723bs/include/wlan_bssdef.h +1 -1
Lines of this file are not shown. View the raw message.
drivers/video/fbdev/intelfb/intelfbdrv.c +5 -5
Lines of this file are not shown. View the raw message.
drivers/video/fbdev/intelfb/intelfbhw.c +1 -1
Lines of this file are not shown. View the raw message.
include/uapi/linux/netfilter_arp/arp_tables.h +1 -1
Lines of this file are not shown. View the raw message.
include/uapi/linux/netfilter_bridge/ebtables.h +1 -1
Lines of this file are not shown. View the raw message.
include/uapi/linux/netfilter_ipv4/ip_tables.h +1 -1
Lines of this file are not shown. View the raw message.
include/uapi/linux/netfilter_ipv6/ip6_tables.h +1 -1
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Part of the diff is not shown here. View the raw message.
Peter Zijlstra
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 44 lines · Peter Zijlstra
Quoted 16 lines · Borislav Petkov
Ok,
with Segher's help I've been playing with his patch ontop of bleeding edge gcc 9 and here are my observations. Please double-check me for booboos so that they can be addressed while there's time.
So here's what I see ontop of 4.19-rc7:
First marked the alternative
asm()as inline and undeffed the "inline" keyword. I need to do that because of the funky games we do with "inline" redefinitions ininclude/linux/compiler_types.h.And Segher hinted at either doing:
asm volatile inline(...
Quoted 8 lines
or
asm volatile __inline__(...
but both "inline" variants are defined as macros in that file.
Which means we either need to #undef inline before using it in
asm()or come up with something cleverer.# git grep -e "\<__inline__\>" | wc -l 488 # git grep -e "\<__inline\>" | wc -l 56 # git grep -e "\<inline\>" | wc -l 69598And we already have
scripts/checkpatch.pl:# Check for
__inline__and__inline, prefer inlineWhich suggests we do:
git grep -l "\<__inline\(\|__\)\>" | while read file do
sed -i -e 's/\<__inline\(\|__\)\>/inline/g' $filedone
Quoted 8 lines
and get it over with.
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinux
17387603 5065468 1953892 24406963 1746bb3 defconfig-build/vmlinux
If I do an additional:
git grep -l "asm volatile" | while read file do
sed -i -e 's/asm volatile/asm_volatile/g' $file
done
on the tree...
No changes for:
-#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
+#define asm_volatile_goto(x...) do { asm __inline__ goto (x); asm (""); } while (0)
I suppose all our goto's are small now (my tree includes Nadav's patch to static_cpu_has).
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Peter ZijlstraQuoted 11 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).So yes, this seems like something we could work with.
Great to hear. Note that with my latest patches
(see https://gcc.gnu.org/ml/gcc-patches/2018-10/msg01931.html ) there is no required order "asm volatile inline" anymore, so you can just say "asm inline volatile". (And similar for "goto" as well).
Segher
Joe Perches
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).
[]
Quoted 3 lines
scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +--
I believe these should be excluded from the conversions.
Other than that, generic conversion by script seems a good idea.
Peter Zijlstra
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 8 lines · Joe Perches
Quoted 7 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinux
Quoted 8 lines
Quoted 2 lines
Which shows we inline more (look for
asm_volatilefor the actual changes).[]
Quoted 3 lines
scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +--I believe these should be excluded from the conversions.
Probably, yes. It compiled, which was all I cared about :-)
BTW, if we do that conversion, we should upgrade the checkpatch warn to an error I suppose.
Joe Perches
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 15 lines · Peter Zijlstra
Quoted 14 lines · Joe Perches
Quoted 8 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).[]
Quoted 3 lines
scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +--
Quoted 6 lines
Quoted 1 line
I believe these should be excluded from the conversions.
Probably, yes. It compiled, which was all I cared about :-)
BTW, if we do that conversion, we should upgrade the checkpatch warn to an error I suppose.
More like remove altogether as __inline and __inline__ will no longer be #defined
$ git grep -P 'define\s+__inline' include/linux/compiler_types.h:#define __inline__ inline include/linux/compiler_types.h:#define __inline inline
Peter Zijlstra
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 18 lines · Joe Perches
Quoted 17 lines · Peter Zijlstra
Quoted 15 lines · Joe Perches
Quoted 8 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).[]
Quoted 3 lines
scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +--I believe these should be excluded from the conversions.
Quoted 7 lines
Quoted 4 lines
Probably, yes. It compiled, which was all I cared about :-)
BTW, if we do that conversion, we should upgrade the checkpatch warn to an error I suppose.
More like remove altogether as
__inlineand__inline__will no longer be #defined
That's the point, therefore checkpatch should error when it sees them. Otherwise we'll grow new instances, because it will compile just file.
Joe Perches
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Peter ZijlstraQuoted 15 lines · Peter Zijlstra
Quoted 14 lines · Joe Perches
Quoted 8 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).[]
Quoted 3 lines
scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +--
Quoted 6 lines
Quoted 1 line
I believe these should be excluded from the conversions.
Probably, yes. It compiled, which was all I cared about :-)
BTW, if we do that conversion, we should upgrade the checkpatch warn to an error I suppose.
More like remove altogether as __inline and __inline__ will no longer be #defined
$ git grep -P 'define\s+__inline' include/linux/compiler_types.h:#define __inline__ inline include/linux/compiler_types.h:#define __inline inline
Joe Perches
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).
[]
Quoted 3 lines
scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +--
I believe these should be excluded from the conversions.
Other than that, generic conversion by script seems a good idea.
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Peter ZijlstraHi Peter,
Quoted 38 lines · Peter Zijlstra
Quoted 16 lines · Borislav Petkov
Ok,
with Segher's help I've been playing with his patch ontop of bleeding edge gcc 9 and here are my observations. Please double-check me for booboos so that they can be addressed while there's time.
So here's what I see ontop of 4.19-rc7:
First marked the alternative
asm()as inline and undeffed the "inline" keyword. I need to do that because of the funky games we do with "inline" redefinitions ininclude/linux/compiler_types.h.And Segher hinted at either doing:
asm volatile inline(...
Quoted 8 lines
or
asm volatile __inline__(...
but both "inline" variants are defined as macros in that file.
Which means we either need to #undef inline before using it in
asm()or come up with something cleverer.# git grep -e "\<__inline__\>" | wc -l 488 # git grep -e "\<__inline\>" | wc -l 56 # git grep -e "\<inline\>" | wc -l 69598And we already have
scripts/checkpatch.pl:# Check for
__inline__and__inline, prefer inline
Quoted 8 lines
Which suggests we do:
git grep -l "\<__inline\(\|__\)\>" | while read file do
sed -i -e 's/\<__inline\(\|__\)\>/inline/g' $filedone
and get it over with.
Do you have a plan to really do this?
This is a nice cleanup anyway.
I think the last minute of MW is
a good timing for the global replacement like this.
Quoted 180 lines
Anyway, with the below patch, I get:
text data bss dec hex filename
17385183 5064780 1953892 24403855 1745f8f defconfig-build/vmlinux 17385678 5064780 1953892 24404350 174617e defconfig-build/vmlinuxWhich shows we inline more (look for
asm_volatilefor the actual changes).So yes, this seems like something we could work with.
--- Documentation/trace/tracepoint-analysis.rst | 2 +- Documentation/translations/ja_JP/SubmittingPatches | 4 +-- Documentation/translations/zh_CN/SubmittingPatches | 4 +-- arch/alpha/include/asm/atomic.h | 12 +++---- arch/alpha/include/asm/bitops.h | 6 ++-- arch/alpha/include/asm/compiler.h | 4 +-- arch/alpha/include/asm/dma.h | 22 ++++++------ arch/alpha/include/asm/floppy.h | 4 +-- arch/alpha/include/asm/irq.h | 2 +- arch/alpha/include/asm/local.h | 4 +-- arch/alpha/include/asm/smp.h | 2 +- arch/arm/mach-iop32x/include/mach/uncompress.h | 2 +- arch/arm/mach-iop33x/include/mach/uncompress.h | 2 +- arch/arm/mach-ixp4xx/include/mach/uncompress.h | 2 +- arch/ia64/hp/common/sba_iommu.c | 2 +- arch/ia64/hp/sim/simeth.c | 2 +- arch/ia64/include/asm/atomic.h | 8 ++--- arch/ia64/include/asm/bitops.h | 34 +++++++++--------- arch/ia64/include/asm/delay.h | 14 ++++---- arch/ia64/include/asm/irq.h | 2 +- arch/ia64/include/asm/page.h | 2 +- arch/ia64/include/asm/sn/leds.h | 2 +- arch/ia64/include/asm/uaccess.h | 4 +-- arch/ia64/include/uapi/asm/rse.h | 12 +++---- arch/ia64/include/uapi/asm/swab.h | 6 ++-- arch/ia64/oprofile/backtrace.c | 4 +-- arch/m68k/include/asm/blinken.h | 2 +- arch/m68k/include/asm/checksum.h | 2 +- arch/m68k/include/asm/dma.h | 32 ++++++++--------- arch/m68k/include/asm/floppy.h | 8 ++--- arch/m68k/include/asm/nettel.h | 8 ++--- arch/m68k/mac/iop.c | 14 ++++---- arch/mips/include/asm/atomic.h | 16 ++++----- arch/mips/include/asm/checksum.h | 2 +- arch/mips/include/asm/dma.h | 20 +++++------ arch/mips/include/asm/jazz.h | 2 +- arch/mips/include/asm/local.h | 4 +-- arch/mips/include/asm/string.h | 8 ++--- arch/mips/kernel/binfmt_elfn32.c | 2 +- arch/nds32/include/asm/swab.h | 4 +-- arch/parisc/include/asm/atomic.h | 20 +++++------ arch/parisc/include/asm/bitops.h | 18 +++++----- arch/parisc/include/asm/checksum.h | 4 +-- arch/parisc/include/asm/compat.h | 2 +- arch/parisc/include/asm/delay.h | 2 +- arch/parisc/include/asm/dma.h | 20 +++++------ arch/parisc/include/asm/ide.h | 8 ++--- arch/parisc/include/asm/irq.h | 2 +- arch/parisc/include/asm/spinlock.h | 12 +++---- arch/powerpc/include/asm/atomic.h | 40 +++++++++++----------- arch/powerpc/include/asm/bitops.h | 28 +++++++-------- arch/powerpc/include/asm/dma.h | 20 +++++------ arch/powerpc/include/asm/edac.h | 2 +- arch/powerpc/include/asm/irq.h | 2 +- arch/powerpc/include/asm/local.h | 14 ++++---- arch/sh/include/asm/pgtable_64.h | 2 +- arch/sh/include/asm/processor_32.h | 4 +-- arch/sh/include/cpu-sh3/cpu/dac.h | 6 ++-- arch/x86/include/asm/alternative.h | 14 ++++---- arch/x86/um/asm/checksum.h | 4 +-- arch/x86/um/asm/checksum_32.h | 4 +-- arch/xtensa/include/asm/checksum.h | 14 ++++---- arch/xtensa/include/asm/cmpxchg.h | 4 +-- arch/xtensa/include/asm/irq.h | 2 +- block/partitions/amiga.c | 2 +- drivers/atm/he.c | 6 ++-- drivers/atm/idt77252.c | 6 ++-- drivers/gpu/drm/mga/mga_drv.h | 2 +- drivers/gpu/drm/mga/mga_state.c | 14 ++++---- drivers/gpu/drm/r128/r128_drv.h | 2 +- drivers/gpu/drm/r128/r128_state.c | 14 ++++---- drivers/gpu/drm/via/via_irq.c | 2 +- drivers/gpu/drm/via/via_verifier.c | 30 ++++++++-------- drivers/isdn/hardware/eicon/platform.h | 14 ++++---- drivers/isdn/i4l/isdn_net.c | 14 ++++---- drivers/isdn/i4l/isdn_net.h | 8 ++--- drivers/media/pci/ivtv/ivtv-ioctl.c | 2 +- drivers/net/ethernet/sun/sungem.c | 8 ++--- drivers/net/ethernet/sun/sunhme.c | 6 ++-- drivers/net/hamradio/baycom_ser_fdx.c | 2 +- drivers/net/wan/lapbether.c | 2 +- drivers/net/wan/n2.c | 4 +-- drivers/parisc/led.c | 4 +-- drivers/parisc/sba_iommu.c | 2 +- drivers/parport/parport_gsc.c | 2 +- drivers/parport/parport_gsc.h | 4 +-- drivers/parport/parport_pc.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 2 +- drivers/scsi/pcmcia/sym53c500_cs.c | 4 +-- drivers/scsi/qla2xxx/qla_inline.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 4 +-- drivers/staging/rtl8723bs/core/rtw_pwrctrl.c | 4 +-- drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 2 +- drivers/staging/rtl8723bs/include/drv_types.h | 6 ++-- drivers/staging/rtl8723bs/include/ieee80211.h | 6 ++-- drivers/staging/rtl8723bs/include/osdep_service.h | 10 +++--- .../rtl8723bs/include/osdep_service_linux.h | 14 ++++---- drivers/staging/rtl8723bs/include/rtw_mlme.h | 14 ++++---- drivers/staging/rtl8723bs/include/rtw_recv.h | 16 ++++----- drivers/staging/rtl8723bs/include/sta_info.h | 2 +- drivers/staging/rtl8723bs/include/wifi.h | 14 ++++---- drivers/staging/rtl8723bs/include/wlan_bssdef.h | 2 +- drivers/tty/amiserial.c | 2 +- drivers/tty/serial/ip22zilog.c | 2 +- drivers/tty/serial/sunsab.c | 4 +-- drivers/tty/serial/sunzilog.c | 2 +- drivers/video/fbdev/core/fbcon.c | 20 +++++------ drivers/video/fbdev/ffb.c | 2 +- drivers/video/fbdev/intelfb/intelfbdrv.c | 10 +++--- drivers/video/fbdev/intelfb/intelfbhw.c | 2 +- drivers/w1/masters/matrox_w1.c | 4 +-- fs/coda/coda_linux.h | 6 ++-- fs/freevxfs/vxfs_inode.c | 2 +- fs/nfsd/nfsfh.h | 4 +-- include/acpi/platform/acgcc.h | 2 +- include/acpi/platform/acintel.h | 2 +- include/asm-generic/ide_iops.h | 8 ++--- include/linux/atalk.h | 4 +-- include/linux/ceph/messenger.h | 2 +- include/linux/compiler_types.h | 4 +-- include/linux/hdlc.h | 4 +-- include/linux/inetdevice.h | 8 ++--- include/linux/parport.h | 4 +-- include/linux/parport_pc.h | 22 ++++++------ include/net/ax25.h | 2 +- include/net/checksum.h | 2 +- include/net/dn_nsp.h | 16 ++++----- include/net/ip.h | 2 +- include/net/ip6_checksum.h | 2 +- include/net/ipx.h | 10 +++--- include/net/llc_c_ev.h | 4 +-- include/net/llc_conn.h | 4 +-- include/net/llc_s_ev.h | 2 +- include/net/netrom.h | 8 ++--- include/net/scm.h | 14 ++++---- include/net/udplite.h | 2 +- include/net/x25.h | 8 ++--- include/net/xfrm.h | 18 +++++----- include/uapi/linux/atm.h | 4 +-- include/uapi/linux/atmsap.h | 2 +- include/uapi/linux/map_to_7segment.h | 2 +- include/uapi/linux/netfilter_arp/arp_tables.h | 2 +- include/uapi/linux/netfilter_bridge/ebtables.h | 2 +- include/uapi/linux/netfilter_ipv4/ip_tables.h | 2 +- include/uapi/linux/netfilter_ipv6/ip6_tables.h | 2 +- include/video/newport.h | 12 +++---- lib/zstd/mem.h | 2 +- net/appletalk/atalk_proc.c | 4 +-- net/appletalk/ddp.c | 2 +- net/core/neighbour.c | 2 +- net/core/scm.c | 2 +- net/decnet/dn_nsp_in.c | 2 +- net/decnet/dn_nsp_out.c | 2 +- net/decnet/dn_route.c | 2 +- net/decnet/dn_table.c | 4 +-- net/ipv4/igmp.c | 2 +- net/ipv6/af_inet6.c | 2 +- net/ipv6/icmp.c | 4 +-- net/ipv6/udp.c | 4 +-- net/lapb/lapb_iface.c | 4 +-- net/llc/llc_input.c | 2 +- scripts/checkpatch.pl | 8 ++--- scripts/genksyms/keywords.c | 4 +-- scripts/kernel-doc | 4 +-- sound/sparc/amd7930.c | 6 ++-- 165 files changed, 547 insertions(+), 547 deletions(-)
Signature · 2 lines
Best Regards Masahiro Yamada
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 2 lines · Segher Boessenkool
It would be great to hear from kernel people if it works adequately for what you guys want it for :-)
Sure, ping me when you have the final version and I'll try to build gcc with it and do some size comparisons.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 4 lines · Segher Boessenkool
The code immediately after this makes it size 1, even for things like
asm(""), I suppose this works better for the inliner. But that's a detail (and it might change); the description says "consider this asm as minimum length and cost for inlining decisions", which works for either 0 or 1.
Thanks for implementing this, much appreciated. If you need people to test stuff, lemme know.
Quoted 3 lines
You can think of it as meaning "we want this asm inlined always", and then whether that actually happens depends on if the function around it is inlined or not.
My only concern is how we would catch the other extremity where the inline asm grows too big and we end up inlining it everywhere and thus getting fat. The 0day bot already builds tinyconfigs but we should be looking at vmlinux size growth too.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 5 lines · Segher Boessenkool
Quoted 4 lines · Ingo Molnar
Quoted 2 lines · Richard Biener
Can kernel folks give this a second and third thought please so we don't implement sth that in the end won't satisfy you guys?
Quoted 8 lines
Quoted 3 lines
So this basically passes '0 size' to the inliner, which should be better than passing in the explicit size, as we'd inevitably get it wrong in cases.
The code immediately after this makes it size 1, even for things like
asm(""), I suppose this works better for the inliner. But that's a detail (and it might change); the description says "consider this asm as minimum length and cost for inlining decisions", which works for either 0 or 1.
It was made 1 as otherwise the inliner happily explodes on
void foo () { asm(""); foo(); }
Quoted 8 lines
Quoted 4 lines
I also like 'size 0' for the reason that we tend to write assembly code and mark it 'inline' if we really think it matters to performance, so making it more likely to be inlined when used within another inline function is a plus as well.
You can think of it as meaning "we want this asm inlined always", and then whether that actually happens depends on if the function around it is inlined or not.
Richard.
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Richard BienerQuoted 21 lines · Richard Biener
Quoted 20 lines · Segher Boessenkool
Quoted 18 lines · Richard Biener
Quoted 5 lines · Segher Boessenkool
Quoted 4 lines · Michael Matz
Quoted 3 lines · Segher Boessenkool
Quoted 2 lines · Borislav Petkov
Now, Richard suggested doing something like:
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
Quoted 6 lines
Quoted 4 lines
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Looks good. A few nits - you need to document this in extend.texi, the
Yup.
Quoted 1 line
tree flag use needs documenting in
tree-core.h,
Ah yes.
Quoted 3 lines
and we need a testcase
(I'd suggest one that shows we inline a function with "large" asm inline () even at -Os).
I have one. Oh, and I probably should do a comment at the one line of code that isn't just bookkeeping ;-)
Quoted 2 lines
Oh, and I don't think we want C and C++ to diverge - so you need to cook up C++ support as well.
Right, that's why I said "C only so far".
Quoted 2 lines
Can kernel folks give this a second and third thought please so we don't implement sth that in the end won't satisfy you guys?
Or actually try it out and see if it has the desired effect! Nothing beats field trials.
I'll do the C++ thing today hopefully, and send things to gcc-patches@.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 16 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
It looks good to me in general. I have a couple of reservations, but I suspect you will not want to address them:
1. It is not backward compatible, requiring a C macro to wrap it, as the kernel might be built with different compilers.
2. It is specific to asm. I do not have in mind another use case (excluding the __builtin_constant_p), but it would be nicer IMHO to have a builtin saying “ignore the cost of this statement” for the matter of optimizations.
Regards,
Nadav
Re: PROPOSAL: Extend inline asm syntax with size spec
Hi Nadav,
Quoted 8 lines · Nadav Amit
Quoted 1 line · Segher Boessenkool
How does this look?
It looks good to me in general. I have a couple of reservations, but I suspect you will not want to address them:
1. It is not backward compatible, requiring a C macro to wrap it, as the kernel might be built with different compilers.
How *could* it be backward compatible? There should be an error or at least a warning if the compiler does not support this, in general.
For the kernel, the kernel already has plenty of infrastructure to support this (compiler.h etc.) For other applications it is quite trivial, too.
Quoted 1 line
2. It is specific to asm.
Yes, and that is on purpose.
Quoted 3 lines
I do not have in mind another use case (excluding
the__builtin_constant_p), but it would be nicer IMHO to have a builtin saying “ignore the cost of this statement” for the matter of optimizations.
That is a hundred or a thousand times more work to design and implement (including testing etc.) I'm not going to do it, but feel free to try yourself!
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Nadav AmitQuoted 30 lines · Nadav Amit
Quoted 16 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
It looks good to me in general. I have a couple of reservations, but I suspect you will not want to address them:
Quoted 6 lines
1. It is not backward compatible, requiring a C macro to wrap it, as the kernel might be built with different compilers.
2. It is specific to asm. I do not have in mind another use case (excluding the
__builtin_constant_p), but it would be nicer IMHO to have a builtin saying “ignore the cost of this statement” for the matter of optimizations.
The only easy possibility that comes to my mid is sth like
__attribute__((always_inline, zero_cost)) foo ()
{
... your stmts ...
}
and us, upon inlining, marking the inlined stmts properly. That would also work for the asm() case and it would be backwards compatible (well, you'd get a diagnostic for the unknown zero_cost attribute).
There's the slight complication that if you have, say
_1 = _2 * 3; // zero-cost
_4 = _1 * 2;
and optimization ends up combining those to
_4 = _2 * 6;
then is this stmt supposed to be zero-cost or not? Compare that to
_1 = _2 * 3;
_4 = _1 * 2; // zero-cost
So outside of asm() there are new issues that come up with respect to expected (cost) semantics.
Richard.
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolHi.
Quoted 17 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Thank you very much for your work.
https://gcc.gnu.org/ml/gcc-patches/2018-10/msg01932.html
How is the progress of this in GCC ML?
I am really hoping the issue will be solved by compiler instead of the in-kernel workaround.
Since commit 77b0bf55bc675233d22cd5df97605d516d64525e, DISTCC breakage was reported.
Then, another problem showed up.
Debian linux-headers package is broken
due to missing arch/x86/kernel/macros.s
https://www.spinics.net/lists/linux-kbuild/msg20037.html
The kernel-devel RPM package is broken as well.
More fundamentally, the external module building itself is broken; 'make clean' must keep all files needed for external modules, but *.s files are all gone.
Of course, we can fix the problems at the cost of uglifying Makefiles. I wrote a patch to fix the external module building
and packages, and now have it in hand locally.
But, I'd like to ask if x86 people want to keep this macros.s approach. Revert 77b0bf55bc675 right now
assuming the compiler will eventually solve the issue?
Do you have ideas? Comments?
Signature · 2 lines
Best Regards Masahiro Yamada
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 29 lines · Masahiro Yamada
Quoted 17 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Quoted 6 lines
Thank you very much for your work.
https://gcc.gnu.org/ml/gcc-patches/2018-10/msg01932.html
How is the progress of this in GCC ML?
Latest patch was pinged a few times:
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg01569.html .
I'll ping it again. Will fix the subject as well if I remember to, sigh.
Quoted 2 lines
I am really hoping the issue will be solved by compiler instead of the in-kernel workaround.
This will only be fixed from GCC 9 on, if the compiler adopts it. The kernel wants to support ancient GCC, so it will need to have a workaround for older GCC versions anyway.
Segher
Boris Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 4 lines · Segher Boessenkool
This will only be fixed from GCC 9 on, if the compiler adopts it. The kernel wants to support ancient GCC, so it will need to have a workaround
for older GCC versions anyway.
What about backporting it, like Richard says?
Signature · 1 line
Sent from a small device: formatting sux and brevity is inevitable.
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 7 lines · Boris Petkov
Quoted 4 lines · Segher Boessenkool
This will only be fixed from GCC 9 on, if the compiler adopts it. The kernel wants to support ancient GCC, so it will need to have a workaround
for older GCC versions anyway.What about backporting it, like Richard says?
Let me first get it into GCC trunk :-)
It should backport fine, sure; and I'll work on that.
Segher
Re: PROPOSAL: Extend inline asm syntax with size spec
Hi Segher,
Quoted 8 lines · Segher Boessenkool
Quoted 6 lines · Boris Petkov
Quoted 4 lines · Segher Boessenkool
This will only be fixed from GCC 9 on, if the compiler adopts it. The kernel wants to support ancient GCC, so it will need to have a workaround
for older GCC versions anyway.
Quoted 6 lines
Quoted 1 line
What about backporting it, like Richard says?
Let me first get it into GCC trunk :-)
It should backport fine, sure; and I'll work on that.
Now, I can see it in the GCC trunk. Hooray!!!
commit 6de46ad5326fc5e6b730a2feb8c62d09c1561f92
Author: segher <segher@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Thu Dec 6 17:56:58 2018 +0000
asm inline
The Linux kernel people want a feature that makes GCC pretend some inline assembler code is tiny (while it would think it is huge), so that such code will be inlined essentially always instead of essentially never.
This patch lets you say "asm inline" instead of just "asm", with the result that that inline assembler is always counted as minimum cost for inlining. It implements this for C and C++, making "inline" another asm-qualifier (supplementing "volatile" and "goto").
Signature · 2 lines
Best Regards Masahiro Yamada
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolHi Segher,
Quoted 8 lines · Segher Boessenkool
Quoted 6 lines · Boris Petkov
Quoted 4 lines · Segher Boessenkool
This will only be fixed from GCC 9 on, if the compiler adopts it. The kernel wants to support ancient GCC, so it will need to have a workaround
for older GCC versions anyway.
Quoted 6 lines
Quoted 1 line
What about backporting it, like Richard says?
Let me first get it into GCC trunk :-)
It should backport fine, sure; and I'll work on that.
Now, I can see it in the GCC trunk. Hooray!!!
commit 6de46ad5326fc5e6b730a2feb8c62d09c1561f92
Author: segher <segher@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Thu Dec 6 17:56:58 2018 +0000
asm inline
The Linux kernel people want a feature that makes GCC pretend some inline assembler code is tiny (while it would think it is huge), so that such code will be inlined essentially always instead of essentially never.
This patch lets you say "asm inline" instead of just "asm", with the result that that inline assembler is always counted as minimum cost for inlining. It implements this for C and C++, making "inline" another asm-qualifier (supplementing "volatile" and "goto").
Signature · 2 lines
Best Regards Masahiro Yamada
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolQuoted 4 lines · Segher Boessenkool
This will only be fixed from GCC 9 on, if the compiler adopts it. The kernel wants to support ancient GCC, so it will need to have a workaround
for older GCC versions anyway.
What about backporting it, like Richard says?
Signature · 1 line
Sent from a small device: formatting sux and brevity is inevitable.
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
In reply to Masahiro YamadaQuoted 3 lines · Masahiro Yamada
But, I'd like to ask if x86 people want to keep this macros.s approach. Revert
77b0bf55bc675right now
assuming the compiler will eventually solve the issue?
Yap, considering how elegant the compiler solution is and how much problems this macros-in-asm thing causes, I think we should patch out the latter and wait for gcc9. I mean, the savings are not so mind-blowing to have to deal with the fallout.
But this is just my opinion.
Thx.
Signature · 5 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 11 lines · Borislav Petkov
Quoted 3 lines · Masahiro Yamada
But, I'd like to ask if x86 people want to keep this macros.s approach. Revert
77b0bf55bc675right now
assuming the compiler will eventually solve the issue?Yap, considering how elegant the compiler solution is and how much problems this macros-in-asm thing causes, I think we should patch out the latter and wait for gcc9. I mean, the savings are not so mind-blowing to have to deal with the fallout.
But this is just my opinion.
I'd be not opposed to backporting the asm inline support.
Of course we still have to be happy with it and install the patch ;)
Are you (kernel folks) happy with asm inline ()?
Richard.
Quoted 3 lines
Thx.
Signature · 2 lines
Richard Biener <[email protected]> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)
Borislav Petkov
maintainerRe: PROPOSAL: Extend inline asm syntax with size spec
Quoted 1 line · Richard Biener
I'd be not opposed to backporting the asm inline support.
Even better! :-)
Quoted 3 lines
Of course we still have to be happy with it and install the patch ;)
Are you (kernel folks) happy with asm inline ()?
Yes, I think we are:
https://lkml.kernel.org/r/[email protected]
Thx.
Signature · 5 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 5 lines · Borislav Petkov
Quoted 1 line · Richard Biener
I'd be not opposed to backporting the asm inline support.
Even better! :-)
Quoted 7 lines
Quoted 3 lines
Of course we still have to be happy with it and install the patch ;)
Are you (kernel folks) happy with asm inline ()?
Yes, I think we are:
OK, Segher - can you ping the latest version of the patch please?
Thanks,
Richard.
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Richard BienerQuoted 1 line · Richard Biener
I'd be not opposed to backporting the asm inline support.
Even better! :-)
Quoted 3 lines
Of course we still have to be happy with it and install the patch ;)
Are you (kernel folks) happy with asm inline ()?
Yes, I think we are:
https://lkml.kernel.org/r/[email protected]
Thx.
Signature · 5 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Segher BoessenkoolHi.
Quoted 17 lines · Segher Boessenkool
Quoted 15 lines · Richard Biener
Quoted 13 lines · Segher Boessenkool
Quoted 10 lines · Michael Matz
Quoted 6 lines · Segher Boessenkool
Quoted 3 lines · Borislav Petkov
Now, Richard suggested doing something like:
1) inline asm ("...")
What would the semantics of this be?
The size of the inline asm wouldn't be counted towards the inliner size limits (or be counted as "1").
That sounds like a good option.
Quoted 8 lines
Quoted 3 lines
Yes, I also like it for simplicity. It also avoids the requirement of translating the number (in bytes?) given by the user to "number of GIMPLE instructions" as needed by the inliner.
This patch implements this, for C only so far. And the syntax is "asm inline", which is more in line with other syntax.
How does this look?
Thank you very much for your work.
https://gcc.gnu.org/ml/gcc-patches/2018-10/msg01932.html
How is the progress of this in GCC ML?
I am really hoping the issue will be solved by compiler instead of the in-kernel workaround.
Since commit 77b0bf55bc675233d22cd5df97605d516d64525e, DISTCC breakage was reported.
Then, another problem showed up.
Debian linux-headers package is broken
due to missing arch/x86/kernel/macros.s
https://www.spinics.net/lists/linux-kbuild/msg20037.html
The kernel-devel RPM package is broken as well.
More fundamentally, the external module building itself is broken; 'make clean' must keep all files needed for external modules, but *.s files are all gone.
Of course, we can fix the problems at the cost of uglifying Makefiles. I wrote a patch to fix the external module building
and packages, and now have it in hand locally.
But, I'd like to ask if x86 people want to keep this macros.s approach. Revert 77b0bf55bc675 right now
assuming the compiler will eventually solve the issue?
Do you have ideas? Comments?
Signature · 2 lines
Best Regards Masahiro Yamada
RE: PROPOSAL: Extend inline asm syntax with size spec
In reply to Michael MatzFrom: Michael Matz
Quoted 1 line
Sent: 07 October 2018 16:53
...
Quoted 7 lines
I think the examples I saw from Boris were all indirect inlines:
static inline void
foo(){asm("large-looking-but-small-asm"); } static voidbar1(){ ...foo()... }
static voidbar2(){ ...foo()... }
void goo (void) {bar1(); } // bar1 should have been inlined
Quoted 5 lines
So, while the immediate asm user was marked as always inline that in turn caused users of it to become non-inlined. I'm assuming the kernel guys did proper measurements that they _really_ get some non-trivial speed benefit by inlining bar1/bar2, but for some reasons (I didn't inquire) didn't want to mark them all as inline as well.
Could you add a 'size' attribute to the 'always inlined' foo() above rather than trying to add one to the asm() statement itself. Then add a warning in the documentation that small size attributes might make the assembly fail due to limited branch offsets (etc).
Size '1' probably ought to be reserved for things that definitely fit in a delay slot.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
RE: PROPOSAL: Extend inline asm syntax with size spec
In reply to Michael MatzFrom: Michael Matz
Quoted 1 line
Sent: 07 October 2018 16:53
...
Quoted 7 lines
I think the examples I saw from Boris were all indirect inlines:
static inline void
foo(){asm("large-looking-but-small-asm"); } static voidbar1(){ ...foo()... }
static voidbar2(){ ...foo()... }
void goo (void) {bar1(); } // bar1 should have been inlined
Quoted 5 lines
So, while the immediate asm user was marked as always inline that in turn caused users of it to become non-inlined. I'm assuming the kernel guys did proper measurements that they _really_ get some non-trivial speed benefit by inlining bar1/bar2, but for some reasons (I didn't inquire) didn't want to mark them all as inline as well.
Could you add a 'size' attribute to the 'always inlined' foo() above rather than trying to add one to the asm() statement itself. Then add a warning in the documentation that small size attributes might make the assembly fail due to limited branch offsets (etc).
Size '1' probably ought to be reserved for things that definitely fit in a delay slot.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Borislav PetkovQuoted 34 lines · Borislav Petkov
Hi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost estimation heuristic which counts lines, I think, for example like in this here macro:
the resulting code ends up not inlining the functions themselves which use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));with which user can tell gcc what the size of that inline asm statement is and thus allow for more precise cost estimation and in the end better inlining.
Quoted 5 lines
And FWIW 3) looks pretty straight-forward to me because attributes are pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thanks for taking care of it. I would like to mention a second issue, since you may want to resolve both with a single solution: not inlining conditional __builtin_constant_p(), in which there are two code-paths - one for constants and one for variables.
Consider for example the Linux kernel ilog2 macro, which has a condition based on __builtin_constant_p() (
https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/log2.h#L160
). The compiler mistakenly considers the “heavy” code-path that is supposed to be evaluated only in compilation time to evaluate the code size. This causes the kernel to consider functions such as kmalloc() as “big”. kmalloc() is marked with always_inline attribute, so instead the calling functions, such as kzalloc() are not inlined.
When I thought about hacking gcc to solve this issue, I considered an intrinsic that would override the cost of a given statement. This solution is not too nice, but may solve both issues.
In addition, note that AFAIU the impact of a wrong cost of code estimation can also impact loop and other optimizations.
Regards,
Nadav
PATCH RESEND 1/1 PROPOSAL: Extend inline asm syntax with size spec
Second try after being blocked by gcc mailing list:
at 9:09 AM, Nadav Amit <[email protected]<mailto:[email protected]>> wrote:
at 2:18 AM, Borislav Petkov <[email protected]<mailto:[email protected]>> wrote:
Hi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost estimation heuristic which counts lines, I think, for example like in this here macro:
the resulting code ends up not inlining the functions themselves which use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));
with which user can tell gcc what the size of that inline asm statement is and thus allow for more precise cost estimation and in the end better inlining.
And FWIW 3) looks pretty straight-forward to me because attributes are pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thanks for taking care of it. I would like to mention a second issue, since you may want to resolve both with a single solution: not inlining conditional __builtin_constant_p(), in which there are two code-paths - one for constants and one for variables.
Consider for example the Linux kernel ilog2 macro, which has a condition based on __builtin_constant_p() (
https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/log2.h#L160
). The compiler mistakenly considers the “heavy” code-path that is supposed to be evaluated only in compilation time to evaluate the code size. This causes the kernel to consider functions such as kmalloc() as “big”. kmalloc() is marked with always_inline attribute, so instead the calling functions, such as kzalloc() are not inlined.
When I thought about hacking gcc to solve this issue, I considered an intrinsic that would override the cost of a given statement. This solution is not too nice, but may solve both issues.
In addition, note that AFAIU the impact of a wrong cost of code estimation can also impact loop and other optimizations.
Regards,
Nadav
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Nadav AmitQuoted 55 lines · Nadav Amit
Quoted 8 lines · Borislav Petkov
Hi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost
estimation
Quoted 4 lines
heuristic which counts lines, I think, for example like in this here macro:
Quoted 2 lines
the resulting code ends up not inlining the functions themselves
which
Quoted 10 lines
use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Quoted 7 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));with which user can tell gcc what the size of that inline asm
statement
Quoted 1 line
is and thus allow for more precise cost estimation and in the end
better
Quoted 3 lines
inlining.
And FWIW 3) looks pretty straight-forward to me because attributes
are
Quoted 4 lines
pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thanks for taking care of it. I would like to mention a second issue, since
you may want to resolve both with a single solution: not inlining conditional__builtin_constant_p(), in which there are two code-paths - one
for constants and one for variables.
Quoted 7 lines
Consider for example the Linux kernel ilog2 macro, which has a condition
based on__builtin_constant_p()(
https://elixir.bootlin.com/linux/v4.19-rc7/source/include/linux/log2.h#L160
). The compiler mistakenly considers the “heavy” code-path that is supposed
to be evaluated only in compilation time to evaluate the code size.
But this is a misconception about __builtin_constant_p. It doesn't guard sth like 'constexpr' regions. If you try to use it with those semantics you'll fail (appearantly you do).
Of course IPA CP code size estimates when seeing a constant fed to bcp might be not optimal, that's another issue of course.
Richard.
Quoted 17 lines
This
causes the kernel to consider functions such askmalloc()as “big”.kmalloc()is marked withalways_inlineattribute, so instead the calling
functions, such askzalloc()are not inlined.When I thought about hacking gcc to solve this issue, I considered an intrinsic that would override the cost of a given statement. This solution
is not too nice, but may solve both issues.In addition, note that AFAIU the impact of a wrong cost of code estimation
can also impact loop and other optimizations.Regards,
Nadav
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 61 lines · Richard Biener
Quoted 52 lines · Nadav Amit
Quoted 8 lines · Borislav Petkov
Hi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost
estimation
Quoted 2 lines
heuristic which counts lines, I think, for example like in this here macro:
Quoted 1 line
the resulting code ends up not inlining the functions themselves
which
Quoted 10 lines
use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Quoted 7 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));with which user can tell gcc what the size of that inline asm
statement
Quoted 1 line
is and thus allow for more precise cost estimation and in the end
better
Quoted 3 lines
inlining.
And FWIW 3) looks pretty straight-forward to me because attributes
are
Quoted 4 lines
pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thanks for taking care of it. I would like to mention a second issue, since
you may want to resolve both with a single solution: not inlining conditional__builtin_constant_p(), in which there are two code-paths - one
for constants and one for variables.Quoted 7 lines
Consider for example the Linux kernel ilog2 macro, which has a condition
based on__builtin_constant_p()(
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv4.19-rc7%2Fsource%2Finclude%2Flinux%2Flog2.h%23L160&data=02%7C01%7Cnamit%40vmware.com%7C860403cecb874db64b7e08d62c746f46%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636745275975515386&sdata=Hk39Za9%2FxcFyK0sGENB24d6QySjsDGzF%2FwqjnUEMiGk%3D&reserved=0
). The compiler mistakenly considers the “heavy” code-path that is supposed
to be evaluated only in compilation time to evaluate the code size.
Quoted 3 lines
But this is a misconception about
__builtin_constant_p. It doesn't guard sth like 'constexpr' regions. If you try to use it with those semantics you'll fail (appearantly you do).Of course IPA CP code size estimates when seeing a constant fed to bcp might be not optimal, that's another issue of course.
I understand that this is might not be the right way to implement macros such as ilog2() and test_bit(), but this code is around for some time.
I thought of using __builtin_choose_expr() instead of ternary operator, but this introduces a different problem, as the variable version is used instead of the constant one in many cases. From my brief experiments with llvm, it appears that llvm does not have both of these issues (wrong cost attributed to inline asm and conditions based on __builtin_constant_p()).
So what alternative do you propose to implement ilog2() like behavior? I was digging through the gcc code to find a workaround with no success.
Thanks,
Nadav
Re: PROPOSAL: Extend inline asm syntax with size spec
Quoted 63 lines · Nadav Amit
Quoted 61 lines · Richard Biener
Quoted 59 lines · Nadav Amit
Quoted 8 lines · Borislav Petkov
Hi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost
estimation
Quoted 2 lines
heuristic which counts lines, I think, for example like in this here macro:
Quoted 1 line
the resulting code ends up not inlining the functions themselves
which
Quoted 10 lines
use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Quoted 7 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));with which user can tell gcc what the size of that inline asm
statement
Quoted 1 line
is and thus allow for more precise cost estimation and in the end
better
Quoted 3 lines
inlining.
And FWIW 3) looks pretty straight-forward to me because attributes
are
Quoted 4 lines
pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thanks for taking care of it. I would like to mention a second issue, since
you may want to resolve both with a single solution: not inlining conditional__builtin_constant_p(), in which there are two code-paths - one
for constants and one for variables.Consider for example the Linux kernel ilog2 macro, which has a condition
based on__builtin_constant_p()(
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv4.19-rc7%2Fsource%2Finclude%2Flinux%2Flog2.h%23L160&data=02%7C01%7Cnamit%40vmware.com%7C860403cecb874db64b7e08d62c746f46%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636745275975515386&sdata=Hk39Za9%2FxcFyK0sGENB24d6QySjsDGzF%2FwqjnUEMiGk%3D&reserved=0
). The compiler mistakenly considers the “heavy” code-path that is supposed
to be evaluated only in compilation time to evaluate the code size.
Quoted 6 lines
Quoted 3 lines
But this is a misconception about
__builtin_constant_p. It doesn't guard sth like 'constexpr' regions. If you try to use it with those semantics you'll fail (appearantly you do).Of course IPA CP code size estimates when seeing a constant fed to bcp might be not optimal, that's another issue of course.
I understand that this is might not be the right way to implement macros such as
ilog2()andtest_bit(), but this code is around for some time.
That doesn't make it right -- and there's been numerous bogus bugs reported against ilog2 because the authors of ilog2 haven't had a clear understanding of the semantics of builtin_constant_p.
Jeff
Re: PROPOSAL: Extend inline asm syntax with size spec
In reply to Nadav AmitQuoted 70 lines · Nadav Amit
Quoted 61 lines · Richard Biener
Quoted 52 lines · Nadav Amit
Quoted 8 lines · Borislav Petkov
Hi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost
estimation
Quoted 2 lines
heuristic which counts lines, I think, for example like in this here macro:
Quoted 1 line
the resulting code ends up not inlining the functions themselves
which
Quoted 10 lines
use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Quoted 7 lines
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));with which user can tell gcc what the size of that inline asm
statement
Quoted 1 line
is and thus allow for more precise cost estimation and in the end
better
Quoted 3 lines
inlining.
And FWIW 3) looks pretty straight-forward to me because attributes
are
Quoted 4 lines
pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thanks for taking care of it. I would like to mention a second issue, since
you may want to resolve both with a single solution: not inlining conditional__builtin_constant_p(), in which there are two code-paths - one
for constants and one for variables.Quoted 7 lines
Consider for example the Linux kernel ilog2 macro, which has a condition
based on__builtin_constant_p()(
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Felixir.bootlin.com%2Flinux%2Fv4.19-rc7%2Fsource%2Finclude%2Flinux%2Flog2.h%23L160&data=02%7C01%7Cnamit%40vmware.com%7C860403cecb874db64b7e08d62c746f46%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636745275975515386&sdata=Hk39Za9%2FxcFyK0sGENB24d6QySjsDGzF%2FwqjnUEMiGk%3D&reserved=0
). The compiler mistakenly considers the “heavy” code-path that is supposed
to be evaluated only in compilation time to evaluate the code size.Quoted 3 lines
But this is a misconception about
__builtin_constant_p. It doesn't guard sth like 'constexpr' regions. If you try to use it with those semantics you'll fail (appearantly you do).Of course IPA CP code size estimates when seeing a constant fed to bcp might be not optimal, that's another issue of course.
I understand that this is might not be the right way to implement macros such as
ilog2()andtest_bit(), but this code is around for some time.
Quoted 8 lines
I thought of using
__builtin_choose_expr()instead of ternary operator, but this introduces a different problem, as the variable version is used instead of the constant one in many cases. From my brief experiments with llvm, it appears that llvm does not have both of these issues (wrong cost attributed to inline asm and conditions based on__builtin_constant_p()).So what alternative do you propose to implement
ilog2()like behavior? I was digging through the gcc code to find a workaround with no success.
1) Don't try to cheat the compilers constant propagation abilities
2) Use a language that allows this (C++)
3) Define (and implement) the corresponding GNU C extension
__builtin_constant_p() isn't the right fit (I wonder what it was implemented for in the first place though...).
I suppose you want sth like
if (__builtin_constant_p (x))
return __constexpr ...;
or use a call and have constexpr functions. Note it wouldn't be C++-constexpr like since you want the constexpr evaluation to happen very late in the compilation to benefit from optimizations and you are fine with the non-constexpr path.
Properly defining a language extension is hard.
Richard.
Quoted 5 lines
Thanks,
Nadav
Signature · 2 lines
Richard Biener <[email protected]> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)
Borislav Petkov
maintainerPROPOSAL: Extend inline asm syntax with size spec
In reply to Nadav AmitHi people,
this is an attempt to see whether gcc's inline asm heuristic when estimating inline asm statements' cost for better inlining can be improved.
AFAIU, the problematic arises when one ends up using a lot of inline asm statements in the kernel but due to the inline asm cost estimation heuristic which counts lines, I think, for example like in this here macro:
the resulting code ends up not inlining the functions themselves which use this macro. I.e., you see a CALL <function> instead of its body getting inlined directly.
Even though it should be because the actual instructions are only a couple in most cases and all those other directives end up in another section anyway.
The issue is explained below in the forwarded mail in a larger detail too.
Now, Richard suggested doing something like:
1) inline asm ("...")
2) asm ("..." : : : : <size-expr>)
3) asm ("...") __attribute__((asm_size(<size-expr>)));
with which user can tell gcc what the size of that inline asm statement is and thus allow for more precise cost estimation and in the end better inlining.
And FWIW 3) looks pretty straight-forward to me because attributes are pretty common anyways.
But I'm sure there are other options and I'm sure people will have better/different ideas so feel free to chime in.
Thx.
Quoted 148 lines · Nadav Amit
This patch-set deals with an interesting yet stupid problem: kernel code that does not get inlined despite its simplicity. There are several causes for this behavior: "cold" attribute on
__init, different function optimization levels; conditional constant computations based on__builtin_constant_p(); and finally large inline assembly blocks.This patch-set deals with the inline assembly problem. I separated these patches from the others (that were sent in the RFC) for easier inclusion. I also separated the removal of unnecessary new-lines which would be sent separately.
The problem with inline assembly is that inline assembly is often used by the kernel for things that are other than code - for example, assembly directives and data. GCC however is oblivious to the content of the blocks and assumes their cost in space and time is proportional to the number of the perceived assembly "instruction", according to the number of newlines and semicolons. Alternatives, paravirt and other mechanisms are affected, causing code not to be inlined, and degrading compilation quality in general.
The solution that this patch-set carries for this problem is to create an assembly macro, and then call it from the inline assembly block. As a result, the compiler sees a single "instruction" and assigns the more appropriate cost to the code.
To avoid uglification of the code, as many noted, the macros are first precompiled into an assembly file, which is later assembled together with the C files. This also enables to avoid duplicate implementation that was set before for the asm and C code. This can be seen in the exception table changes.
Overall this patch-set slightly increases the kernel size (my build was done using my Ubuntu 18.04 config + localyesconfig for the record):
text data bss dec hex filename
18140829 10224724 2957312 31322865 1ddf2f1 ./vmlinux before 18163608 10227348 2957312 31348268 1de562c ./vmlinux after (+0.1%)The number of static functions in the image is reduced by 379, but actually inlining is even better, which does not always shows in these
numbers: a function may be inlined causing the calling function not to be inlined.I ran some limited number of benchmarks, and in general the performance impact is not very notable. You can still see >10 cycles shaved off some syscalls that manipulate page-tables (e.g.,
mprotect()), in which paravirt caused many functions not to be inlined. In addition this patch-set can prevent issues such as [1], and improves code readability and maintainability.Update: Rasmus recently caused me (inadvertently) to become paranoid about the dependencies. To clarify: if any of the headers changes, any c file which uses macros that are included in
macros.Swould be fine as long as it includes the header as well (as it should). Adding an assertion to check this is done might become slightly ugly, and nobody else is concerned about it. Another minor issue is that changes ofmacros.Swould not trigger a global rebuild, but that is pretty similar to changes of theMakefilethat do not trigger a rebuild.[1] https://patchwork.kernel.org/patch/10450037/
v8->v9: * Restoring the '-pipe' parameter (Rasmus)
* Adding Kees's tested-by tag (Kees)
v7->v8: * Add acks (Masahiro, Max)
* Rebase on 4.19 (Ingo)
v6->v7: * Fix context switch tracking (Ingo)
* Fix xtensa build error (Ingo)
* Rebase on 4.18-rc8
v5->v6: * Removing more code from jump-labels (PeterZ)
* Fix build issue on i386 (0-day, PeterZ)
v4->v5: *Makefilefixes (Masahiro, Sam)
v3->v4: * Changed naming of macros in 2 patches (PeterZ)
* Minor cleanup of the paravirt patch
v2->v3: * Several build issues resolved (0-day)
* Wrong comments fix (Josh)
* Change asm vs C order in refcount (Kees)
v1->v2: * Compiling the macros into a separate .s file, improving
readability (Linus)
* Improving assembly formatting, applying most of the comments according to my judgment (Jan)
* Adding exception-table, cpufeature and jump-labels
* Removing new-line cleanup; to be submitted separatelyCc Masahiro Yamada <[email protected]>Cc Sam Ravnborg <[email protected]>Cc Alok Kataria <[email protected]>Cc Christopher Li <[email protected]>Cc Greg Kroah-Hartman <[email protected]>Cc "H. Peter Anvin" <[email protected]>Cc Ingo Molnar <[email protected]>Cc Jan Beulich <[email protected]>Cc Josh Poimboeuf <[email protected]>Cc Juergen Gross <[email protected]>Cc Kate Stewart <[email protected]>Cc Kees Cook <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Philippe Ombredanne <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Linus Torvalds <[email protected]>Cc Chris Zankel <[email protected]>Cc Max Filippov <[email protected]>Nadav Amit (10):
xtensa: definingLINKER_SCRIPTfor the linker script
Makefile: Prepare for using macros for inline asm
x86: objtool: use asm macro for better compiler decisions
x86: refcount: prevent gcc distortions
x86: alternatives: macrofy locks for better inlining
x86: bug: prevent gcc distortions
x86: prevent inline distortion by paravirt ops
x86: extable: use macros instead of inline assembly
x86: cpufeature: use macros instead of inline assembly
x86: jump-labels: use macros instead of inline assemblyMakefile | 9 ++- arch/x86/Makefile | 7 ++ arch/x86/entry/calling.h | 2 +- arch/x86/include/asm/alternative-asm.h | 20 ++++-- arch/x86/include/asm/alternative.h | 11 +-- arch/x86/include/asm/asm.h | 61 +++++++--------- arch/x86/include/asm/bug.h | 98 +++++++++++++++----------- arch/x86/include/asm/cpufeature.h | 82 ++++++++++++--------- arch/x86/include/asm/jump_label.h | 77 ++++++++------------ arch/x86/include/asm/paravirt_types.h | 56 +++++++-------- arch/x86/include/asm/refcount.h | 74 +++++++++++-------- arch/x86/kernel/macros.S | 16 +++++ arch/xtensa/kernel/Makefile | 4 +- include/asm-generic/bug.h | 8 +-- include/linux/compiler.h | 56 +++++++++++---- scripts/Kbuild.include | 4 +- scripts/mod/Makefile | 2 + 17 files changed, 331 insertions(+), 256 deletions(-) create mode 100644 arch/x86/kernel/macros.SSignature · 1 line
2.17.1
Signature · 4 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.