x86/asm changes for v3.12
Subsystems (2)
Linus,
Please pull the latest x86-asm-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-asm-for-linus
HEAD: f69fa9a91f60fff6f2d8b658b7d84d235d9d89b7 x86, doc: Update uaccess.h comment to reflect clang changes
Main changes:
- Apply low level mutex optimization on x86-64, by Wedson Almeida Filho.
- Change bitops to be naturally 'long', by H. Peter Anvin.
- Add TSX-NI opcodes support to the x86 (instrumentation) decoder, by Masami Hiramatsu.
- Add clang compatibility adjustments/workarounds, by Jan-Simon Möller.
Thanks,
Ingo
------------------>
H. Peter Anvin (2):
x86, bitops: Change bitops to be native operand size x86, doc: Update uaccess.h comment to reflect clang changes
Jan-Simon Möller (2):
x86, asm: Extend definitions of _ASM_* with a raw format x86, asm: Fix a compilation issue with clang
Masami Hiramatsu (1):
x86, insn: Add new opcodes as of June, 2013
Ramkumar Ramachandra (1):
x86/ia32/asm: Remove unused argument in macro
Wedson Almeida Filho (1):
x86: Use asm-goto to implement mutex fast path on x86-64
arch/x86/ia32/ia32entry.S | 2 +- arch/x86/include/asm/asm.h | 6 ++++- arch/x86/include/asm/bitops.h | 46 +++++++++++++++++++++--------------- arch/x86/include/asm/mutex_64.h | 30 +++++++++++++++++++++++ arch/x86/include/asm/sync_bitops.h | 24 +++++++++---------- arch/x86/include/asm/uaccess.h | 7 ++++-- arch/x86/lib/x86-opcode-map.txt | 42 ++++++++++++++++++-------------- arch/x86/tools/gen-insn-attr-x86.awk | 4 +++- 8 files changed, 107 insertions(+), 54 deletions(-)
arch/x86/ia32/ia32entry.S +1 -1
@@ -452,7 +452,7 @@ ia32_badsys: CFI_ENDPROC - .macro PTREGSCALL label, func, arg + .macro PTREGSCALL label, func ALIGN GLOBAL(\label) leaq \func(%rip),%rax
arch/x86/include/asm/asm.h +5 -1
@@ -3,21 +3,25 @@#ifdef __ASSEMBLY__# define __ASM_FORM (x) x +# define __ASM_FORM_RAW (x) x# define __ASM_FORM_COMMA (x) x,#else # define __ASM_FORM (x) " " #x " " +# define __ASM_FORM_RAW (x) #x# define __ASM_FORM_COMMA (x) " " #x ","#endif #ifdef CONFIG_X86_32 # define __ASM_SEL (a,b) __ASM_FORM(a) +# define __ASM_SEL_RAW (a,b) __ASM_FORM_RAW(a)#else # define __ASM_SEL (a,b) __ASM_FORM(b) +# define __ASM_SEL_RAW (a,b) __ASM_FORM_RAW(b)#endif #define __ASM_SIZE (inst, ...) __ASM_SEL(inst##l##__VA_ARGS__, \ inst##q##__VA_ARGS__) -#define __ASM_REG (reg) __ASM_SEL(e##reg, r##reg) +#define __ASM_REG (reg) __ASM_SEL_RAW(e##reg, r##reg)#define _ASM_PTR __ASM_SEL(.long, .quad)#define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8)
arch/x86/include/asm/bitops.h +27 -19
150 lines not on this page · raw message
arch/x86/include/asm/mutex_64.h +30 -0
@@ -16,6 +16,20 @@* * Atomically decrements @v and calls <fail_fn> if the result is negative. */ +#ifdef CC_HAVE_ASM_GOTO +static inline void __mutex_fastpath_lock (atomic_t *v, +void (*fail_fn)(atomic_t *)) +{ + asmvolatile goto(LOCK_PREFIX " decl %0\n" +" jns %l[exit]\n" + : :"m" (v->counter) + :"memory" ,"cc" + : exit); +fail_fn (v); +exit: +return ; +} +#else #define __mutex_fastpath_lock (v, fail_fn) \ do { \ unsigned long dummy; \
@@ -32,6 +46,7 @@ do { \ : "rax", "rsi", "rdx", "rcx", \ "r8", "r9", "r10", "r11", "memory"); \ } while (0) +#endif /** * __mutex_fastpath_lock_retval - try to take the lock by moving the count
@@ -59,6 +74,20 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count,* * Atomically increments @v and calls <fail_fn> if the result is nonpositive. */ +#ifdef CC_HAVE_ASM_GOTO +static inline void __mutex_fastpath_unlock (atomic_t *v, +void (*fail_fn)(atomic_t *)) +{ + asmvolatile goto(LOCK_PREFIX " incl %0\n" +" jg %l[exit]\n" + : :"m" (v->counter) + :"memory" ,"cc" + : exit); +fail_fn (v); +exit: +return ; +} +#else #define __mutex_fastpath_unlock (v, fail_fn) \ do { \ unsigned long dummy; \
@@ -75,6 +104,7 @@ do { \ : "rax", "rsi", "rdx", "rcx", \ "r8", "r9", "r10", "r11", "memory"); \ } while (0) +#endif#define __mutex_slowpath_needs_to_unlock () 1
arch/x86/include/asm/sync_bitops.h +12 -12
@@ -26,9 +26,9 @@* Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void sync_set_bit (int nr,volatile unsigned long *addr) +static inline void sync_set_bit (long nr,volatile unsigned long *addr) { - asmvolatile ("lock; btsl %1,%0" + asmvolatile ("lock; bts %1,%0" :"+m" (ADDR ) :"Ir" (nr) :"memory" );
@@ -44,9 +44,9 @@ static inline void sync_set_bit(int nr, volatile unsigned long *addr)* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() * in order to ensure changes are visible on other processors. */ -static inline void sync_clear_bit (int nr,volatile unsigned long *addr) +static inline void sync_clear_bit (long nr,volatile unsigned long *addr) { - asmvolatile ("lock; btrl %1,%0" + asmvolatile ("lock; btr %1,%0" :"+m" (ADDR ) :"Ir" (nr) :"memory" );
@@ -61,9 +61,9 @@ static inline void sync_clear_bit(int nr, volatile unsigned long *addr)* Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void sync_change_bit (int nr,volatile unsigned long *addr) +static inline void sync_change_bit (long nr,volatile unsigned long *addr) { - asmvolatile ("lock; btcl %1,%0" + asmvolatile ("lock; btc %1,%0" :"+m" (ADDR ) :"Ir" (nr) :"memory" );
@@ -77,11 +77,11 @@ static inline void sync_change_bit(int nr, volatile unsigned long *addr)* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int sync_test_and_set_bit (int nr,volatile unsigned long *addr) +static inline int sync_test_and_set_bit (long nr,volatile unsigned long *addr) {int oldbit; - asmvolatile ("lock; btsl %2,%1\n\tsbbl %0,%0" + asmvolatile ("lock; bts %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit;
@@ -95,11 +95,11 @@ static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr)* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int sync_test_and_clear_bit (int nr,volatile unsigned long *addr) +static inline int sync_test_and_clear_bit (long nr,volatile unsigned long *addr) {int oldbit; - asmvolatile ("lock; btrl %2,%1\n\tsbbl %0,%0" + asmvolatile ("lock; btr %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit;
@@ -113,11 +113,11 @@ static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr)* This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int sync_test_and_change_bit (int nr,volatile unsigned long *addr) +static inline int sync_test_and_change_bit (long nr,volatile unsigned long *addr) {int oldbit; - asmvolatile ("lock; btcl %2,%1\n\tsbbl %0,%0" + asmvolatile ("lock; btc %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"+m" (ADDR ) :"Ir" (nr) :"memory" );return oldbit;
arch/x86/include/asm/uaccess.h +5 -2
@@ -153,16 +153,19 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))* Careful: we have to cast the result to the type of the pointer * for sign reasons. * -* The use of %edx as the register specifier is a bit of a +* The use of _ASM_DX as the register specifier is a bit of a * simplification, as gcc only cares about it as the starting point * and not size: for a 64-bit value it will use %ecx:%edx on 32 bits * (%ecx being the next register in gcc's x86 register sequence), and * %rdx on 64 bits. +* +* Clang/LLVM cares about the size of the register, but still wants +* the base register for something that ends up being a pair. */ #define get_user (x, ptr) \ ({ \ int __ret_gu; \ - register __inttype(*(ptr)) __val_gu asm("%edx"); \ + register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \ __chk_user_ptr(ptr); \ might_fault(); \ asm volatile("call __get_user_%P3" \
arch/x86/lib/x86-opcode-map.txt +24 -18
98 lines not on this page · raw message
arch/x86/tools/gen-insn-attr-x86.awk +3 -1
@@ -68,7 +68,7 @@ BEGIN { lprefix1_expr = "\\((66|!F3)\\)" lprefix2_expr = "\\(F3\\)" - lprefix3_expr = "\\((F2|!F3)\\)" + lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)" lprefix_expr = "\\((66|F2|F3)\\)" max_lprefix = 4
@@ -83,6 +83,8 @@ BEGIN { prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" prefix_num["REPNE"] = "INAT_PFX_REPNE" prefix_num["REP/REPE"] = "INAT_PFX_REPE" + prefix_num["XACQUIRE"] = "INAT_PFX_REPNE" + prefix_num["XRELEASE"] = "INAT_PFX_REPE" prefix_num["LOCK"] = "INAT_PFX_LOCK" prefix_num["SEG=CS"] = "INAT_PFX_CS" prefix_num["SEG=DS"] = "INAT_PFX_DS"