x86: use gcc 6+ asm flag output feature
Subsystems (5)
v2 cover x86: use gcc 6+ asm flag output feature
From: "H. Peter Anvin" <[email protected]>
gcc 6+ has the ability to let flags (actually, conditions, which are specific combinations of flags) to be used directly as asm() outputs. The syntax for that is "=@cc<cc>" where <cc> is the same set of letters that would be used in a j<cc> or set<cc> instruction (e.g. "=@ccz" to test the ZF flag.)
This patchset by itself reduces the size of the x86-64 kernel by 0.12%, from a baseline of 4.7-rc2 built with gcc 6.1 (first line is with the patchset, the second one is without):
text data bss dec hex filename
68245656 41004339 20533248 129783243 7bc55cb o.i386-allconfig/vmlinux 68355716 41008499 20533248 129897463 7be13f7 o.i386-allconfig/vmlinux
127384005 129742359 38150144 295276508 11998fdc o.x86_64-allconfig/vmlinux 127538765 129742295 38150144 295431204 119bec24 o.x86_64-allconfig/vmlinux
v2: fix a conflict between <linux/random.h> and <asm/archrandom.h>
discovered by Ingo Molnar. There are a few places in x86-specific code where we need all of <arch/archrandom.h> even when xCONFIG_ARCH_RANDOM is disabled, so <linux/random.h> does not suffice. Only the <asm/archrandom.h> patch has been changed; since it is a little bit different from the others I have moved it to the end.
PATCH v2 1/10 x86, bitops: remove use of "sbb" to return CF
From: "H. Peter Anvin" <[email protected]>
Use SETC instead of SBB to return the value of CF from assembly. Using SETcc enables uniformity with other flags-returning pieces of assembly code.
--- arch/x86/include/asm/bitops.h | 24 ++++++++++++------------ arch/x86/include/asm/percpu.h | 12 ++++++------ arch/x86/include/asm/signal.h | 6 +++--- arch/x86/include/asm/sync_bitops.h | 18 +++++++++--------- arch/x86/kernel/vm86_32.c | 5 +---- 5 files changed, 31 insertions(+), 34 deletions(-)
arch/x86/include/asm/bitops.h +12 -12
@@ -230,11 +230,11 @@ test_and_set_bit_lock(long nr, volatile unsigned long *addr)*/ static __always_inline int __test_and_set_bit(long nr, volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; asm("bts %2,%1\n\t" -"sbb %0,%0" - : "=r" (oldbit), ADDR +"setc %0" + : "=qm" (oldbit), ADDR :"Ir" (nr));return oldbit; }
@@ -270,11 +270,11 @@ static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *a*/ static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; asmvolatile ("btr %2,%1\n\t" -"sbb %0,%0" - : "=r" (oldbit), ADDR +"setc %0" + : "=qm" (oldbit), ADDR :"Ir" (nr));return oldbit; }
@@ -282,11 +282,11 @@ static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long/* WARNING: non atomic and it can be reordered! */ static __always_inline int __test_and_change_bit(long nr, volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; asmvolatile ("btc %2,%1\n\t" -"sbb %0,%0" - : "=r" (oldbit), ADDR +"setc %0" + : "=qm" (oldbit), ADDR :"Ir" (nr) :"memory" );return oldbit;
@@ -313,11 +313,11 @@ static __always_inline int constant_test_bit(long nr, const volatile unsigned lo static __always_inline int variable_test_bit(long nr, volatile const unsigned long *addr) { -int oldbit; +unsigned char oldbit; asmvolatile ("bt %2,%1\n\t" -"sbb %0,%0" - :"=r" (oldbit) +"setc %0" + :"=qm" (oldbit) :"m" (*(unsigned long *)addr),"Ir" (nr));return oldbit;
arch/x86/include/asm/percpu.h +6 -6
@@ -510,9 +510,9 @@ do { \/* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define x86_test_and_clear_bit_percpu (bit, var) \ ({ \ - int old__; \ - asm volatile("btr %2,"__percpu_arg(1)"\n\tsbbl %0,%0" \ - : "=r" (old__), "+m" (var) \ + unsigned char old__; \ + asm volatile("btr %2,"__percpu_arg(1)"\n\tsetc %0" \ + : "=qm" (old__), "+m" (var) \ : "dIr" (bit)); \ old__; \ })
@@ -532,11 +532,11 @@ static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,static inline int x86_this_cpu_variable_test_bit (int nr,const unsigned long __percpu *addr) { -int oldbit; +unsigned char oldbit; asm volatile("bt "__percpu_arg(2)",%1\n\t" - "sbb %0,%0" - : "=r" (oldbit) + "setc %0" + : "=qm" (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr));return oldbit;
arch/x86/include/asm/signal.h +3 -3
@@ -81,9 +81,9 @@ static inline int __const_sigismember(sigset_t *set, int _sig)static inline int __gen_sigismember (sigset_t *set,int _sig) { -int ret; - asm("btl %2,%1\n\tsbbl %0,%0" - :"=r" (ret) :"m" (*set),"Ir" (_sig-1 ) :"cc" ); +unsigned char ret; + asm("btl %2,%1\n\tsetc %0" + :"=qm" (ret) :"m" (*set),"Ir" (_sig-1 ) :"cc" );return ret; }
arch/x86/include/asm/sync_bitops.h +9 -9
@@ -79,10 +79,10 @@ static inline void sync_change_bit(long nr, volatile unsigned long *addr)*/ static inline int sync_test_and_set_bit (long nr,volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; - asmvolatile ("lock; bts %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (ADDR ) + asmvolatile ("lock; bts %2,%1\n\tsetc %0" + :"=qm" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit; }
@@ -97,10 +97,10 @@ static inline int sync_test_and_set_bit(long nr, volatile unsigned long *addr)*/ static inline int sync_test_and_clear_bit (long nr,volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; - asmvolatile ("lock; btr %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (ADDR ) + asmvolatile ("lock; btr %2,%1\n\tsetc %0" + :"=qm" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit; }
@@ -115,10 +115,10 @@ static inline int sync_test_and_clear_bit(long nr, volatile unsigned long *addr)*/ static inline int sync_test_and_change_bit (long nr,volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; - asmvolatile ("lock; btc %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (ADDR ) + asmvolatile ("lock; btc %2,%1\n\tsetc %0" + :"=qm" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit; }
arch/x86/kernel/vm86_32.c +1 -4
@@ -440,10 +440,7 @@ static inline unsigned long get_vflags(struct kernel_vm86_regs *regs)static inline int is_revectored (int nr,struct revectored_struct *bitmap) { - __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" - :"=r" (nr) - :"m" (*bitmap),"r" (nr)); -return nr; +return test_bit (nr, bitmap->__map); }#define val_byte (val, n) (((__u8 *)&val)[n])
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, bitops: remove use of "sbb" to return CF
x86, bitops: remove use of "sbb" to return CF
Commit-ID: 2823d4da5d8a0c222747b24eceb65f5b30717d02 Gitweb: http://git.kernel.org/tip/2823d4da5d8a0c222747b24eceb65f5b30717d02 Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:37 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, bitops: remove use of "sbb" to return CF
Use SETC instead of SBB to return the value of CF from assembly. Using SETcc enables uniformity with other flags-returning pieces of assembly code.
--- arch/x86/include/asm/bitops.h | 24 ++++++++++++------------ arch/x86/include/asm/percpu.h | 12 ++++++------ arch/x86/include/asm/signal.h | 6 +++--- arch/x86/include/asm/sync_bitops.h | 18 +++++++++--------- arch/x86/kernel/vm86_32.c | 5 +---- 5 files changed, 31 insertions(+), 34 deletions(-)
arch/x86/include/asm/bitops.h +12 -12
@@ -230,11 +230,11 @@ test_and_set_bit_lock(long nr, volatile unsigned long *addr)*/ static __always_inline int __test_and_set_bit(long nr, volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; asm("bts %2,%1\n\t" -"sbb %0,%0" - : "=r" (oldbit), ADDR +"setc %0" + : "=qm" (oldbit), ADDR :"Ir" (nr));return oldbit; }
@@ -270,11 +270,11 @@ static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *a*/ static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; asmvolatile ("btr %2,%1\n\t" -"sbb %0,%0" - : "=r" (oldbit), ADDR +"setc %0" + : "=qm" (oldbit), ADDR :"Ir" (nr));return oldbit; }
@@ -282,11 +282,11 @@ static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long/* WARNING: non atomic and it can be reordered! */ static __always_inline int __test_and_change_bit(long nr, volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; asmvolatile ("btc %2,%1\n\t" -"sbb %0,%0" - : "=r" (oldbit), ADDR +"setc %0" + : "=qm" (oldbit), ADDR :"Ir" (nr) :"memory" );return oldbit;
@@ -313,11 +313,11 @@ static __always_inline int constant_test_bit(long nr, const volatile unsigned lo static __always_inline int variable_test_bit(long nr, volatile const unsigned long *addr) { -int oldbit; +unsigned char oldbit; asmvolatile ("bt %2,%1\n\t" -"sbb %0,%0" - :"=r" (oldbit) +"setc %0" + :"=qm" (oldbit) :"m" (*(unsigned long *)addr),"Ir" (nr));return oldbit;
arch/x86/include/asm/percpu.h +6 -6
@@ -510,9 +510,9 @@ do { \/* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define x86_test_and_clear_bit_percpu (bit, var) \ ({ \ - int old__; \ - asm volatile("btr %2,"__percpu_arg(1)"\n\tsbbl %0,%0" \ - : "=r" (old__), "+m" (var) \ + unsigned char old__; \ + asm volatile("btr %2,"__percpu_arg(1)"\n\tsetc %0" \ + : "=qm" (old__), "+m" (var) \ : "dIr" (bit)); \ old__; \ })
@@ -532,11 +532,11 @@ static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,static inline int x86_this_cpu_variable_test_bit (int nr,const unsigned long __percpu *addr) { -int oldbit; +unsigned char oldbit; asm volatile("bt "__percpu_arg(2)",%1\n\t" - "sbb %0,%0" - : "=r" (oldbit) + "setc %0" + : "=qm" (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr));return oldbit;
arch/x86/include/asm/signal.h +3 -3
@@ -81,9 +81,9 @@ static inline int __const_sigismember(sigset_t *set, int _sig)static inline int __gen_sigismember (sigset_t *set,int _sig) { -int ret; - asm("btl %2,%1\n\tsbbl %0,%0" - :"=r" (ret) :"m" (*set),"Ir" (_sig-1 ) :"cc" ); +unsigned char ret; + asm("btl %2,%1\n\tsetc %0" + :"=qm" (ret) :"m" (*set),"Ir" (_sig-1 ) :"cc" );return ret; }
arch/x86/include/asm/sync_bitops.h +9 -9
@@ -79,10 +79,10 @@ static inline void sync_change_bit(long nr, volatile unsigned long *addr)*/ static inline int sync_test_and_set_bit (long nr,volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; - asmvolatile ("lock; bts %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (ADDR ) + asmvolatile ("lock; bts %2,%1\n\tsetc %0" + :"=qm" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit; }
@@ -97,10 +97,10 @@ static inline int sync_test_and_set_bit(long nr, volatile unsigned long *addr)*/ static inline int sync_test_and_clear_bit (long nr,volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; - asmvolatile ("lock; btr %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (ADDR ) + asmvolatile ("lock; btr %2,%1\n\tsetc %0" + :"=qm" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit; }
@@ -115,10 +115,10 @@ static inline int sync_test_and_clear_bit(long nr, volatile unsigned long *addr)*/ static inline int sync_test_and_change_bit (long nr,volatile unsigned long *addr) { -int oldbit; +unsigned char oldbit; - asmvolatile ("lock; btc %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (ADDR ) + asmvolatile ("lock; btc %2,%1\n\tsetc %0" + :"=qm" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit; }
arch/x86/kernel/vm86_32.c +1 -4
@@ -440,10 +440,7 @@ static inline unsigned long get_vflags(struct kernel_vm86_regs *regs)static inline int is_revectored (int nr,struct revectored_struct *bitmap) { - __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" - :"=r" (nr) - :"m" (*bitmap),"r" (nr)); -return nr; +return test_bit (nr, bitmap->__map); }#define val_byte (val, n) (((__u8 *)&val)[n])
PATCH v2 2/10 x86, asm: use bool for bitops and other assembly outputs
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
The gcc people have confirmed that using "bool" when combined with inline assembly always is treated as a byte-sized operand that can be assumed to be 0 or 1, which is exactly what the SET instruction emits. Change the output types and intermediate variables of as many operations as practical to "bool".
--- arch/x86/boot/bitops.h | 8 +++++--- arch/x86/boot/boot.h | 8 ++++---- arch/x86/boot/string.c | 2 +- arch/x86/include/asm/apm.h | 6 +++--- arch/x86/include/asm/archrandom.h | 16 ++++++++-------- arch/x86/include/asm/atomic.h | 8 ++++---- arch/x86/include/asm/atomic64_64.h | 10 +++++----- arch/x86/include/asm/bitops.h | 28 ++++++++++++++-------------- arch/x86/include/asm/local.h | 8 ++++---- arch/x86/include/asm/percpu.h | 8 ++++---- arch/x86/include/asm/rmwcc.h | 4 ++-- arch/x86/include/asm/rwsem.h | 17 +++++++++-------- include/linux/random.h | 12 ++++++------ 13 files changed, 69 insertions(+), 66 deletions(-)
arch/x86/boot/bitops.h +5 -3
@@ -16,14 +16,16 @@#define BOOT_BITOPS_H #define _LINUX_BITOPS_H/* Inhibit inclusion of <linux/bitops.h> */ -static inline int constant_test_bit (int nr,const void *addr) +#include <linux/types.h> + +static inline bool constant_test_bit (int nr,const void *addr) {const u32 *p = (const u32 *)addr;return ((1UL << (nr &31 )) & (p[nr >>5 ])) !=0 ; } -static inline int variable_test_bit (int nr,const void *addr) +static inline bool variable_test_bit (int nr,const void *addr) { -u8 v; +bool v;const u32 *p = (const u32 *)addr; asm("btl %2,%1; setc %0" :"=qm" (v) :"m" (*p),"Ir" (nr));
arch/x86/boot/boot.h +4 -4
@@ -176,16 +176,16 @@ static inline void wrgs32(u32 v, addr_t addr) }/* Note: these only return true/false, not a signed return value! */ -static inline int memcmp_fs (const void *s1,addr_t s2,size_t len) +static inline bool memcmp_fs (const void *s1,addr_t s2,size_t len) { -u8 diff; +bool diff; asmvolatile ("fs; repe; cmpsb; setnz %0" :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len));return diff; } -static inline int memcmp_gs (const void *s1,addr_t s2,size_t len) +static inline bool memcmp_gs (const void *s1,addr_t s2,size_t len) { -u8 diff; +bool diff; asmvolatile ("gs; repe; cmpsb; setnz %0" :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len));return diff;
arch/x86/boot/string.c +1 -1
@@ -17,7 +17,7 @@int memcmp (const void *s1,const void *s2,size_t len) { -u8 diff; +bool diff; asm("repe; cmpsb; setnz %0" :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len));return diff;
arch/x86/include/asm/apm.h +3 -3
@@ -45,11 +45,11 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, : "memory", "cc"); } -static inline u8 apm_bios_call_simple_asm (u32 func,u32 ebx_in, -u32 ecx_in,u32 *eax) +static inline bool apm_bios_call_simple_asm (u32 func,u32 ebx_in, +u32 ecx_in,u32 *eax) {int cx, dx, si; -u8 error; +bool error;/* * N.B. We do NOT need a cld after the BIOS call
arch/x86/include/asm/archrandom.h +8 -8
@@ -43,7 +43,7 @@#ifdef CONFIG_ARCH_RANDOM /* Instead of arch_get_random_long() when alternatives haven't run. */ -static inline int rdrand_long (unsigned long *v) +static inline bool rdrand_long (unsigned long *v) {int ok; asm volatile("1: " RDRAND_LONG "\n\t"
@@ -53,13 +53,13 @@ static inline int rdrand_long(unsigned long *v) "2:" : "=r" (ok), "=a" (*v) : "0" (RDRAND_RETRY_LOOPS)); -return ok; +return !!ok; }/* A single attempt at RDSEED */ static inline bool rdseed_long (unsigned long *v) { -unsigned char ok; +bool ok; asmvolatile (RDSEED_LONG "\n\t" "setc %0" :"=qm" (ok),"=a" (*v));
@@ -67,7 +67,7 @@ static inline bool rdseed_long(unsigned long *v) }#define GET_RANDOM (name, type, rdrand, nop) \ -static inline int name(type *v) \ +static inline bool name(type *v) \ { \ int ok; \ alternative_io("movl $0, %0\n\t" \
@@ -80,13 +80,13 @@ static inline int name(type *v) \X86_FEATURE_RDRAND , \ASM_OUTPUT2 ("=r" (ok),"=a" (*v)), \ "0" (RDRAND_RETRY_LOOPS)); \ -return ok; \ +return !!ok; \ }#define GET_SEED (name, type, rdseed, nop) \ -static inline int name(type *v) \ +static inline bool name(type *v) \ { \ - unsigned char ok; \ + bool ok; \ alternative_io("movb $0, %0\n\t" \ nop, \ rdseed "\n\t" \
@@ -119,7 +119,7 @@ GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);#else -static inline int rdrand_long (unsigned long *v) +static inline bool rdrand_long (unsigned long *v) {return 0 ; }
arch/x86/include/asm/atomic.h +4 -4
@@ -75,7 +75,7 @@ static __always_inline void atomic_sub(int i, atomic_t *v)* true if the result is zero, or false for all * other cases. */ -static __always_inline int atomic_sub_and_test(int i, atomic_t *v) +static __always_inline bool atomic_sub_and_test(int i, atomic_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "subl" , v->counter,"er" , i,"%0" ,"e" ); }
@@ -112,7 +112,7 @@ static __always_inline void atomic_dec(atomic_t *v)* returns true if the result is 0, or false for all other * cases. */ -static __always_inline int atomic_dec_and_test(atomic_t *v) +static __always_inline bool atomic_dec_and_test(atomic_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "decl" , v->counter,"%0" ,"e" ); }
@@ -125,7 +125,7 @@ static __always_inline int atomic_dec_and_test(atomic_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static __always_inline int atomic_inc_and_test(atomic_t *v) +static __always_inline bool atomic_inc_and_test(atomic_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "incl" , v->counter,"%0" ,"e" ); }
@@ -139,7 +139,7 @@ static __always_inline int atomic_inc_and_test(atomic_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static __always_inline int atomic_add_negative(int i, atomic_t *v) +static __always_inline bool atomic_add_negative(int i, atomic_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "addl" , v->counter,"er" , i,"%0" ,"s" ); }
arch/x86/include/asm/atomic64_64.h +5 -5
@@ -70,7 +70,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)* true if the result is zero, or false for all * other cases. */ -static inline int atomic64_sub_and_test (long i,atomic64_t *v) +static inline bool atomic64_sub_and_test (long i,atomic64_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "subq" , v->counter,"er" , i,"%0" ,"e" ); }
@@ -109,7 +109,7 @@ static __always_inline void atomic64_dec(atomic64_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline int atomic64_dec_and_test (atomic64_t *v) +static inline bool atomic64_dec_and_test (atomic64_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "decq" , v->counter,"%0" ,"e" ); }
@@ -122,7 +122,7 @@ static inline int atomic64_dec_and_test(atomic64_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline int atomic64_inc_and_test (atomic64_t *v) +static inline bool atomic64_inc_and_test (atomic64_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "incq" , v->counter,"%0" ,"e" ); }
@@ -136,7 +136,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline int atomic64_add_negative (long i,atomic64_t *v) +static inline bool atomic64_add_negative (long i,atomic64_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "addq" , v->counter,"er" , i,"%0" ,"s" ); }
@@ -180,7 +180,7 @@ static inline long atomic64_xchg(atomic64_t *v, long new)* Atomically adds @a to @v, so long as it was not @u. * Returns the old value of @v. */ -static inline int atomic64_add_unless (atomic64_t *v,long a,long u) +static inline bool atomic64_add_unless (atomic64_t *v,long a,long u) {long c, old; c =atomic64_read (v);
arch/x86/include/asm/bitops.h +14 -14
@@ -201,7 +201,7 @@ static __always_inline void change_bit(long nr, volatile unsigned long *addr)* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static __always_inline int test_and_set_bit(long nr, volatile unsigned long *addr) +static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) {GEN_BINARY_RMWcc (LOCK_PREFIX "bts" , *addr,"Ir" , nr,"%0" ,"c" ); }
@@ -213,7 +213,7 @@ static __always_inline int test_and_set_bit(long nr, volatile unsigned long *add* * This is the same as test_and_set_bit on x86. */ -static __always_inline int +static __always_inline booltest_and_set_bit_lock (long nr,volatile unsigned long *addr) {return test_and_set_bit (nr, addr);
@@ -228,9 +228,9 @@ test_and_set_bit_lock(long nr, volatile unsigned long *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 __always_inline int __test_and_set_bit(long nr, volatile unsigned long *addr) +static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asm("bts %2,%1\n\t" "setc %0"
@@ -247,7 +247,7 @@ static __always_inline int __test_and_set_bit(long nr, volatile unsigned long *a* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *addr) +static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr) {GEN_BINARY_RMWcc (LOCK_PREFIX "btr" , *addr,"Ir" , nr,"%0" ,"c" ); }
@@ -268,9 +268,9 @@ static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *a* accessed from a hypervisor on the same CPU if running in a VM: don't change * this without also updating arch/x86/kernel/kvm.c */ -static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long *addr) +static __always_inline bool __test_and_clear_bit(long nr, volatile unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asmvolatile ("btr %2,%1\n\t" "setc %0"
@@ -280,9 +280,9 @@ static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long }/* WARNING: non atomic and it can be reordered! */ -static __always_inline int __test_and_change_bit(long nr, volatile unsigned long *addr) +static __always_inline bool __test_and_change_bit(long nr, volatile unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asmvolatile ("btc %2,%1\n\t" "setc %0"
@@ -300,20 +300,20 @@ static __always_inline int __test_and_change_bit(long nr, volatile unsigned long* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static __always_inline int test_and_change_bit(long nr, volatile unsigned long *addr) +static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr) {GEN_BINARY_RMWcc (LOCK_PREFIX "btc" , *addr,"Ir" , nr,"%0" ,"c" ); } -static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) +static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr) {return ((1UL << (nr & (BITS_PER_LONG -1 ))) & (addr[nr >> _BITOPS_LONG_SHIFT])) !=0 ; } -static __always_inline int variable_test_bit(long nr, volatile const unsigned long *addr) +static __always_inline bool variable_test_bit(long nr, volatile const unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asmvolatile ("bt %2,%1\n\t" "setc %0"
@@ -329,7 +329,7 @@ static __always_inline int variable_test_bit(long nr, volatile const unsigned lo* @nr: bit number to test * @addr: Address to start counting from */ -static int test_bit (int nr,const volatile unsigned long *addr); +static bool test_bit (int nr,const volatile unsigned long *addr);#endif #define test_bit (nr, addr) \
arch/x86/include/asm/local.h +4 -4
@@ -50,7 +50,7 @@ static inline void local_sub(long i, local_t *l)* true if the result is zero, or false for all * other cases. */ -static inline int local_sub_and_test (long i,local_t *l) +static inline bool local_sub_and_test (long i,local_t *l) {GEN_BINARY_RMWcc (_ASM_SUB, l->a.counter,"er" , i,"%0" ,"e" ); }
@@ -63,7 +63,7 @@ static inline int local_sub_and_test(long i, local_t *l)* returns true if the result is 0, or false for all other * cases. */ -static inline int local_dec_and_test (local_t *l) +static inline bool local_dec_and_test (local_t *l) {GEN_UNARY_RMWcc (_ASM_DEC, l->a.counter,"%0" ,"e" ); }
@@ -76,7 +76,7 @@ static inline int local_dec_and_test(local_t *l)* and returns true if the result is zero, or false for all * other cases. */ -static inline int local_inc_and_test (local_t *l) +static inline bool local_inc_and_test (local_t *l) {GEN_UNARY_RMWcc (_ASM_INC, l->a.counter,"%0" ,"e" ); }
@@ -90,7 +90,7 @@ static inline int local_inc_and_test(local_t *l)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline int local_add_negative (long i,local_t *l) +static inline bool local_add_negative (long i,local_t *l) {GEN_BINARY_RMWcc (_ASM_ADD, l->a.counter,"er" , i,"%0" ,"s" ); }
arch/x86/include/asm/percpu.h +4 -4
@@ -510,14 +510,14 @@ do { \/* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define x86_test_and_clear_bit_percpu (bit, var) \ ({ \ - unsigned char old__; \ + bool old__; \ asm volatile("btr %2,"__percpu_arg(1)"\n\tsetc %0" \ : "=qm" (old__), "+m" (var) \ : "dIr" (bit)); \ old__; \ }) -static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr, +static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr,const unsigned long __percpu *addr) {unsigned long __percpu *a = (unsigned long *)addr + nr /BITS_PER_LONG ;
@@ -529,10 +529,10 @@ static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,#endif } -static inline int x86_this_cpu_variable_test_bit (int nr, +static inline bool x86_this_cpu_variable_test_bit (int nr,const unsigned long __percpu *addr) { -unsigned char oldbit; +bool oldbit; asm volatile("bt "__percpu_arg(2)",%1\n\t""setc %0"
arch/x86/include/asm/rmwcc.h +2 -2
@@ -23,11 +23,11 @@ cc_label: \#define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ - char c; \ + bool c; \ asm volatile (fullop "; set" cc " %1" \ : "+m" (var), "=qm" (c) \ : __VA_ARGS__ : "memory"); \ - return c != 0; \ + return c; \ } while (0)#define GEN_UNARY_RMWcc (op, var, arg0, cc) \
arch/x86/include/asm/rwsem.h +9 -8
@@ -77,7 +77,7 @@ static inline void __down_read(struct rw_semaphore *sem)/* * trylock for reading -- returns 1 if successful, 0 if contention */ -static inline int __down_read_trylock (struct rw_semaphore *sem) +static inline bool __down_read_trylock (struct rw_semaphore *sem) {long result, tmp; asm volatile("# beginning __down_read_trylock\n\t"
@@ -93,7 +93,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) : "+m" (sem->count), "=&a" (result), "=&r" (tmp) : "i" (RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); -return result >=0 ?1 :0 ; +return result >=0 ; }/*
@@ -134,9 +134,10 @@ static inline int __down_write_killable(struct rw_semaphore *sem)/* * trylock for writing -- returns 1 if successful, 0 if contention */ -static inline int __down_write_trylock (struct rw_semaphore *sem) +static inline bool __down_write_trylock (struct rw_semaphore *sem) { -long result, tmp; +bool result; +long tmp0, tmp1; asmvolatile ("# beginning __down_write_trylock\n\t" " mov %0,%1\n\t" "1:\n\t"
@@ -144,14 +145,14 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)/* was the active mask 0 before? */ " jnz 2f\n\t" " mov %1,%2\n\t" -" add %3,%2\n\t" +" add %4,%2\n\t" LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" "2:\n\t" -" sete %b1\n\t" -" movzbl %b1, %k1\n\t" +" sete %3\n\t" "# ending __down_write_trylock\n\t" - : "+m" (sem->count), "=&a" (result), "=&r" (tmp) + : "+m" (sem->count), "=&a" (tmp0), "=&r" (tmp1), + "=qm" (result) : "er" (RWSEM_ACTIVE_WRITE_BIAS) : "memory", "cc"); return result;
include/linux/random.h +6 -6
@@ -95,27 +95,27 @@ static inline void prandom_seed_state(struct rnd_state *state, u64 seed)#ifdef CONFIG_ARCH_RANDOM # include <asm/archrandom.h> #else -static inline int arch_get_random_long (unsigned long *v) +static inline bool arch_get_random_long (unsigned long *v) {return 0 ; } -static inline int arch_get_random_int (unsigned int *v) +static inline bool arch_get_random_int (unsigned int *v) {return 0 ; } -static inline int arch_has_random (void ) +static inline bool arch_has_random (void ) {return 0 ; } -static inline int arch_get_random_seed_long (unsigned long *v) +static inline bool arch_get_random_seed_long (unsigned long *v) {return 0 ; } -static inline int arch_get_random_seed_int (unsigned int *v) +static inline bool arch_get_random_seed_int (unsigned int *v) {return 0 ; } -static inline int arch_has_random_seed (void ) +static inline bool arch_has_random_seed (void ) {return 0 ; }
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: use bool for bitops and other assembly outputs
x86, asm: use bool for bitops and other assembly outputs
Commit-ID: 117780eef7740729e803bdcc0d5f2f48137ea8e3 Gitweb: http://git.kernel.org/tip/117780eef7740729e803bdcc0d5f2f48137ea8e3 Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:38 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: use bool for bitops and other assembly outputs
The gcc people have confirmed that using "bool" when combined with inline assembly always is treated as a byte-sized operand that can be assumed to be 0 or 1, which is exactly what the SET instruction emits. Change the output types and intermediate variables of as many operations as practical to "bool".
--- arch/x86/boot/bitops.h | 8 +++++--- arch/x86/boot/boot.h | 8 ++++---- arch/x86/boot/string.c | 2 +- arch/x86/include/asm/apm.h | 6 +++--- arch/x86/include/asm/archrandom.h | 16 ++++++++-------- arch/x86/include/asm/atomic.h | 8 ++++---- arch/x86/include/asm/atomic64_64.h | 10 +++++----- arch/x86/include/asm/bitops.h | 28 ++++++++++++++-------------- arch/x86/include/asm/local.h | 8 ++++---- arch/x86/include/asm/percpu.h | 8 ++++---- arch/x86/include/asm/rmwcc.h | 4 ++-- arch/x86/include/asm/rwsem.h | 17 +++++++++-------- include/linux/random.h | 12 ++++++------ 13 files changed, 69 insertions(+), 66 deletions(-)
arch/x86/boot/bitops.h +5 -3
@@ -16,14 +16,16 @@#define BOOT_BITOPS_H #define _LINUX_BITOPS_H/* Inhibit inclusion of <linux/bitops.h> */ -static inline int constant_test_bit (int nr,const void *addr) +#include <linux/types.h> + +static inline bool constant_test_bit (int nr,const void *addr) {const u32 *p = (const u32 *)addr;return ((1UL << (nr &31 )) & (p[nr >>5 ])) !=0 ; } -static inline int variable_test_bit (int nr,const void *addr) +static inline bool variable_test_bit (int nr,const void *addr) { -u8 v; +bool v;const u32 *p = (const u32 *)addr; asm("btl %2,%1; setc %0" :"=qm" (v) :"m" (*p),"Ir" (nr));
arch/x86/boot/boot.h +4 -4
@@ -176,16 +176,16 @@ static inline void wrgs32(u32 v, addr_t addr) }/* Note: these only return true/false, not a signed return value! */ -static inline int memcmp_fs (const void *s1,addr_t s2,size_t len) +static inline bool memcmp_fs (const void *s1,addr_t s2,size_t len) { -u8 diff; +bool diff; asmvolatile ("fs; repe; cmpsb; setnz %0" :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len));return diff; } -static inline int memcmp_gs (const void *s1,addr_t s2,size_t len) +static inline bool memcmp_gs (const void *s1,addr_t s2,size_t len) { -u8 diff; +bool diff; asmvolatile ("gs; repe; cmpsb; setnz %0" :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len));return diff;
arch/x86/boot/string.c +1 -1
@@ -17,7 +17,7 @@int memcmp (const void *s1,const void *s2,size_t len) { -u8 diff; +bool diff; asm("repe; cmpsb; setnz %0" :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len));return diff;
arch/x86/include/asm/apm.h +3 -3
@@ -45,11 +45,11 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, : "memory", "cc"); } -static inline u8 apm_bios_call_simple_asm (u32 func,u32 ebx_in, -u32 ecx_in,u32 *eax) +static inline bool apm_bios_call_simple_asm (u32 func,u32 ebx_in, +u32 ecx_in,u32 *eax) {int cx, dx, si; -u8 error; +bool error;/* * N.B. We do NOT need a cld after the BIOS call
arch/x86/include/asm/archrandom.h +8 -8
@@ -43,7 +43,7 @@#ifdef CONFIG_ARCH_RANDOM /* Instead of arch_get_random_long() when alternatives haven't run. */ -static inline int rdrand_long (unsigned long *v) +static inline bool rdrand_long (unsigned long *v) {int ok; asm volatile("1: " RDRAND_LONG "\n\t"
@@ -53,13 +53,13 @@ static inline int rdrand_long(unsigned long *v) "2:" : "=r" (ok), "=a" (*v) : "0" (RDRAND_RETRY_LOOPS)); -return ok; +return !!ok; }/* A single attempt at RDSEED */ static inline bool rdseed_long (unsigned long *v) { -unsigned char ok; +bool ok; asmvolatile (RDSEED_LONG "\n\t" "setc %0" :"=qm" (ok),"=a" (*v));
@@ -67,7 +67,7 @@ static inline bool rdseed_long(unsigned long *v) }#define GET_RANDOM (name, type, rdrand, nop) \ -static inline int name(type *v) \ +static inline bool name(type *v) \ { \ int ok; \ alternative_io("movl $0, %0\n\t" \
@@ -80,13 +80,13 @@ static inline int name(type *v) \X86_FEATURE_RDRAND , \ASM_OUTPUT2 ("=r" (ok),"=a" (*v)), \ "0" (RDRAND_RETRY_LOOPS)); \ -return ok; \ +return !!ok; \ }#define GET_SEED (name, type, rdseed, nop) \ -static inline int name(type *v) \ +static inline bool name(type *v) \ { \ - unsigned char ok; \ + bool ok; \ alternative_io("movb $0, %0\n\t" \ nop, \ rdseed "\n\t" \
@@ -119,7 +119,7 @@ GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);#else -static inline int rdrand_long (unsigned long *v) +static inline bool rdrand_long (unsigned long *v) {return 0 ; }
arch/x86/include/asm/atomic.h +4 -4
@@ -75,7 +75,7 @@ static __always_inline void atomic_sub(int i, atomic_t *v)* true if the result is zero, or false for all * other cases. */ -static __always_inline int atomic_sub_and_test(int i, atomic_t *v) +static __always_inline bool atomic_sub_and_test(int i, atomic_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "subl" , v->counter,"er" , i,"%0" ,"e" ); }
@@ -112,7 +112,7 @@ static __always_inline void atomic_dec(atomic_t *v)* returns true if the result is 0, or false for all other * cases. */ -static __always_inline int atomic_dec_and_test(atomic_t *v) +static __always_inline bool atomic_dec_and_test(atomic_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "decl" , v->counter,"%0" ,"e" ); }
@@ -125,7 +125,7 @@ static __always_inline int atomic_dec_and_test(atomic_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static __always_inline int atomic_inc_and_test(atomic_t *v) +static __always_inline bool atomic_inc_and_test(atomic_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "incl" , v->counter,"%0" ,"e" ); }
@@ -139,7 +139,7 @@ static __always_inline int atomic_inc_and_test(atomic_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static __always_inline int atomic_add_negative(int i, atomic_t *v) +static __always_inline bool atomic_add_negative(int i, atomic_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "addl" , v->counter,"er" , i,"%0" ,"s" ); }
arch/x86/include/asm/atomic64_64.h +5 -5
@@ -70,7 +70,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)* true if the result is zero, or false for all * other cases. */ -static inline int atomic64_sub_and_test (long i,atomic64_t *v) +static inline bool atomic64_sub_and_test (long i,atomic64_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "subq" , v->counter,"er" , i,"%0" ,"e" ); }
@@ -109,7 +109,7 @@ static __always_inline void atomic64_dec(atomic64_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline int atomic64_dec_and_test (atomic64_t *v) +static inline bool atomic64_dec_and_test (atomic64_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "decq" , v->counter,"%0" ,"e" ); }
@@ -122,7 +122,7 @@ static inline int atomic64_dec_and_test(atomic64_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline int atomic64_inc_and_test (atomic64_t *v) +static inline bool atomic64_inc_and_test (atomic64_t *v) {GEN_UNARY_RMWcc (LOCK_PREFIX "incq" , v->counter,"%0" ,"e" ); }
@@ -136,7 +136,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline int atomic64_add_negative (long i,atomic64_t *v) +static inline bool atomic64_add_negative (long i,atomic64_t *v) {GEN_BINARY_RMWcc (LOCK_PREFIX "addq" , v->counter,"er" , i,"%0" ,"s" ); }
@@ -180,7 +180,7 @@ static inline long atomic64_xchg(atomic64_t *v, long new)* Atomically adds @a to @v, so long as it was not @u. * Returns the old value of @v. */ -static inline int atomic64_add_unless (atomic64_t *v,long a,long u) +static inline bool atomic64_add_unless (atomic64_t *v,long a,long u) {long c, old; c =atomic64_read (v);
arch/x86/include/asm/bitops.h +14 -14
@@ -201,7 +201,7 @@ static __always_inline void change_bit(long nr, volatile unsigned long *addr)* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static __always_inline int test_and_set_bit(long nr, volatile unsigned long *addr) +static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) {GEN_BINARY_RMWcc (LOCK_PREFIX "bts" , *addr,"Ir" , nr,"%0" ,"c" ); }
@@ -213,7 +213,7 @@ static __always_inline int test_and_set_bit(long nr, volatile unsigned long *add* * This is the same as test_and_set_bit on x86. */ -static __always_inline int +static __always_inline booltest_and_set_bit_lock (long nr,volatile unsigned long *addr) {return test_and_set_bit (nr, addr);
@@ -228,9 +228,9 @@ test_and_set_bit_lock(long nr, volatile unsigned long *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 __always_inline int __test_and_set_bit(long nr, volatile unsigned long *addr) +static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asm("bts %2,%1\n\t" "setc %0"
@@ -247,7 +247,7 @@ static __always_inline int __test_and_set_bit(long nr, volatile unsigned long *a* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *addr) +static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr) {GEN_BINARY_RMWcc (LOCK_PREFIX "btr" , *addr,"Ir" , nr,"%0" ,"c" ); }
@@ -268,9 +268,9 @@ static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *a* accessed from a hypervisor on the same CPU if running in a VM: don't change * this without also updating arch/x86/kernel/kvm.c */ -static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long *addr) +static __always_inline bool __test_and_clear_bit(long nr, volatile unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asmvolatile ("btr %2,%1\n\t" "setc %0"
@@ -280,9 +280,9 @@ static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long }/* WARNING: non atomic and it can be reordered! */ -static __always_inline int __test_and_change_bit(long nr, volatile unsigned long *addr) +static __always_inline bool __test_and_change_bit(long nr, volatile unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asmvolatile ("btc %2,%1\n\t" "setc %0"
@@ -300,20 +300,20 @@ static __always_inline int __test_and_change_bit(long nr, volatile unsigned long* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static __always_inline int test_and_change_bit(long nr, volatile unsigned long *addr) +static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr) {GEN_BINARY_RMWcc (LOCK_PREFIX "btc" , *addr,"Ir" , nr,"%0" ,"c" ); } -static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) +static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr) {return ((1UL << (nr & (BITS_PER_LONG -1 ))) & (addr[nr >> _BITOPS_LONG_SHIFT])) !=0 ; } -static __always_inline int variable_test_bit(long nr, volatile const unsigned long *addr) +static __always_inline bool variable_test_bit(long nr, volatile const unsigned long *addr) { -unsigned char oldbit; +bool oldbit; asmvolatile ("bt %2,%1\n\t" "setc %0"
@@ -329,7 +329,7 @@ static __always_inline int variable_test_bit(long nr, volatile const unsigned lo* @nr: bit number to test * @addr: Address to start counting from */ -static int test_bit (int nr,const volatile unsigned long *addr); +static bool test_bit (int nr,const volatile unsigned long *addr);#endif #define test_bit (nr, addr) \
arch/x86/include/asm/local.h +4 -4
@@ -50,7 +50,7 @@ static inline void local_sub(long i, local_t *l)* true if the result is zero, or false for all * other cases. */ -static inline int local_sub_and_test (long i,local_t *l) +static inline bool local_sub_and_test (long i,local_t *l) {GEN_BINARY_RMWcc (_ASM_SUB, l->a.counter,"er" , i,"%0" ,"e" ); }
@@ -63,7 +63,7 @@ static inline int local_sub_and_test(long i, local_t *l)* returns true if the result is 0, or false for all other * cases. */ -static inline int local_dec_and_test (local_t *l) +static inline bool local_dec_and_test (local_t *l) {GEN_UNARY_RMWcc (_ASM_DEC, l->a.counter,"%0" ,"e" ); }
@@ -76,7 +76,7 @@ static inline int local_dec_and_test(local_t *l)* and returns true if the result is zero, or false for all * other cases. */ -static inline int local_inc_and_test (local_t *l) +static inline bool local_inc_and_test (local_t *l) {GEN_UNARY_RMWcc (_ASM_INC, l->a.counter,"%0" ,"e" ); }
@@ -90,7 +90,7 @@ static inline int local_inc_and_test(local_t *l)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline int local_add_negative (long i,local_t *l) +static inline bool local_add_negative (long i,local_t *l) {GEN_BINARY_RMWcc (_ASM_ADD, l->a.counter,"er" , i,"%0" ,"s" ); }
arch/x86/include/asm/percpu.h +4 -4
@@ -510,14 +510,14 @@ do { \/* This is not atomic against other CPUs -- CPU preemption needs to be off */ #define x86_test_and_clear_bit_percpu (bit, var) \ ({ \ - unsigned char old__; \ + bool old__; \ asm volatile("btr %2,"__percpu_arg(1)"\n\tsetc %0" \ : "=qm" (old__), "+m" (var) \ : "dIr" (bit)); \ old__; \ }) -static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr, +static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr,const unsigned long __percpu *addr) {unsigned long __percpu *a = (unsigned long *)addr + nr /BITS_PER_LONG ;
@@ -529,10 +529,10 @@ static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,#endif } -static inline int x86_this_cpu_variable_test_bit (int nr, +static inline bool x86_this_cpu_variable_test_bit (int nr,const unsigned long __percpu *addr) { -unsigned char oldbit; +bool oldbit; asm volatile("bt "__percpu_arg(2)",%1\n\t""setc %0"
arch/x86/include/asm/rmwcc.h +2 -2
@@ -23,11 +23,11 @@ cc_label: \#define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ - char c; \ + bool c; \ asm volatile (fullop "; set" cc " %1" \ : "+m" (var), "=qm" (c) \ : __VA_ARGS__ : "memory"); \ - return c != 0; \ + return c; \ } while (0)#define GEN_UNARY_RMWcc (op, var, arg0, cc) \
arch/x86/include/asm/rwsem.h +9 -8
@@ -77,7 +77,7 @@ static inline void __down_read(struct rw_semaphore *sem)/* * trylock for reading -- returns 1 if successful, 0 if contention */ -static inline int __down_read_trylock (struct rw_semaphore *sem) +static inline bool __down_read_trylock (struct rw_semaphore *sem) {long result, tmp; asm volatile("# beginning __down_read_trylock\n\t"
@@ -93,7 +93,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) : "+m" (sem->count), "=&a" (result), "=&r" (tmp) : "i" (RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); -return result >=0 ?1 :0 ; +return result >=0 ; }/*
@@ -134,9 +134,10 @@ static inline int __down_write_killable(struct rw_semaphore *sem)/* * trylock for writing -- returns 1 if successful, 0 if contention */ -static inline int __down_write_trylock (struct rw_semaphore *sem) +static inline bool __down_write_trylock (struct rw_semaphore *sem) { -long result, tmp; +bool result; +long tmp0, tmp1; asmvolatile ("# beginning __down_write_trylock\n\t" " mov %0,%1\n\t" "1:\n\t"
@@ -144,14 +145,14 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)/* was the active mask 0 before? */ " jnz 2f\n\t" " mov %1,%2\n\t" -" add %3,%2\n\t" +" add %4,%2\n\t" LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" "2:\n\t" -" sete %b1\n\t" -" movzbl %b1, %k1\n\t" +" sete %3\n\t" "# ending __down_write_trylock\n\t" - : "+m" (sem->count), "=&a" (result), "=&r" (tmp) + : "+m" (sem->count), "=&a" (tmp0), "=&r" (tmp1), + "=qm" (result) : "er" (RWSEM_ACTIVE_WRITE_BIAS) : "memory", "cc"); return result;
include/linux/random.h +6 -6
@@ -95,27 +95,27 @@ static inline void prandom_seed_state(struct rnd_state *state, u64 seed)#ifdef CONFIG_ARCH_RANDOM # include <asm/archrandom.h> #else -static inline int arch_get_random_long (unsigned long *v) +static inline bool arch_get_random_long (unsigned long *v) {return 0 ; } -static inline int arch_get_random_int (unsigned int *v) +static inline bool arch_get_random_int (unsigned int *v) {return 0 ; } -static inline int arch_has_random (void ) +static inline bool arch_has_random (void ) {return 0 ; } -static inline int arch_get_random_seed_long (unsigned long *v) +static inline bool arch_get_random_seed_long (unsigned long *v) {return 0 ; } -static inline int arch_get_random_seed_int (unsigned int *v) +static inline bool arch_get_random_seed_int (unsigned int *v) {return 0 ; } -static inline int arch_has_random_seed (void ) +static inline bool arch_has_random_seed (void ) {return 0 ; }
PATCH v2 3/10 x86, asm: change the GEN_*_RMWcc() macros to not quote the condition
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
Change the lexical defintion of the GEN_*_RMWcc() macros to not take the condition code as a quoted string. This will help support changing them to use the new __GCC_ASM_FLAG_OUTPUTS__ feature in a subsequent patch.
--- arch/x86/include/asm/atomic.h | 8 ++++---- arch/x86/include/asm/atomic64_64.h | 8 ++++---- arch/x86/include/asm/bitops.h | 6 +++--- arch/x86/include/asm/local.h | 8 ++++---- arch/x86/include/asm/preempt.h | 2 +- arch/x86/include/asm/rmwcc.h | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/include/asm/atomic.h +4 -4
@@ -77,7 +77,7 @@ static __always_inline void atomic_sub(int i, atomic_t *v)*/ static __always_inline bool atomic_sub_and_test(int i, atomic_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "subl" , v->counter,"er" , i,"%0" ,"e" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "subl" , v->counter,"er" , i,"%0" , e); }/**
@@ -114,7 +114,7 @@ static __always_inline void atomic_dec(atomic_t *v)*/ static __always_inline bool atomic_dec_and_test(atomic_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "decl" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "decl" , v->counter,"%0" , e); }/**
@@ -127,7 +127,7 @@ static __always_inline bool atomic_dec_and_test(atomic_t *v)*/ static __always_inline bool atomic_inc_and_test(atomic_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "incl" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "incl" , v->counter,"%0" , e); }/**
@@ -141,7 +141,7 @@ static __always_inline bool atomic_inc_and_test(atomic_t *v)*/ static __always_inline bool atomic_add_negative(int i, atomic_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "addl" , v->counter,"er" , i,"%0" ,"s" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "addl" , v->counter,"er" , i,"%0" , s); }/**
arch/x86/include/asm/atomic64_64.h +4 -4
@@ -72,7 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)*/ static inline bool atomic64_sub_and_test (long i,atomic64_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "subq" , v->counter,"er" , i,"%0" ,"e" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "subq" , v->counter,"er" , i,"%0" , e); }/**
@@ -111,7 +111,7 @@ static __always_inline void atomic64_dec(atomic64_t *v)*/ static inline bool atomic64_dec_and_test (atomic64_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "decq" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "decq" , v->counter,"%0" , e); }/**
@@ -124,7 +124,7 @@ static inline bool atomic64_dec_and_test(atomic64_t *v)*/ static inline bool atomic64_inc_and_test (atomic64_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "incq" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "incq" , v->counter,"%0" , e); }/**
@@ -138,7 +138,7 @@ static inline bool atomic64_inc_and_test(atomic64_t *v)*/ static inline bool atomic64_add_negative (long i,atomic64_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "addq" , v->counter,"er" , i,"%0" ,"s" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "addq" , v->counter,"er" , i,"%0" , s); }/**
arch/x86/include/asm/bitops.h +3 -3
@@ -203,7 +203,7 @@ static __always_inline void change_bit(long nr, volatile unsigned long *addr)*/ static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) { -GEN_BINARY_RMWcc (LOCK_PREFIX "bts" , *addr,"Ir" , nr,"%0" ,"c" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "bts" , *addr,"Ir" , nr,"%0" , c); }/**
@@ -249,7 +249,7 @@ static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long **/ static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr) { -GEN_BINARY_RMWcc (LOCK_PREFIX "btr" , *addr,"Ir" , nr,"%0" ,"c" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "btr" , *addr,"Ir" , nr,"%0" , c); }/**
@@ -302,7 +302,7 @@ static __always_inline bool __test_and_change_bit(long nr, volatile unsigned lon*/ static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr) { -GEN_BINARY_RMWcc (LOCK_PREFIX "btc" , *addr,"Ir" , nr,"%0" ,"c" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "btc" , *addr,"Ir" , nr,"%0" , c); } static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr)
arch/x86/include/asm/local.h +4 -4
@@ -52,7 +52,7 @@ static inline void local_sub(long i, local_t *l)*/ static inline bool local_sub_and_test (long i,local_t *l) { -GEN_BINARY_RMWcc (_ASM_SUB, l->a.counter,"er" , i,"%0" ,"e" ); +GEN_BINARY_RMWcc (_ASM_SUB, l->a.counter,"er" , i,"%0" , e); }/**
@@ -65,7 +65,7 @@ static inline bool local_sub_and_test(long i, local_t *l)*/ static inline bool local_dec_and_test (local_t *l) { -GEN_UNARY_RMWcc (_ASM_DEC, l->a.counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (_ASM_DEC, l->a.counter,"%0" , e); }/**
@@ -78,7 +78,7 @@ static inline bool local_dec_and_test(local_t *l)*/ static inline bool local_inc_and_test (local_t *l) { -GEN_UNARY_RMWcc (_ASM_INC, l->a.counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (_ASM_INC, l->a.counter,"%0" , e); }/**
@@ -92,7 +92,7 @@ static inline bool local_inc_and_test(local_t *l)*/ static inline bool local_add_negative (long i,local_t *l) { -GEN_BINARY_RMWcc (_ASM_ADD, l->a.counter,"er" , i,"%0" ,"s" ); +GEN_BINARY_RMWcc (_ASM_ADD, l->a.counter,"er" , i,"%0" , s); }/**
arch/x86/include/asm/preempt.h +1 -1
@@ -81,7 +81,7 @@ static __always_inline void __preempt_count_sub(int val)*/ static __always_inline bool __preempt_count_dec_and_test(void) { -GEN_UNARY_RMWcc ("decl" , __preempt_count,__percpu_arg (0 ),"e" ); +GEN_UNARY_RMWcc ("decl" , __preempt_count,__percpu_arg (0 ), e); }/*
arch/x86/include/asm/rmwcc.h +2 -2
@@ -5,7 +5,7 @@#define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ - asm_volatile_goto (fullop "; j" cc " %l[cc_label]" \ + asm_volatile_goto (fullop "; j" #cc " %l[cc_label]" \ : : "m" (var), ## __VA_ARGS__ \ : "memory" : cc_label); \ return 0; \
@@ -24,7 +24,7 @@ cc_label: \#define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ bool c; \ - asm volatile (fullop "; set" cc " %1" \ + asm volatile (fullop "; set" #cc " %1" \ : "+m" (var), "=qm" (c) \ : __VA_ARGS__ : "memory"); \ return c; \
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: change the GEN_*_RMWcc() macros to not quote the condition
x86, asm: change the GEN_*_RMWcc() macros to not quote the condition
Commit-ID: 18fe58229d80c7f4f138a07e84ba608e1ebd232b Gitweb: http://git.kernel.org/tip/18fe58229d80c7f4f138a07e84ba608e1ebd232b Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:39 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: change the GEN_*_RMWcc() macros to not quote the condition
Change the lexical defintion of the GEN_*_RMWcc() macros to not take the condition code as a quoted string. This will help support changing them to use the new __GCC_ASM_FLAG_OUTPUTS__ feature in a subsequent patch.
--- arch/x86/include/asm/atomic.h | 8 ++++---- arch/x86/include/asm/atomic64_64.h | 8 ++++---- arch/x86/include/asm/bitops.h | 6 +++--- arch/x86/include/asm/local.h | 8 ++++---- arch/x86/include/asm/preempt.h | 2 +- arch/x86/include/asm/rmwcc.h | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/include/asm/atomic.h +4 -4
@@ -77,7 +77,7 @@ static __always_inline void atomic_sub(int i, atomic_t *v)*/ static __always_inline bool atomic_sub_and_test(int i, atomic_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "subl" , v->counter,"er" , i,"%0" ,"e" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "subl" , v->counter,"er" , i,"%0" , e); }/**
@@ -114,7 +114,7 @@ static __always_inline void atomic_dec(atomic_t *v)*/ static __always_inline bool atomic_dec_and_test(atomic_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "decl" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "decl" , v->counter,"%0" , e); }/**
@@ -127,7 +127,7 @@ static __always_inline bool atomic_dec_and_test(atomic_t *v)*/ static __always_inline bool atomic_inc_and_test(atomic_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "incl" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "incl" , v->counter,"%0" , e); }/**
@@ -141,7 +141,7 @@ static __always_inline bool atomic_inc_and_test(atomic_t *v)*/ static __always_inline bool atomic_add_negative(int i, atomic_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "addl" , v->counter,"er" , i,"%0" ,"s" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "addl" , v->counter,"er" , i,"%0" , s); }/**
arch/x86/include/asm/atomic64_64.h +4 -4
@@ -72,7 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)*/ static inline bool atomic64_sub_and_test (long i,atomic64_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "subq" , v->counter,"er" , i,"%0" ,"e" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "subq" , v->counter,"er" , i,"%0" , e); }/**
@@ -111,7 +111,7 @@ static __always_inline void atomic64_dec(atomic64_t *v)*/ static inline bool atomic64_dec_and_test (atomic64_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "decq" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "decq" , v->counter,"%0" , e); }/**
@@ -124,7 +124,7 @@ static inline bool atomic64_dec_and_test(atomic64_t *v)*/ static inline bool atomic64_inc_and_test (atomic64_t *v) { -GEN_UNARY_RMWcc (LOCK_PREFIX "incq" , v->counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (LOCK_PREFIX "incq" , v->counter,"%0" , e); }/**
@@ -138,7 +138,7 @@ static inline bool atomic64_inc_and_test(atomic64_t *v)*/ static inline bool atomic64_add_negative (long i,atomic64_t *v) { -GEN_BINARY_RMWcc (LOCK_PREFIX "addq" , v->counter,"er" , i,"%0" ,"s" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "addq" , v->counter,"er" , i,"%0" , s); }/**
arch/x86/include/asm/bitops.h +3 -3
@@ -203,7 +203,7 @@ static __always_inline void change_bit(long nr, volatile unsigned long *addr)*/ static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) { -GEN_BINARY_RMWcc (LOCK_PREFIX "bts" , *addr,"Ir" , nr,"%0" ,"c" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "bts" , *addr,"Ir" , nr,"%0" , c); }/**
@@ -249,7 +249,7 @@ static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long **/ static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr) { -GEN_BINARY_RMWcc (LOCK_PREFIX "btr" , *addr,"Ir" , nr,"%0" ,"c" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "btr" , *addr,"Ir" , nr,"%0" , c); }/**
@@ -302,7 +302,7 @@ static __always_inline bool __test_and_change_bit(long nr, volatile unsigned lon*/ static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr) { -GEN_BINARY_RMWcc (LOCK_PREFIX "btc" , *addr,"Ir" , nr,"%0" ,"c" ); +GEN_BINARY_RMWcc (LOCK_PREFIX "btc" , *addr,"Ir" , nr,"%0" , c); } static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr)
arch/x86/include/asm/local.h +4 -4
@@ -52,7 +52,7 @@ static inline void local_sub(long i, local_t *l)*/ static inline bool local_sub_and_test (long i,local_t *l) { -GEN_BINARY_RMWcc (_ASM_SUB, l->a.counter,"er" , i,"%0" ,"e" ); +GEN_BINARY_RMWcc (_ASM_SUB, l->a.counter,"er" , i,"%0" , e); }/**
@@ -65,7 +65,7 @@ static inline bool local_sub_and_test(long i, local_t *l)*/ static inline bool local_dec_and_test (local_t *l) { -GEN_UNARY_RMWcc (_ASM_DEC, l->a.counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (_ASM_DEC, l->a.counter,"%0" , e); }/**
@@ -78,7 +78,7 @@ static inline bool local_dec_and_test(local_t *l)*/ static inline bool local_inc_and_test (local_t *l) { -GEN_UNARY_RMWcc (_ASM_INC, l->a.counter,"%0" ,"e" ); +GEN_UNARY_RMWcc (_ASM_INC, l->a.counter,"%0" , e); }/**
@@ -92,7 +92,7 @@ static inline bool local_inc_and_test(local_t *l)*/ static inline bool local_add_negative (long i,local_t *l) { -GEN_BINARY_RMWcc (_ASM_ADD, l->a.counter,"er" , i,"%0" ,"s" ); +GEN_BINARY_RMWcc (_ASM_ADD, l->a.counter,"er" , i,"%0" , s); }/**
arch/x86/include/asm/preempt.h +1 -1
@@ -81,7 +81,7 @@ static __always_inline void __preempt_count_sub(int val)*/ static __always_inline bool __preempt_count_dec_and_test(void) { -GEN_UNARY_RMWcc ("decl" , __preempt_count,__percpu_arg (0 ),"e" ); +GEN_UNARY_RMWcc ("decl" , __preempt_count,__percpu_arg (0 ), e); }/*
arch/x86/include/asm/rmwcc.h +2 -2
@@ -5,7 +5,7 @@#define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ - asm_volatile_goto (fullop "; j" cc " %l[cc_label]" \ + asm_volatile_goto (fullop "; j" #cc " %l[cc_label]" \ : : "m" (var), ## __VA_ARGS__ \ : "memory" : cc_label); \ return 0; \
@@ -24,7 +24,7 @@ cc_label: \#define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ bool c; \ - asm volatile (fullop "; set" cc " %1" \ + asm volatile (fullop "; set" #cc " %1" \ : "+m" (var), "=qm" (c) \ : __VA_ARGS__ : "memory"); \ return c; \
PATCH v2 4/10 x86, asm: define CC_SET() and CC_OUT() macros
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
The CC_SET() and CC_OUT() macros can be used together to take advantage of the new __GCC_ASM_FLAG_OUTPUTS__ feature in gcc 6+ while remaining backwards compatible. CC_SET() generates a SET instruction on older compilers; CC_OUT() makes sure the output is received in the correct variable.
--- arch/x86/include/asm/asm.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/x86/include/asm/asm.h +12 -0
@@ -42,6 +42,18 @@#define _ASM_SI __ASM_REG(si)#define _ASM_DI __ASM_REG(di) +/* +* Macros to generate condition code outputs from inline assembly, +* The output operand must be type "bool". +*/ +#ifdef __GCC_ASM_FLAG_OUTPUTS__ +# define CC_SET(c) "\n\t/* output condition code " #c "*/\n" +# define CC_OUT (c) "=@cc" #c +#else +# define CC_SET (c) "\n\tset" #c " %[_cc_" #c "]\n" +# define CC_OUT (c) [_cc_ ## c] "=qm" +#endif +/* Exception table entry */ #ifdef __ASSEMBLY__# define _ASM_EXTABLE_HANDLE (from, to, handler) \
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: define CC_SET() and CC_OUT() macros
x86, asm: define CC_SET() and CC_OUT() macros
Commit-ID: ff3554b409b82d349f71e9d7082648b7b0a1a5bb Gitweb: http://git.kernel.org/tip/ff3554b409b82d349f71e9d7082648b7b0a1a5bb Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:40 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: define CC_SET() and CC_OUT() macros
The CC_SET() and CC_OUT() macros can be used together to take advantage of the new __GCC_ASM_FLAG_OUTPUTS__ feature in gcc 6+ while remaining backwards compatible. CC_SET() generates a SET instruction on older compilers; CC_OUT() makes sure the output is received in the correct variable.
--- arch/x86/include/asm/asm.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/x86/include/asm/asm.h +12 -0
@@ -42,6 +42,18 @@#define _ASM_SI __ASM_REG(si)#define _ASM_DI __ASM_REG(di) +/* +* Macros to generate condition code outputs from inline assembly, +* The output operand must be type "bool". +*/ +#ifdef __GCC_ASM_FLAG_OUTPUTS__ +# define CC_SET(c) "\n\t/* output condition code " #c "*/\n" +# define CC_OUT (c) "=@cc" #c +#else +# define CC_SET (c) "\n\tset" #c " %[_cc_" #c "]\n" +# define CC_OUT (c) [_cc_ ## c] "=qm" +#endif +/* Exception table entry */ #ifdef __ASSEMBLY__# define _ASM_EXTABLE_HANDLE (from, to, handler) \
PATCH v2 5/10 x86, asm: change GEN_*_RMWcc() to use CC_SET()/CC_OUT()
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
Change the GEN_*_RMWcc() macros to use the CC_SET()/CC_OUT() macros defined in <asm/asm.h>, and disable the use of asm goto if __GCC_ASM_FLAG_OUTPUTS__ is enabled. This allows gcc to receive the flags output directly in gcc 6+.
--- arch/x86/include/asm/rmwcc.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
arch/x86/include/asm/rmwcc.h +9 -5
@@ -1,7 +1,9 @@#ifndef _ASM_X86_RMWcc#define _ASM_X86_RMWcc -#ifdef CC_HAVE_ASM_GOTO +#if !defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(CC_HAVE_ASM_GOTO ) + +/* Use asm goto */ #define __GEN_RMWcc (fullop, var, cc, ...) \ do { \
@@ -19,13 +21,15 @@ cc_label: \#define GEN_BINARY_RMWcc (op, var, vcon, val, arg0, cc) \ __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val)) -#else /* !CC_HAVE_ASM_GOTO */ +#else /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */ + +/* Use flags output or a set instruction */ #define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ bool c; \ - asm volatile (fullop "; set" #cc " %1" \ - : "+m" (var), "=qm" (c) \ + asm volatile (fullop ";" CC_SET(cc) \ + : "+m" (var), CC_OUT(cc) (c) \ : __VA_ARGS__ : "memory"); \ return c; \ } while (0)
@@ -36,6 +40,6 @@ do { \#define GEN_BINARY_RMWcc (op, var, vcon, val, arg0, cc) \ __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val)) -#endif /* CC_HAVE_ASM_GOTO */ +#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */ #endif /* _ASM_X86_RMWcc */
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: change GEN_*_RMWcc() to use CC_SET()/CC_OUT()
x86, asm: change GEN_*_RMWcc() to use CC_SET()/CC_OUT()
Commit-ID: ba741e356c49bfce0adcfa851080666870867f6b Gitweb: http://git.kernel.org/tip/ba741e356c49bfce0adcfa851080666870867f6b Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:41 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: change GEN_*_RMWcc() to use CC_SET()/CC_OUT()
Change the GEN_*_RMWcc() macros to use the CC_SET()/CC_OUT() macros defined in <asm/asm.h>, and disable the use of asm goto if __GCC_ASM_FLAG_OUTPUTS__ is enabled. This allows gcc to receive the flags output directly in gcc 6+.
--- arch/x86/include/asm/rmwcc.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
arch/x86/include/asm/rmwcc.h +9 -5
@@ -1,7 +1,9 @@#ifndef _ASM_X86_RMWcc#define _ASM_X86_RMWcc -#ifdef CC_HAVE_ASM_GOTO +#if !defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(CC_HAVE_ASM_GOTO ) + +/* Use asm goto */ #define __GEN_RMWcc (fullop, var, cc, ...) \ do { \
@@ -19,13 +21,15 @@ cc_label: \#define GEN_BINARY_RMWcc (op, var, vcon, val, arg0, cc) \ __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val)) -#else /* !CC_HAVE_ASM_GOTO */ +#else /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */ + +/* Use flags output or a set instruction */ #define __GEN_RMWcc (fullop, var, cc, ...) \ do { \ bool c; \ - asm volatile (fullop "; set" #cc " %1" \ - : "+m" (var), "=qm" (c) \ + asm volatile (fullop ";" CC_SET(cc) \ + : "+m" (var), CC_OUT(cc) (c) \ : __VA_ARGS__ : "memory"); \ return c; \ } while (0)
@@ -36,6 +40,6 @@ do { \#define GEN_BINARY_RMWcc (op, var, vcon, val, arg0, cc) \ __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val)) -#endif /* CC_HAVE_ASM_GOTO */ +#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */ #endif /* _ASM_X86_RMWcc */
PATCH v2 6/10 x86, asm: Use CC_SET()/CC_OUT() in <asm/bitops.h>
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in <asm/bitops.h>.
--- arch/x86/include/asm/bitops.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/x86/include/asm/bitops.h +8 -8
@@ -233,8 +233,8 @@ static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long *bool oldbit; asm("bts %2,%1\n\t" -"setc %0" - : "=qm" (oldbit), ADDR + CC_SET(c) + : CC_OUT(c) (oldbit), ADDR : "Ir" (nr));return oldbit; }
@@ -273,8 +273,8 @@ static __always_inline bool __test_and_clear_bit(long nr, volatile unsigned longbool oldbit; asm volatile("btr %2,%1\n\t" -"setc %0" - : "=qm" (oldbit), ADDR + CC_SET(c) + : CC_OUT(c) (oldbit), ADDR : "Ir" (nr));return oldbit; }
@@ -285,8 +285,8 @@ static __always_inline bool __test_and_change_bit(long nr, volatile unsigned lonbool oldbit; asm volatile("btc %2,%1\n\t" -"setc %0" - : "=qm" (oldbit), ADDR + CC_SET(c) + : CC_OUT(c) (oldbit), ADDR : "Ir" (nr) : "memory");return oldbit;
@@ -316,8 +316,8 @@ static __always_inline bool variable_test_bit(long nr, volatile const unsigned lbool oldbit; asm volatile("bt %2,%1\n\t" -"setc %0" - :"=qm" (oldbit) + CC_SET(c) + : CC_OUT(c) (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr));return oldbit;
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: Use CC_SET()/CC_OUT() in <asm/bitops.h>
x86, asm: Use CC_SET()/CC_OUT() in <asm/bitops.h>
Commit-ID: 86b61240d4c233b440cd29daf0baa440daf4a148 Gitweb: http://git.kernel.org/tip/86b61240d4c233b440cd29daf0baa440daf4a148 Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:42 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: Use CC_SET()/CC_OUT() in <asm/bitops.h>
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in <asm/bitops.h>.
--- arch/x86/include/asm/bitops.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/x86/include/asm/bitops.h +8 -8
@@ -233,8 +233,8 @@ static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long *bool oldbit; asm("bts %2,%1\n\t" -"setc %0" - : "=qm" (oldbit), ADDR + CC_SET(c) + : CC_OUT(c) (oldbit), ADDR : "Ir" (nr));return oldbit; }
@@ -273,8 +273,8 @@ static __always_inline bool __test_and_clear_bit(long nr, volatile unsigned longbool oldbit; asm volatile("btr %2,%1\n\t" -"setc %0" - : "=qm" (oldbit), ADDR + CC_SET(c) + : CC_OUT(c) (oldbit), ADDR : "Ir" (nr));return oldbit; }
@@ -285,8 +285,8 @@ static __always_inline bool __test_and_change_bit(long nr, volatile unsigned lonbool oldbit; asm volatile("btc %2,%1\n\t" -"setc %0" - : "=qm" (oldbit), ADDR + CC_SET(c) + : CC_OUT(c) (oldbit), ADDR : "Ir" (nr) : "memory");return oldbit;
@@ -316,8 +316,8 @@ static __always_inline bool variable_test_bit(long nr, volatile const unsigned lbool oldbit; asm volatile("bt %2,%1\n\t" -"setc %0" - :"=qm" (oldbit) + CC_SET(c) + : CC_OUT(c) (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr));return oldbit;
PATCH v2 7/10 x86, asm: Use CC_SET()/CC_OUT() in <asm/percpu.h>
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in <asm/percpu.h>.
--- arch/x86/include/asm/percpu.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/x86/include/asm/percpu.h +5 -4
@@ -511,8 +511,9 @@ do { \#define x86_test_and_clear_bit_percpu (bit, var) \ ({ \ bool old__; \ - asm volatile("btr %2,"__percpu_arg(1)"\n\tsetc %0" \ - : "=qm" (old__), "+m" (var) \ + asm volatile("btr %2,"__percpu_arg(1)"\n\t" \ + CC_SET(c) \ + : CC_OUT(c) (old__), "+m" (var) \ : "dIr" (bit)); \ old__; \ })
@@ -535,8 +536,8 @@ static inline bool x86_this_cpu_variable_test_bit(int nr,bool oldbit; asm volatile("bt "__percpu_arg(2)",%1\n\t" - "setc %0" - : "=qm" (oldbit) + CC_SET(c) + : CC_OUT(c) (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr));return oldbit;
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: Use CC_SET()/CC_OUT() in <asm/percpu.h>
x86, asm: Use CC_SET()/CC_OUT() in <asm/percpu.h>
Commit-ID: 64be6d36f5674f3424d1901772f76e21874f4954 Gitweb: http://git.kernel.org/tip/64be6d36f5674f3424d1901772f76e21874f4954 Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:43 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: Use CC_SET()/CC_OUT() in <asm/percpu.h>
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in <asm/percpu.h>.
--- arch/x86/include/asm/percpu.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/x86/include/asm/percpu.h +5 -4
@@ -511,8 +511,9 @@ do { \#define x86_test_and_clear_bit_percpu (bit, var) \ ({ \ bool old__; \ - asm volatile("btr %2,"__percpu_arg(1)"\n\tsetc %0" \ - : "=qm" (old__), "+m" (var) \ + asm volatile("btr %2,"__percpu_arg(1)"\n\t" \ + CC_SET(c) \ + : CC_OUT(c) (old__), "+m" (var) \ : "dIr" (bit)); \ old__; \ })
@@ -535,8 +536,8 @@ static inline bool x86_this_cpu_variable_test_bit(int nr,bool oldbit; asm volatile("bt "__percpu_arg(2)",%1\n\t" - "setc %0" - : "=qm" (oldbit) + CC_SET(c) + : CC_OUT(c) (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr));return oldbit;
PATCH v2 8/10 x86, asm: Use CC_SET()/CC_OUT() in <asm/rwsem.h>
In reply to H. Peter AnvinFrom: "H. Peter Anvin" <[email protected]>
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in <asm/rwsem.h>.
--- arch/x86/include/asm/rwsem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/include/asm/rwsem.h +2 -2
@@ -149,10 +149,10 @@ static inline bool __down_write_trylock(struct rw_semaphore *sem) LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" "2:\n\t" -" sete %3\n\t" + CC_SET(e) "# ending __down_write_trylock\n\t" : "+m" (sem->count), "=&a" (tmp0), "=&r" (tmp1), - "=qm" (result) + CC_OUT(e) (result) : "er" (RWSEM_ACTIVE_WRITE_BIAS) : "memory", "cc");return result;
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: Use CC_SET()/CC_OUT() in <asm/rwsem.h>
x86, asm: Use CC_SET()/CC_OUT() in <asm/rwsem.h>
Commit-ID: 35ccfb7114e2f0f454f264c049b03c31f4c6bbc0 Gitweb: http://git.kernel.org/tip/35ccfb7114e2f0f454f264c049b03c31f4c6bbc0 Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:44 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: Use CC_SET()/CC_OUT() in <asm/rwsem.h>
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in <asm/rwsem.h>.
--- arch/x86/include/asm/rwsem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/include/asm/rwsem.h +2 -2
@@ -149,10 +149,10 @@ static inline bool __down_write_trylock(struct rw_semaphore *sem) LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" "2:\n\t" -" sete %3\n\t" + CC_SET(e) "# ending __down_write_trylock\n\t" : "+m" (sem->count), "=&a" (tmp0), "=&r" (tmp1), - "=qm" (result) + CC_OUT(e) (result) : "er" (RWSEM_ACTIVE_WRITE_BIAS) : "memory", "cc");return result;
PATCH v2 9/10 x86, asm, boot: Use CC_SET()/CC_OUT() in arch/x86/boot/boot.h
In reply to H. Peter AnvinRemove open-coded uses of set instructions to use CC_SET()/CC_OUT() in arch/x86/boot/boot.h.
--- arch/x86/boot/boot.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/x86/boot/boot.h +5 -4
@@ -24,6 +24,7 @@#include <linux/types.h> #include <linux/edd.h> #include <asm/setup.h> +#include <asm/asm.h> #include "bitops.h" #include "ctype.h" #include "cpuflags.h"
@@ -179,15 +180,15 @@ static inline void wrgs32(u32 v, addr_t addr)static inline bool memcmp_fs (const void *s1,addr_t s2,size_t len) {bool diff; - asmvolatile ("fs; repe; cmpsb; setnz %0" - :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len)); + asm volatile("fs; repe; cmpsb" CC_SET(nz) + : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));return diff; }static inline bool memcmp_gs (const void *s1,addr_t s2,size_t len) {bool diff; - asmvolatile ("gs; repe; cmpsb; setnz %0" - :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len)); + asm volatile("gs; repe; cmpsb" CC_SET(nz) + : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));return diff; }
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm, boot: Use CC_SET()/CC_OUT() in arch/x86/boot/boot.h
x86, asm, boot: Use CC_SET()/CC_OUT() in arch/x86/boot/boot.h
Commit-ID: 66928b4eb92dfb6d87c204238057b9278b36452b Gitweb: http://git.kernel.org/tip/66928b4eb92dfb6d87c204238057b9278b36452b Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:45 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm, boot: Use CC_SET()/CC_OUT() in arch/x86/boot/boot.h
Remove open-coded uses of set instructions to use CC_SET()/CC_OUT() in arch/x86/boot/boot.h.
--- arch/x86/boot/boot.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/x86/boot/boot.h +5 -4
@@ -24,6 +24,7 @@#include <linux/types.h> #include <linux/edd.h> #include <asm/setup.h> +#include <asm/asm.h> #include "bitops.h" #include "ctype.h" #include "cpuflags.h"
@@ -179,15 +180,15 @@ static inline void wrgs32(u32 v, addr_t addr)static inline bool memcmp_fs (const void *s1,addr_t s2,size_t len) {bool diff; - asmvolatile ("fs; repe; cmpsb; setnz %0" - :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len)); + asm volatile("fs; repe; cmpsb" CC_SET(nz) + : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));return diff; }static inline bool memcmp_gs (const void *s1,addr_t s2,size_t len) {bool diff; - asmvolatile ("gs; repe; cmpsb; setnz %0" - :"=qm" (diff),"+D" (s1),"+S" (s2),"+c" (len)); + asm volatile("gs; repe; cmpsb" CC_SET(nz) + : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));return diff; }
PATCH v2 10/10 x86, asm: Use CC_SET()/CC_OUT() and static_cpu_has() in archrandom.h
In reply to H. Peter AnvinUse CC_SET()/CC_OUT() and static_cpu_has(). This produces code good enough to eliminate ad hoc use of alternatives in <asm/archrandom.h>, greatly simplifying the code.
While we are at it, make x86_init_rdrand() compile out completely if we don't need it.
v2: fix a conflict between <linux/random.h> and <asm/archrandom.h>
discovered by Ingo Molnar. There are a few places in x86-specific code where we need all of <arch/archrandom.h> even when CONFIG_ARCH_RANDOM is disabled, so <linux/random.h> does not suffice.
--- arch/x86/include/asm/archrandom.h | 128 ++++++++++++++++++-------------------- arch/x86/kernel/cpu/rdrand.c | 4 +- 2 files changed, 62 insertions(+), 70 deletions(-)
arch/x86/include/asm/archrandom.h +60 -68
@@ -25,8 +25,6 @@#include <asm/processor.h> #include <asm/cpufeature.h> -#include <asm/alternative.h> -#include <asm/nops.h> #define RDRAND_RETRY_LOOPS 10
@@ -40,97 +38,91 @@# define RDSEED_LONG RDSEED_INT#endif -#ifdef CONFIG_ARCH_RANDOM +/* Unconditional execution of RDRAND and RDSEED */ -/* Instead of arch_get_random_long() when alternatives haven't run. */ static inline bool rdrand_long (unsigned long *v) { -int ok; - asmvolatile ("1: " RDRAND_LONG "\n\t" -"jc 2f\n\t" -"decl %0\n\t" -"jnz 1b\n\t" -"2:" - :"=r" (ok),"=a" (*v) - :"0" (RDRAND_RETRY_LOOPS )); -return !!ok; +bool ok; +unsigned int retry =RDRAND_RETRY_LOOPS ; +do { + asm volatile(RDRAND_LONG "\n\t" + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v)); +if (ok) +return true; + }while (--retry); +return false; +} + +static inline bool rdrand_int (unsigned int *v) +{ +bool ok; +unsigned int retry =RDRAND_RETRY_LOOPS ; +do { + asm volatile(RDRAND_INT "\n\t" + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v)); +if (ok) +return true; + }while (--retry); +return false; } -/* A single attempt at RDSEED */ static inline bool rdseed_long (unsigned long *v) {bool ok; asm volatile(RDSEED_LONG "\n\t" -"setc %0" - :"=qm" (ok),"=a" (*v)); + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v));return ok; } -#define GET_RANDOM (name, type, rdrand, nop) \ -static inline bool name(type *v) \ -{ \ - int ok; \ - alternative_io("movl $0, %0\n\t" \ - nop, \ - "\n1: " rdrand "\n\t" \ - "jc 2f\n\t" \ - "decl %0\n\t" \ - "jnz 1b\n\t" \ - "2:", \ - X86_FEATURE_RDRAND, \ - ASM_OUTPUT2("=r" (ok), "=a" (*v)), \ - "0" (RDRAND_RETRY_LOOPS)); \ - return !!ok; \ -} - -#define GET_SEED (name, type, rdseed, nop) \ -static inline bool name(type *v) \ -{ \ - bool ok; \ - alternative_io("movb $0, %0\n\t" \ - nop, \ - rdseed "\n\t" \ - "setc %0", \ - X86_FEATURE_RDSEED, \ - ASM_OUTPUT2("=q" (ok), "=a" (*v))); \ - return ok; \ +static inline bool rdseed_int (unsigned int *v) +{ +bool ok; + asm volatile(RDSEED_INT "\n\t" + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v)); +return ok; } -#ifdef CONFIG_X86_64 - -GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5); -GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4); - -GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP5); -GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4); - -#else - -GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3); -GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); - -GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP4); -GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4); - -#endif /* CONFIG_X86_64 */ - +/* Conditional execution based on CPU type */ #define arch_has_random () static_cpu_has(X86_FEATURE_RDRAND)#define arch_has_random_seed () static_cpu_has(X86_FEATURE_RDSEED) -#else +/* +* These are the generic interfaces; they must not be declared if the +* stubs in <linux/random.h> are to be invoked, +* i.e. CONFIG_ARCH_RANDOM is not defined. +*/ +#ifdef CONFIG_ARCH_RANDOM -static inline bool rdrand_long (unsigned long *v) +static inline bool arch_get_random_long (unsigned long *v) { -return 0 ; +return arch_has_random () ?rdrand_long (v) : false; } -static inline bool rdseed_long (unsigned long *v) +static inline bool arch_get_random_int (unsigned int *v) { -return 0 ; +return arch_has_random () ?rdrand_int (v) : false; } -#endif /* CONFIG_ARCH_RANDOM */ +static inline bool arch_get_random_seed_long (unsigned long *v) +{ +return arch_has_random_seed () ?rdseed_long (v) : false; +} + +static inline bool arch_get_random_seed_int (unsigned int *v) +{ +return arch_has_random_seed () ?rdseed_int (v) : false; +}extern void x86_init_rdrand (struct cpuinfo_x86 *c); +#else /* !CONFIG_ARCH_RANDOM */ + +static inline void x86_init_rdrand (struct cpuinfo_x86 *c) { } + +#endif /* !CONFIG_ARCH_RANDOM */ +#endif /* ASM_X86_ARCHRANDOM_H */
arch/x86/kernel/cpu/rdrand.c +2 -2
@@ -39,9 +39,9 @@ __setup("nordrand", x86_rdrand_setup);*/ #define SANITY_CHECK_LOOPS 8 +#ifdef CONFIG_ARCH_RANDOM void x86_init_rdrand (struct cpuinfo_x86 *c) { -#ifdef CONFIG_ARCH_RANDOM unsigned long tmp;int i;
@@ -55,5 +55,5 @@ void x86_init_rdrand(struct cpuinfo_x86 *c) return; } } -#endif } +#endif
Signature · 1 line
2.7.3.0.11.gd79db92
tip-bot for H. Peter Anvin
merge bot[tip:x86/asm] x86, asm: Use CC_SET()/CC_OUT() and static_cpu_has() in archrandom.h
x86, asm: Use CC_SET()/CC_OUT() and static_cpu_has() in archrandom.h
Commit-ID: 3b290398638ee4e57f1fb2e35c02005cba9a737f Gitweb: http://git.kernel.org/tip/3b290398638ee4e57f1fb2e35c02005cba9a737f Author: H. Peter Anvin <[email protected]> AuthorDate: Wed, 8 Jun 2016 12:38:46 -0700 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 8 Jun 2016 12:41:20 -0700
x86, asm: Use CC_SET()/CC_OUT() and static_cpu_has() in archrandom.h
Use CC_SET()/CC_OUT() and static_cpu_has(). This produces code good enough to eliminate ad hoc use of alternatives in <asm/archrandom.h>, greatly simplifying the code.
While we are at it, make x86_init_rdrand() compile out completely if we don't need it.
v2: fix a conflict between <linux/random.h> and <asm/archrandom.h>
discovered by Ingo Molnar. There are a few places in x86-specific code where we need all of <arch/archrandom.h> even when CONFIG_ARCH_RANDOM is disabled, so <linux/random.h> does not suffice.
--- arch/x86/include/asm/archrandom.h | 128 ++++++++++++++++++-------------------- arch/x86/kernel/cpu/rdrand.c | 4 +- 2 files changed, 62 insertions(+), 70 deletions(-)
arch/x86/include/asm/archrandom.h +60 -68
@@ -25,8 +25,6 @@#include <asm/processor.h> #include <asm/cpufeature.h> -#include <asm/alternative.h> -#include <asm/nops.h> #define RDRAND_RETRY_LOOPS 10
@@ -40,97 +38,91 @@# define RDSEED_LONG RDSEED_INT#endif -#ifdef CONFIG_ARCH_RANDOM +/* Unconditional execution of RDRAND and RDSEED */ -/* Instead of arch_get_random_long() when alternatives haven't run. */ static inline bool rdrand_long (unsigned long *v) { -int ok; - asmvolatile ("1: " RDRAND_LONG "\n\t" -"jc 2f\n\t" -"decl %0\n\t" -"jnz 1b\n\t" -"2:" - :"=r" (ok),"=a" (*v) - :"0" (RDRAND_RETRY_LOOPS )); -return !!ok; +bool ok; +unsigned int retry =RDRAND_RETRY_LOOPS ; +do { + asm volatile(RDRAND_LONG "\n\t" + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v)); +if (ok) +return true; + }while (--retry); +return false; +} + +static inline bool rdrand_int (unsigned int *v) +{ +bool ok; +unsigned int retry =RDRAND_RETRY_LOOPS ; +do { + asm volatile(RDRAND_INT "\n\t" + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v)); +if (ok) +return true; + }while (--retry); +return false; } -/* A single attempt at RDSEED */ static inline bool rdseed_long (unsigned long *v) {bool ok; asm volatile(RDSEED_LONG "\n\t" -"setc %0" - :"=qm" (ok),"=a" (*v)); + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v));return ok; } -#define GET_RANDOM (name, type, rdrand, nop) \ -static inline bool name(type *v) \ -{ \ - int ok; \ - alternative_io("movl $0, %0\n\t" \ - nop, \ - "\n1: " rdrand "\n\t" \ - "jc 2f\n\t" \ - "decl %0\n\t" \ - "jnz 1b\n\t" \ - "2:", \ - X86_FEATURE_RDRAND, \ - ASM_OUTPUT2("=r" (ok), "=a" (*v)), \ - "0" (RDRAND_RETRY_LOOPS)); \ - return !!ok; \ -} - -#define GET_SEED (name, type, rdseed, nop) \ -static inline bool name(type *v) \ -{ \ - bool ok; \ - alternative_io("movb $0, %0\n\t" \ - nop, \ - rdseed "\n\t" \ - "setc %0", \ - X86_FEATURE_RDSEED, \ - ASM_OUTPUT2("=q" (ok), "=a" (*v))); \ - return ok; \ +static inline bool rdseed_int (unsigned int *v) +{ +bool ok; + asm volatile(RDSEED_INT "\n\t" + CC_SET(c) + : CC_OUT(c) (ok), "=a" (*v)); +return ok; } -#ifdef CONFIG_X86_64 - -GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5); -GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4); - -GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP5); -GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4); - -#else - -GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3); -GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); - -GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP4); -GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4); - -#endif /* CONFIG_X86_64 */ - +/* Conditional execution based on CPU type */ #define arch_has_random () static_cpu_has(X86_FEATURE_RDRAND)#define arch_has_random_seed () static_cpu_has(X86_FEATURE_RDSEED) -#else +/* +* These are the generic interfaces; they must not be declared if the +* stubs in <linux/random.h> are to be invoked, +* i.e. CONFIG_ARCH_RANDOM is not defined. +*/ +#ifdef CONFIG_ARCH_RANDOM -static inline bool rdrand_long (unsigned long *v) +static inline bool arch_get_random_long (unsigned long *v) { -return 0 ; +return arch_has_random () ?rdrand_long (v) : false; } -static inline bool rdseed_long (unsigned long *v) +static inline bool arch_get_random_int (unsigned int *v) { -return 0 ; +return arch_has_random () ?rdrand_int (v) : false; } -#endif /* CONFIG_ARCH_RANDOM */ +static inline bool arch_get_random_seed_long (unsigned long *v) +{ +return arch_has_random_seed () ?rdseed_long (v) : false; +} + +static inline bool arch_get_random_seed_int (unsigned int *v) +{ +return arch_has_random_seed () ?rdseed_int (v) : false; +}extern void x86_init_rdrand (struct cpuinfo_x86 *c); +#else /* !CONFIG_ARCH_RANDOM */ + +static inline void x86_init_rdrand (struct cpuinfo_x86 *c) { } + +#endif /* !CONFIG_ARCH_RANDOM */ +#endif /* ASM_X86_ARCHRANDOM_H */
arch/x86/kernel/cpu/rdrand.c +2 -2
@@ -39,9 +39,9 @@ __setup("nordrand", x86_rdrand_setup);*/ #define SANITY_CHECK_LOOPS 8 +#ifdef CONFIG_ARCH_RANDOM void x86_init_rdrand (struct cpuinfo_x86 *c) { -#ifdef CONFIG_ARCH_RANDOM unsigned long tmp;int i;
@@ -55,5 +55,5 @@ void x86_init_rdrand(struct cpuinfo_x86 *c) return; } } -#endif } +#endif
Re: [PATCH v2 10/10] x86, asm: Use CC_SET()/CC_OUT() and static_cpu_has() in archrandom.h
In reply to H. Peter AnvinQuoted 14 lines · H. Peter Anvin
Use CC_SET()/CC_OUT() and
static_cpu_has(). This produces code good enough to eliminate ad hoc use of alternatives in <asm/archrandom.h>, greatly simplifying the code.While we are at it, make
x86_init_rdrand()compile out completely if we don't need it.Signed-off-by H. Peter Anvin <[email protected]>v2: fix a conflict between <
linux/random.h> and <asm/archrandom.h>
discovered by Ingo Molnar. There are a few places in x86-specific code where we need all of <arch/archrandom.h> even whenCONFIG_ARCH_RANDOMis disabled, so <linux/random.h> does not suffice.
Quoted 4 lines
--- arch/x86/include/asm/archrandom.h | 128 ++++++++++++++++++-------------------- arch/x86/kernel/cpu/rdrand.c | 4 +- 2 files changed, 62 insertions(+), 70 deletions(-)
Signature · 4 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.H. Peter Anvin
reviewerQuoted 24 lines · H. Peter Anvin
From: "H. Peter Anvin" <[email protected]>
gcc 6+ has the ability to let flags (actually, conditions, which are specific combinations of flags) to be used directly as
asm()outputs. The syntax for that is "=@cc<cc>" where <cc> is the same set of letters that would be used in a j<cc> or set<cc> instruction (e.g. "=@ccz" to test the ZF flag.)This patchset by itself reduces the size of the x86-64 kernel by 0.12%, from a baseline of 4.7-rc2 built with gcc 6.1 (first line is with the patchset, the second one is without):
text data bss dec hex filename
68245656 41004339 20533248 129783243 7bc55cb
o.i386-allconfig/vmlinux
68355716 41008499 20533248 129897463 7be13f7
o.i386-allconfig/vmlinux127384005 129742359 38150144 295276508
11998fdco.x86_64-allconfig/vmlinux
127538765 129742295 38150144 295431204119bec24o.x86_64-allconfig/vmlinux
Quoted 7 lines
v2: fix a conflict between <
linux/random.h> and <asm/archrandom.h>
discovered by Ingo Molnar. There are a few places in x86-specific code where we need all of <arch/archrandom.h> even whenxCONFIG_ARCH_RANDOMis disabled, so <linux/random.h> does not suffice. Only the <asm/archrandom.h> patch has been changed; since it is a little bit different from the others I have moved it to the end.
I should probably clarify one thing: the output type *must* be bool for the flags output. Fortunately, not only does it also work for the older compilers, but it sometimes allows GCC to generate better code, which is why I have made the change unconditionally.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.