diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 20:02:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 20:02:24 -0400 |
commit | eb47418dc56baaca33d270a868d8ddaa81150952 (patch) | |
tree | 16c0b09bacf3f6c25e5786afcfa741fa2a550ae5 /arch | |
parent | 2c9e88a1085b3183e5f92170a74980e5654f817b (diff) | |
parent | a750036f35cda160ef77408ec92c3dc41f8feebb (diff) |
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: Fix write lock scalability 64-bit issue
x86: Unify rwsem assembly implementation
x86: Unify rwlock assembly implementation
x86, asm: Fix binutils 2.16 issue with __USER32_CS
x86, asm: Cleanup thunk_64.S
x86, asm: Flip RESTORE_ARGS arguments logic
x86, asm: Flip SAVE_ARGS arguments logic
x86, asm: Thin down SAVE/RESTORE_* asm macros
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/sys-i386/Makefile | 2 | ||||
-rw-r--r-- | arch/um/sys-x86_64/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 10 | ||||
-rw-r--r-- | arch/x86/include/asm/asm.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/calling.h | 130 | ||||
-rw-r--r-- | arch/x86/include/asm/frame.h | 11 | ||||
-rw-r--r-- | arch/x86/include/asm/rwlock.h | 43 | ||||
-rw-r--r-- | arch/x86/include/asm/segment.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/spinlock.h | 37 | ||||
-rw-r--r-- | arch/x86/include/asm/spinlock_types.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 6 | ||||
-rw-r--r-- | arch/x86/lib/Makefile | 7 | ||||
-rw-r--r-- | arch/x86/lib/rwlock.S | 44 | ||||
-rw-r--r-- | arch/x86/lib/rwlock_64.S | 38 | ||||
-rw-r--r-- | arch/x86/lib/rwsem.S (renamed from arch/x86/lib/rwsem_64.S) | 75 | ||||
-rw-r--r-- | arch/x86/lib/semaphore_32.S | 124 | ||||
-rw-r--r-- | arch/x86/lib/thunk_64.S | 45 |
17 files changed, 263 insertions, 324 deletions
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index b1da91c1b200..15587ed9a361 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -8,7 +8,7 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | |||
8 | 8 | ||
9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o | 9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o |
10 | 10 | ||
11 | subarch-obj-y = lib/semaphore_32.o lib/string_32.o | 11 | subarch-obj-y = lib/rwsem.o lib/string_32.o |
12 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o | 12 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o |
13 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o | 13 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
14 | 14 | ||
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index c1ea9eb04466..61fc99a42e10 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -9,7 +9,7 @@ obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | |||
9 | sysrq.o ksyms.o tls.o | 9 | sysrq.o ksyms.o tls.o |
10 | 10 | ||
11 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \ | 11 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \ |
12 | lib/rwsem_64.o | 12 | lib/rwsem.o |
13 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o | 13 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
14 | 14 | ||
15 | ldt-y = ../sys-i386/ldt.o | 15 | ldt-y = ../sys-i386/ldt.o |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index c1870dddd322..a0e866d233ee 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -143,7 +143,7 @@ ENTRY(ia32_sysenter_target) | |||
143 | CFI_REL_OFFSET rip,0 | 143 | CFI_REL_OFFSET rip,0 |
144 | pushq_cfi %rax | 144 | pushq_cfi %rax |
145 | cld | 145 | cld |
146 | SAVE_ARGS 0,0,1 | 146 | SAVE_ARGS 0,1,0 |
147 | /* no need to do an access_ok check here because rbp has been | 147 | /* no need to do an access_ok check here because rbp has been |
148 | 32bit zero extended */ | 148 | 32bit zero extended */ |
149 | 1: movl (%rbp),%ebp | 149 | 1: movl (%rbp),%ebp |
@@ -173,7 +173,7 @@ sysexit_from_sys_call: | |||
173 | andl $~0x200,EFLAGS-R11(%rsp) | 173 | andl $~0x200,EFLAGS-R11(%rsp) |
174 | movl RIP-R11(%rsp),%edx /* User %eip */ | 174 | movl RIP-R11(%rsp),%edx /* User %eip */ |
175 | CFI_REGISTER rip,rdx | 175 | CFI_REGISTER rip,rdx |
176 | RESTORE_ARGS 1,24,1,1,1,1 | 176 | RESTORE_ARGS 0,24,0,0,0,0 |
177 | xorq %r8,%r8 | 177 | xorq %r8,%r8 |
178 | xorq %r9,%r9 | 178 | xorq %r9,%r9 |
179 | xorq %r10,%r10 | 179 | xorq %r10,%r10 |
@@ -289,7 +289,7 @@ ENTRY(ia32_cstar_target) | |||
289 | * disabled irqs and here we enable it straight after entry: | 289 | * disabled irqs and here we enable it straight after entry: |
290 | */ | 290 | */ |
291 | ENABLE_INTERRUPTS(CLBR_NONE) | 291 | ENABLE_INTERRUPTS(CLBR_NONE) |
292 | SAVE_ARGS 8,1,1 | 292 | SAVE_ARGS 8,0,0 |
293 | movl %eax,%eax /* zero extension */ | 293 | movl %eax,%eax /* zero extension */ |
294 | movq %rax,ORIG_RAX-ARGOFFSET(%rsp) | 294 | movq %rax,ORIG_RAX-ARGOFFSET(%rsp) |
295 | movq %rcx,RIP-ARGOFFSET(%rsp) | 295 | movq %rcx,RIP-ARGOFFSET(%rsp) |
@@ -328,7 +328,7 @@ cstar_dispatch: | |||
328 | jnz sysretl_audit | 328 | jnz sysretl_audit |
329 | sysretl_from_sys_call: | 329 | sysretl_from_sys_call: |
330 | andl $~TS_COMPAT,TI_status(%r10) | 330 | andl $~TS_COMPAT,TI_status(%r10) |
331 | RESTORE_ARGS 1,-ARG_SKIP,1,1,1 | 331 | RESTORE_ARGS 0,-ARG_SKIP,0,0,0 |
332 | movl RIP-ARGOFFSET(%rsp),%ecx | 332 | movl RIP-ARGOFFSET(%rsp),%ecx |
333 | CFI_REGISTER rip,rcx | 333 | CFI_REGISTER rip,rcx |
334 | movl EFLAGS-ARGOFFSET(%rsp),%r11d | 334 | movl EFLAGS-ARGOFFSET(%rsp),%r11d |
@@ -419,7 +419,7 @@ ENTRY(ia32_syscall) | |||
419 | cld | 419 | cld |
420 | /* note the registers are not zero extended to the sf. | 420 | /* note the registers are not zero extended to the sf. |
421 | this could be a problem. */ | 421 | this could be a problem. */ |
422 | SAVE_ARGS 0,0,1 | 422 | SAVE_ARGS 0,1,0 |
423 | GET_THREAD_INFO(%r10) | 423 | GET_THREAD_INFO(%r10) |
424 | orl $TS_COMPAT,TI_status(%r10) | 424 | orl $TS_COMPAT,TI_status(%r10) |
425 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 425 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h index b3ed1e1460ff..9412d6558c88 100644 --- a/arch/x86/include/asm/asm.h +++ b/arch/x86/include/asm/asm.h | |||
@@ -3,9 +3,11 @@ | |||
3 | 3 | ||
4 | #ifdef __ASSEMBLY__ | 4 | #ifdef __ASSEMBLY__ |
5 | # define __ASM_FORM(x) x | 5 | # define __ASM_FORM(x) x |
6 | # define __ASM_FORM_COMMA(x) x, | ||
6 | # define __ASM_EX_SEC .section __ex_table, "a" | 7 | # define __ASM_EX_SEC .section __ex_table, "a" |
7 | #else | 8 | #else |
8 | # define __ASM_FORM(x) " " #x " " | 9 | # define __ASM_FORM(x) " " #x " " |
10 | # define __ASM_FORM_COMMA(x) " " #x "," | ||
9 | # define __ASM_EX_SEC " .section __ex_table,\"a\"\n" | 11 | # define __ASM_EX_SEC " .section __ex_table,\"a\"\n" |
10 | #endif | 12 | #endif |
11 | 13 | ||
@@ -15,7 +17,8 @@ | |||
15 | # define __ASM_SEL(a,b) __ASM_FORM(b) | 17 | # define __ASM_SEL(a,b) __ASM_FORM(b) |
16 | #endif | 18 | #endif |
17 | 19 | ||
18 | #define __ASM_SIZE(inst) __ASM_SEL(inst##l, inst##q) | 20 | #define __ASM_SIZE(inst, ...) __ASM_SEL(inst##l##__VA_ARGS__, \ |
21 | inst##q##__VA_ARGS__) | ||
19 | #define __ASM_REG(reg) __ASM_SEL(e##reg, r##reg) | 22 | #define __ASM_REG(reg) __ASM_SEL(e##reg, r##reg) |
20 | 23 | ||
21 | #define _ASM_PTR __ASM_SEL(.long, .quad) | 24 | #define _ASM_PTR __ASM_SEL(.long, .quad) |
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h index 30af5a832163..a9e3a740f697 100644 --- a/arch/x86/include/asm/calling.h +++ b/arch/x86/include/asm/calling.h | |||
@@ -46,6 +46,7 @@ For 32-bit we have the following conventions - kernel is built with | |||
46 | 46 | ||
47 | */ | 47 | */ |
48 | 48 | ||
49 | #include "dwarf2.h" | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * 64-bit system call stack frame layout defines and helpers, for | 52 | * 64-bit system call stack frame layout defines and helpers, for |
@@ -84,72 +85,57 @@ For 32-bit we have the following conventions - kernel is built with | |||
84 | #define ARGOFFSET R11 | 85 | #define ARGOFFSET R11 |
85 | #define SWFRAME ORIG_RAX | 86 | #define SWFRAME ORIG_RAX |
86 | 87 | ||
87 | .macro SAVE_ARGS addskip=0, norcx=0, nor891011=0 | 88 | .macro SAVE_ARGS addskip=0, save_rcx=1, save_r891011=1 |
88 | subq $9*8+\addskip, %rsp | 89 | subq $9*8+\addskip, %rsp |
89 | CFI_ADJUST_CFA_OFFSET 9*8+\addskip | 90 | CFI_ADJUST_CFA_OFFSET 9*8+\addskip |
90 | movq %rdi, 8*8(%rsp) | 91 | movq_cfi rdi, 8*8 |
91 | CFI_REL_OFFSET rdi, 8*8 | 92 | movq_cfi rsi, 7*8 |
92 | movq %rsi, 7*8(%rsp) | 93 | movq_cfi rdx, 6*8 |
93 | CFI_REL_OFFSET rsi, 7*8 | 94 | |
94 | movq %rdx, 6*8(%rsp) | 95 | .if \save_rcx |
95 | CFI_REL_OFFSET rdx, 6*8 | 96 | movq_cfi rcx, 5*8 |
96 | .if \norcx | ||
97 | .else | ||
98 | movq %rcx, 5*8(%rsp) | ||
99 | CFI_REL_OFFSET rcx, 5*8 | ||
100 | .endif | 97 | .endif |
101 | movq %rax, 4*8(%rsp) | 98 | |
102 | CFI_REL_OFFSET rax, 4*8 | 99 | movq_cfi rax, 4*8 |
103 | .if \nor891011 | 100 | |
104 | .else | 101 | .if \save_r891011 |
105 | movq %r8, 3*8(%rsp) | 102 | movq_cfi r8, 3*8 |
106 | CFI_REL_OFFSET r8, 3*8 | 103 | movq_cfi r9, 2*8 |
107 | movq %r9, 2*8(%rsp) | 104 | movq_cfi r10, 1*8 |
108 | CFI_REL_OFFSET r9, 2*8 | 105 | movq_cfi r11, 0*8 |
109 | movq %r10, 1*8(%rsp) | ||
110 | CFI_REL_OFFSET r10, 1*8 | ||
111 | movq %r11, (%rsp) | ||
112 | CFI_REL_OFFSET r11, 0*8 | ||
113 | .endif | 106 | .endif |
107 | |||
114 | .endm | 108 | .endm |
115 | 109 | ||
116 | #define ARG_SKIP (9*8) | 110 | #define ARG_SKIP (9*8) |
117 | 111 | ||
118 | .macro RESTORE_ARGS skiprax=0, addskip=0, skiprcx=0, skipr11=0, \ | 112 | .macro RESTORE_ARGS rstor_rax=1, addskip=0, rstor_rcx=1, rstor_r11=1, \ |
119 | skipr8910=0, skiprdx=0 | 113 | rstor_r8910=1, rstor_rdx=1 |
120 | .if \skipr11 | 114 | .if \rstor_r11 |
121 | .else | 115 | movq_cfi_restore 0*8, r11 |
122 | movq (%rsp), %r11 | ||
123 | CFI_RESTORE r11 | ||
124 | .endif | 116 | .endif |
125 | .if \skipr8910 | 117 | |
126 | .else | 118 | .if \rstor_r8910 |
127 | movq 1*8(%rsp), %r10 | 119 | movq_cfi_restore 1*8, r10 |
128 | CFI_RESTORE r10 | 120 | movq_cfi_restore 2*8, r9 |
129 | movq 2*8(%rsp), %r9 | 121 | movq_cfi_restore 3*8, r8 |
130 | CFI_RESTORE r9 | ||
131 | movq 3*8(%rsp), %r8 | ||
132 | CFI_RESTORE r8 | ||
133 | .endif | 122 | .endif |
134 | .if \skiprax | 123 | |
135 | .else | 124 | .if \rstor_rax |
136 | movq 4*8(%rsp), %rax | 125 | movq_cfi_restore 4*8, rax |
137 | CFI_RESTORE rax | ||
138 | .endif | 126 | .endif |
139 | .if \skiprcx | 127 | |
140 | .else | 128 | .if \rstor_rcx |
141 | movq 5*8(%rsp), %rcx | 129 | movq_cfi_restore 5*8, rcx |
142 | CFI_RESTORE rcx | ||
143 | .endif | 130 | .endif |
144 | .if \skiprdx | 131 | |
145 | .else | 132 | .if \rstor_rdx |
146 | movq 6*8(%rsp), %rdx | 133 | movq_cfi_restore 6*8, rdx |
147 | CFI_RESTORE rdx | ||
148 | .endif | 134 | .endif |
149 | movq 7*8(%rsp), %rsi | 135 | |
150 | CFI_RESTORE rsi | 136 | movq_cfi_restore 7*8, rsi |
151 | movq 8*8(%rsp), %rdi | 137 | movq_cfi_restore 8*8, rdi |
152 | CFI_RESTORE rdi | 138 | |
153 | .if ARG_SKIP+\addskip > 0 | 139 | .if ARG_SKIP+\addskip > 0 |
154 | addq $ARG_SKIP+\addskip, %rsp | 140 | addq $ARG_SKIP+\addskip, %rsp |
155 | CFI_ADJUST_CFA_OFFSET -(ARG_SKIP+\addskip) | 141 | CFI_ADJUST_CFA_OFFSET -(ARG_SKIP+\addskip) |
@@ -176,33 +162,21 @@ For 32-bit we have the following conventions - kernel is built with | |||
176 | .macro SAVE_REST | 162 | .macro SAVE_REST |
177 | subq $REST_SKIP, %rsp | 163 | subq $REST_SKIP, %rsp |
178 | CFI_ADJUST_CFA_OFFSET REST_SKIP | 164 | CFI_ADJUST_CFA_OFFSET REST_SKIP |
179 | movq %rbx, 5*8(%rsp) | 165 | movq_cfi rbx, 5*8 |
180 | CFI_REL_OFFSET rbx, 5*8 | 166 | movq_cfi rbp, 4*8 |
181 | movq %rbp, 4*8(%rsp) | 167 | movq_cfi r12, 3*8 |
182 | CFI_REL_OFFSET rbp, 4*8 | 168 | movq_cfi r13, 2*8 |
183 | movq %r12, 3*8(%rsp) | 169 | movq_cfi r14, 1*8 |
184 | CFI_REL_OFFSET r12, 3*8 | 170 | movq_cfi r15, 0*8 |
185 | movq %r13, 2*8(%rsp) | ||
186 | CFI_REL_OFFSET r13, 2*8 | ||
187 | movq %r14, 1*8(%rsp) | ||
188 | CFI_REL_OFFSET r14, 1*8 | ||
189 | movq %r15, (%rsp) | ||
190 | CFI_REL_OFFSET r15, 0*8 | ||
191 | .endm | 171 | .endm |
192 | 172 | ||
193 | .macro RESTORE_REST | 173 | .macro RESTORE_REST |
194 | movq (%rsp), %r15 | 174 | movq_cfi_restore 0*8, r15 |
195 | CFI_RESTORE r15 | 175 | movq_cfi_restore 1*8, r14 |
196 | movq 1*8(%rsp), %r14 | 176 | movq_cfi_restore 2*8, r13 |
197 | CFI_RESTORE r14 | 177 | movq_cfi_restore 3*8, r12 |
198 | movq 2*8(%rsp), %r13 | 178 | movq_cfi_restore 4*8, rbp |
199 | CFI_RESTORE r13 | 179 | movq_cfi_restore 5*8, rbx |
200 | movq 3*8(%rsp), %r12 | ||
201 | CFI_RESTORE r12 | ||
202 | movq 4*8(%rsp), %rbp | ||
203 | CFI_RESTORE rbp | ||
204 | movq 5*8(%rsp), %rbx | ||
205 | CFI_RESTORE rbx | ||
206 | addq $REST_SKIP, %rsp | 180 | addq $REST_SKIP, %rsp |
207 | CFI_ADJUST_CFA_OFFSET -(REST_SKIP) | 181 | CFI_ADJUST_CFA_OFFSET -(REST_SKIP) |
208 | .endm | 182 | .endm |
@@ -214,7 +188,7 @@ For 32-bit we have the following conventions - kernel is built with | |||
214 | 188 | ||
215 | .macro RESTORE_ALL addskip=0 | 189 | .macro RESTORE_ALL addskip=0 |
216 | RESTORE_REST | 190 | RESTORE_REST |
217 | RESTORE_ARGS 0, \addskip | 191 | RESTORE_ARGS 1, \addskip |
218 | .endm | 192 | .endm |
219 | 193 | ||
220 | .macro icebp | 194 | .macro icebp |
diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h index 2c6fc9e62812..3b629f47eb65 100644 --- a/arch/x86/include/asm/frame.h +++ b/arch/x86/include/asm/frame.h | |||
@@ -1,5 +1,6 @@ | |||
1 | #ifdef __ASSEMBLY__ | 1 | #ifdef __ASSEMBLY__ |
2 | 2 | ||
3 | #include <asm/asm.h> | ||
3 | #include <asm/dwarf2.h> | 4 | #include <asm/dwarf2.h> |
4 | 5 | ||
5 | /* The annotation hides the frame from the unwinder and makes it look | 6 | /* The annotation hides the frame from the unwinder and makes it look |
@@ -7,13 +8,13 @@ | |||
7 | frame pointer later */ | 8 | frame pointer later */ |
8 | #ifdef CONFIG_FRAME_POINTER | 9 | #ifdef CONFIG_FRAME_POINTER |
9 | .macro FRAME | 10 | .macro FRAME |
10 | pushl_cfi %ebp | 11 | __ASM_SIZE(push,_cfi) %__ASM_REG(bp) |
11 | CFI_REL_OFFSET ebp,0 | 12 | CFI_REL_OFFSET __ASM_REG(bp), 0 |
12 | movl %esp,%ebp | 13 | __ASM_SIZE(mov) %__ASM_REG(sp), %__ASM_REG(bp) |
13 | .endm | 14 | .endm |
14 | .macro ENDFRAME | 15 | .macro ENDFRAME |
15 | popl_cfi %ebp | 16 | __ASM_SIZE(pop,_cfi) %__ASM_REG(bp) |
16 | CFI_RESTORE ebp | 17 | CFI_RESTORE __ASM_REG(bp) |
17 | .endm | 18 | .endm |
18 | #else | 19 | #else |
19 | .macro FRAME | 20 | .macro FRAME |
diff --git a/arch/x86/include/asm/rwlock.h b/arch/x86/include/asm/rwlock.h index 6a8c0d645108..a5370a03d90c 100644 --- a/arch/x86/include/asm/rwlock.h +++ b/arch/x86/include/asm/rwlock.h | |||
@@ -1,7 +1,48 @@ | |||
1 | #ifndef _ASM_X86_RWLOCK_H | 1 | #ifndef _ASM_X86_RWLOCK_H |
2 | #define _ASM_X86_RWLOCK_H | 2 | #define _ASM_X86_RWLOCK_H |
3 | 3 | ||
4 | #define RW_LOCK_BIAS 0x01000000 | 4 | #include <asm/asm.h> |
5 | |||
6 | #if CONFIG_NR_CPUS <= 2048 | ||
7 | |||
8 | #ifndef __ASSEMBLY__ | ||
9 | typedef union { | ||
10 | s32 lock; | ||
11 | s32 write; | ||
12 | } arch_rwlock_t; | ||
13 | #endif | ||
14 | |||
15 | #define RW_LOCK_BIAS 0x00100000 | ||
16 | #define READ_LOCK_SIZE(insn) __ASM_FORM(insn##l) | ||
17 | #define READ_LOCK_ATOMIC(n) atomic_##n | ||
18 | #define WRITE_LOCK_ADD(n) __ASM_FORM_COMMA(addl n) | ||
19 | #define WRITE_LOCK_SUB(n) __ASM_FORM_COMMA(subl n) | ||
20 | #define WRITE_LOCK_CMP RW_LOCK_BIAS | ||
21 | |||
22 | #else /* CONFIG_NR_CPUS > 2048 */ | ||
23 | |||
24 | #include <linux/const.h> | ||
25 | |||
26 | #ifndef __ASSEMBLY__ | ||
27 | typedef union { | ||
28 | s64 lock; | ||
29 | struct { | ||
30 | u32 read; | ||
31 | s32 write; | ||
32 | }; | ||
33 | } arch_rwlock_t; | ||
34 | #endif | ||
35 | |||
36 | #define RW_LOCK_BIAS (_AC(1,L) << 32) | ||
37 | #define READ_LOCK_SIZE(insn) __ASM_FORM(insn##q) | ||
38 | #define READ_LOCK_ATOMIC(n) atomic64_##n | ||
39 | #define WRITE_LOCK_ADD(n) __ASM_FORM(incl) | ||
40 | #define WRITE_LOCK_SUB(n) __ASM_FORM(decl) | ||
41 | #define WRITE_LOCK_CMP 1 | ||
42 | |||
43 | #endif /* CONFIG_NR_CPUS */ | ||
44 | |||
45 | #define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } | ||
5 | 46 | ||
6 | /* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */ | 47 | /* Actual code is in asm/spinlock.h or in arch/x86/lib/rwlock.S */ |
7 | 48 | ||
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index cd84f7208f76..5e641715c3fe 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h | |||
@@ -162,7 +162,7 @@ | |||
162 | #define GDT_ENTRY_DEFAULT_USER32_CS 4 | 162 | #define GDT_ENTRY_DEFAULT_USER32_CS 4 |
163 | #define GDT_ENTRY_DEFAULT_USER_DS 5 | 163 | #define GDT_ENTRY_DEFAULT_USER_DS 5 |
164 | #define GDT_ENTRY_DEFAULT_USER_CS 6 | 164 | #define GDT_ENTRY_DEFAULT_USER_CS 6 |
165 | #define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS * 8 + 3) | 165 | #define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8+3) |
166 | #define __USER32_DS __USER_DS | 166 | #define __USER32_DS __USER_DS |
167 | 167 | ||
168 | #define GDT_ENTRY_TSS 8 /* needs two entries */ | 168 | #define GDT_ENTRY_TSS 8 /* needs two entries */ |
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index 3089f70c0c52..e9e51f710e6c 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define _ASM_X86_SPINLOCK_H | 2 | #define _ASM_X86_SPINLOCK_H |
3 | 3 | ||
4 | #include <asm/atomic.h> | 4 | #include <asm/atomic.h> |
5 | #include <asm/rwlock.h> | ||
6 | #include <asm/page.h> | 5 | #include <asm/page.h> |
7 | #include <asm/processor.h> | 6 | #include <asm/processor.h> |
8 | #include <linux/compiler.h> | 7 | #include <linux/compiler.h> |
@@ -234,7 +233,7 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock) | |||
234 | */ | 233 | */ |
235 | static inline int arch_read_can_lock(arch_rwlock_t *lock) | 234 | static inline int arch_read_can_lock(arch_rwlock_t *lock) |
236 | { | 235 | { |
237 | return (int)(lock)->lock > 0; | 236 | return lock->lock > 0; |
238 | } | 237 | } |
239 | 238 | ||
240 | /** | 239 | /** |
@@ -243,12 +242,12 @@ static inline int arch_read_can_lock(arch_rwlock_t *lock) | |||
243 | */ | 242 | */ |
244 | static inline int arch_write_can_lock(arch_rwlock_t *lock) | 243 | static inline int arch_write_can_lock(arch_rwlock_t *lock) |
245 | { | 244 | { |
246 | return (lock)->lock == RW_LOCK_BIAS; | 245 | return lock->write == WRITE_LOCK_CMP; |
247 | } | 246 | } |
248 | 247 | ||
249 | static inline void arch_read_lock(arch_rwlock_t *rw) | 248 | static inline void arch_read_lock(arch_rwlock_t *rw) |
250 | { | 249 | { |
251 | asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" | 250 | asm volatile(LOCK_PREFIX READ_LOCK_SIZE(dec) " (%0)\n\t" |
252 | "jns 1f\n" | 251 | "jns 1f\n" |
253 | "call __read_lock_failed\n\t" | 252 | "call __read_lock_failed\n\t" |
254 | "1:\n" | 253 | "1:\n" |
@@ -257,47 +256,55 @@ static inline void arch_read_lock(arch_rwlock_t *rw) | |||
257 | 256 | ||
258 | static inline void arch_write_lock(arch_rwlock_t *rw) | 257 | static inline void arch_write_lock(arch_rwlock_t *rw) |
259 | { | 258 | { |
260 | asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t" | 259 | asm volatile(LOCK_PREFIX WRITE_LOCK_SUB(%1) "(%0)\n\t" |
261 | "jz 1f\n" | 260 | "jz 1f\n" |
262 | "call __write_lock_failed\n\t" | 261 | "call __write_lock_failed\n\t" |
263 | "1:\n" | 262 | "1:\n" |
264 | ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory"); | 263 | ::LOCK_PTR_REG (&rw->write), "i" (RW_LOCK_BIAS) |
264 | : "memory"); | ||
265 | } | 265 | } |
266 | 266 | ||
267 | static inline int arch_read_trylock(arch_rwlock_t *lock) | 267 | static inline int arch_read_trylock(arch_rwlock_t *lock) |
268 | { | 268 | { |
269 | atomic_t *count = (atomic_t *)lock; | 269 | READ_LOCK_ATOMIC(t) *count = (READ_LOCK_ATOMIC(t) *)lock; |
270 | 270 | ||
271 | if (atomic_dec_return(count) >= 0) | 271 | if (READ_LOCK_ATOMIC(dec_return)(count) >= 0) |
272 | return 1; | 272 | return 1; |
273 | atomic_inc(count); | 273 | READ_LOCK_ATOMIC(inc)(count); |
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
276 | 276 | ||
277 | static inline int arch_write_trylock(arch_rwlock_t *lock) | 277 | static inline int arch_write_trylock(arch_rwlock_t *lock) |
278 | { | 278 | { |
279 | atomic_t *count = (atomic_t *)lock; | 279 | atomic_t *count = (atomic_t *)&lock->write; |
280 | 280 | ||
281 | if (atomic_sub_and_test(RW_LOCK_BIAS, count)) | 281 | if (atomic_sub_and_test(WRITE_LOCK_CMP, count)) |
282 | return 1; | 282 | return 1; |
283 | atomic_add(RW_LOCK_BIAS, count); | 283 | atomic_add(WRITE_LOCK_CMP, count); |
284 | return 0; | 284 | return 0; |
285 | } | 285 | } |
286 | 286 | ||
287 | static inline void arch_read_unlock(arch_rwlock_t *rw) | 287 | static inline void arch_read_unlock(arch_rwlock_t *rw) |
288 | { | 288 | { |
289 | asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory"); | 289 | asm volatile(LOCK_PREFIX READ_LOCK_SIZE(inc) " %0" |
290 | :"+m" (rw->lock) : : "memory"); | ||
290 | } | 291 | } |
291 | 292 | ||
292 | static inline void arch_write_unlock(arch_rwlock_t *rw) | 293 | static inline void arch_write_unlock(arch_rwlock_t *rw) |
293 | { | 294 | { |
294 | asm volatile(LOCK_PREFIX "addl %1, %0" | 295 | asm volatile(LOCK_PREFIX WRITE_LOCK_ADD(%1) "%0" |
295 | : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory"); | 296 | : "+m" (rw->write) : "i" (RW_LOCK_BIAS) : "memory"); |
296 | } | 297 | } |
297 | 298 | ||
298 | #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) | 299 | #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) |
299 | #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) | 300 | #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) |
300 | 301 | ||
302 | #undef READ_LOCK_SIZE | ||
303 | #undef READ_LOCK_ATOMIC | ||
304 | #undef WRITE_LOCK_ADD | ||
305 | #undef WRITE_LOCK_SUB | ||
306 | #undef WRITE_LOCK_CMP | ||
307 | |||
301 | #define arch_spin_relax(lock) cpu_relax() | 308 | #define arch_spin_relax(lock) cpu_relax() |
302 | #define arch_read_relax(lock) cpu_relax() | 309 | #define arch_read_relax(lock) cpu_relax() |
303 | #define arch_write_relax(lock) cpu_relax() | 310 | #define arch_write_relax(lock) cpu_relax() |
diff --git a/arch/x86/include/asm/spinlock_types.h b/arch/x86/include/asm/spinlock_types.h index dcb48b2edc11..7c7a486fcb68 100644 --- a/arch/x86/include/asm/spinlock_types.h +++ b/arch/x86/include/asm/spinlock_types.h | |||
@@ -11,10 +11,6 @@ typedef struct arch_spinlock { | |||
11 | 11 | ||
12 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } | 12 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } |
13 | 13 | ||
14 | typedef struct { | 14 | #include <asm/rwlock.h> |
15 | unsigned int lock; | ||
16 | } arch_rwlock_t; | ||
17 | |||
18 | #define __ARCH_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } | ||
19 | 15 | ||
20 | #endif /* _ASM_X86_SPINLOCK_TYPES_H */ | 16 | #endif /* _ASM_X86_SPINLOCK_TYPES_H */ |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index d656f68371a4..d130b20a6b90 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -467,7 +467,7 @@ ENTRY(system_call_after_swapgs) | |||
467 | * and short: | 467 | * and short: |
468 | */ | 468 | */ |
469 | ENABLE_INTERRUPTS(CLBR_NONE) | 469 | ENABLE_INTERRUPTS(CLBR_NONE) |
470 | SAVE_ARGS 8,1 | 470 | SAVE_ARGS 8,0 |
471 | movq %rax,ORIG_RAX-ARGOFFSET(%rsp) | 471 | movq %rax,ORIG_RAX-ARGOFFSET(%rsp) |
472 | movq %rcx,RIP-ARGOFFSET(%rsp) | 472 | movq %rcx,RIP-ARGOFFSET(%rsp) |
473 | CFI_REL_OFFSET rip,RIP-ARGOFFSET | 473 | CFI_REL_OFFSET rip,RIP-ARGOFFSET |
@@ -502,7 +502,7 @@ sysret_check: | |||
502 | TRACE_IRQS_ON | 502 | TRACE_IRQS_ON |
503 | movq RIP-ARGOFFSET(%rsp),%rcx | 503 | movq RIP-ARGOFFSET(%rsp),%rcx |
504 | CFI_REGISTER rip,rcx | 504 | CFI_REGISTER rip,rcx |
505 | RESTORE_ARGS 0,-ARG_SKIP,1 | 505 | RESTORE_ARGS 1,-ARG_SKIP,0 |
506 | /*CFI_REGISTER rflags,r11*/ | 506 | /*CFI_REGISTER rflags,r11*/ |
507 | movq PER_CPU_VAR(old_rsp), %rsp | 507 | movq PER_CPU_VAR(old_rsp), %rsp |
508 | USERGS_SYSRET64 | 508 | USERGS_SYSRET64 |
@@ -851,7 +851,7 @@ retint_restore_args: /* return to kernel space */ | |||
851 | */ | 851 | */ |
852 | TRACE_IRQS_IRETQ | 852 | TRACE_IRQS_IRETQ |
853 | restore_args: | 853 | restore_args: |
854 | RESTORE_ARGS 0,8,0 | 854 | RESTORE_ARGS 1,8,1 |
855 | 855 | ||
856 | irq_return: | 856 | irq_return: |
857 | INTERRUPT_RETURN | 857 | INTERRUPT_RETURN |
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 6ba477342b8e..b00f6785da74 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile | |||
@@ -20,6 +20,8 @@ lib-y := delay.o | |||
20 | lib-y += thunk_$(BITS).o | 20 | lib-y += thunk_$(BITS).o |
21 | lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o | 21 | lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o |
22 | lib-y += memcpy_$(BITS).o | 22 | lib-y += memcpy_$(BITS).o |
23 | lib-$(CONFIG_SMP) += rwlock.o | ||
24 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o | ||
23 | lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o | 25 | lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o |
24 | 26 | ||
25 | obj-y += msr.o msr-reg.o msr-reg-export.o | 27 | obj-y += msr.o msr-reg.o msr-reg-export.o |
@@ -29,7 +31,7 @@ ifeq ($(CONFIG_X86_32),y) | |||
29 | lib-y += atomic64_cx8_32.o | 31 | lib-y += atomic64_cx8_32.o |
30 | lib-y += checksum_32.o | 32 | lib-y += checksum_32.o |
31 | lib-y += strstr_32.o | 33 | lib-y += strstr_32.o |
32 | lib-y += semaphore_32.o string_32.o | 34 | lib-y += string_32.o |
33 | lib-y += cmpxchg.o | 35 | lib-y += cmpxchg.o |
34 | ifneq ($(CONFIG_X86_CMPXCHG64),y) | 36 | ifneq ($(CONFIG_X86_CMPXCHG64),y) |
35 | lib-y += cmpxchg8b_emu.o atomic64_386_32.o | 37 | lib-y += cmpxchg8b_emu.o atomic64_386_32.o |
@@ -40,7 +42,6 @@ else | |||
40 | lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o | 42 | lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o |
41 | lib-y += thunk_64.o clear_page_64.o copy_page_64.o | 43 | lib-y += thunk_64.o clear_page_64.o copy_page_64.o |
42 | lib-y += memmove_64.o memset_64.o | 44 | lib-y += memmove_64.o memset_64.o |
43 | lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o | 45 | lib-y += copy_user_64.o copy_user_nocache_64.o |
44 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o | ||
45 | lib-y += cmpxchg16b_emu.o | 46 | lib-y += cmpxchg16b_emu.o |
46 | endif | 47 | endif |
diff --git a/arch/x86/lib/rwlock.S b/arch/x86/lib/rwlock.S new file mode 100644 index 000000000000..1cad22139c88 --- /dev/null +++ b/arch/x86/lib/rwlock.S | |||
@@ -0,0 +1,44 @@ | |||
1 | /* Slow paths of read/write spinlocks. */ | ||
2 | |||
3 | #include <linux/linkage.h> | ||
4 | #include <asm/alternative-asm.h> | ||
5 | #include <asm/frame.h> | ||
6 | #include <asm/rwlock.h> | ||
7 | |||
8 | #ifdef CONFIG_X86_32 | ||
9 | # define __lock_ptr eax | ||
10 | #else | ||
11 | # define __lock_ptr rdi | ||
12 | #endif | ||
13 | |||
14 | ENTRY(__write_lock_failed) | ||
15 | CFI_STARTPROC | ||
16 | FRAME | ||
17 | 0: LOCK_PREFIX | ||
18 | WRITE_LOCK_ADD($RW_LOCK_BIAS) (%__lock_ptr) | ||
19 | 1: rep; nop | ||
20 | cmpl $WRITE_LOCK_CMP, (%__lock_ptr) | ||
21 | jne 1b | ||
22 | LOCK_PREFIX | ||
23 | WRITE_LOCK_SUB($RW_LOCK_BIAS) (%__lock_ptr) | ||
24 | jnz 0b | ||
25 | ENDFRAME | ||
26 | ret | ||
27 | CFI_ENDPROC | ||
28 | END(__write_lock_failed) | ||
29 | |||
30 | ENTRY(__read_lock_failed) | ||
31 | CFI_STARTPROC | ||
32 | FRAME | ||
33 | 0: LOCK_PREFIX | ||
34 | READ_LOCK_SIZE(inc) (%__lock_ptr) | ||
35 | 1: rep; nop | ||
36 | READ_LOCK_SIZE(cmp) $1, (%__lock_ptr) | ||
37 | js 1b | ||
38 | LOCK_PREFIX | ||
39 | READ_LOCK_SIZE(dec) (%__lock_ptr) | ||
40 | js 0b | ||
41 | ENDFRAME | ||
42 | ret | ||
43 | CFI_ENDPROC | ||
44 | END(__read_lock_failed) | ||
diff --git a/arch/x86/lib/rwlock_64.S b/arch/x86/lib/rwlock_64.S deleted file mode 100644 index 05ea55f71405..000000000000 --- a/arch/x86/lib/rwlock_64.S +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /* Slow paths of read/write spinlocks. */ | ||
2 | |||
3 | #include <linux/linkage.h> | ||
4 | #include <asm/rwlock.h> | ||
5 | #include <asm/alternative-asm.h> | ||
6 | #include <asm/dwarf2.h> | ||
7 | |||
8 | /* rdi: pointer to rwlock_t */ | ||
9 | ENTRY(__write_lock_failed) | ||
10 | CFI_STARTPROC | ||
11 | LOCK_PREFIX | ||
12 | addl $RW_LOCK_BIAS,(%rdi) | ||
13 | 1: rep | ||
14 | nop | ||
15 | cmpl $RW_LOCK_BIAS,(%rdi) | ||
16 | jne 1b | ||
17 | LOCK_PREFIX | ||
18 | subl $RW_LOCK_BIAS,(%rdi) | ||
19 | jnz __write_lock_failed | ||
20 | ret | ||
21 | CFI_ENDPROC | ||
22 | END(__write_lock_failed) | ||
23 | |||
24 | /* rdi: pointer to rwlock_t */ | ||
25 | ENTRY(__read_lock_failed) | ||
26 | CFI_STARTPROC | ||
27 | LOCK_PREFIX | ||
28 | incl (%rdi) | ||
29 | 1: rep | ||
30 | nop | ||
31 | cmpl $1,(%rdi) | ||
32 | js 1b | ||
33 | LOCK_PREFIX | ||
34 | decl (%rdi) | ||
35 | js __read_lock_failed | ||
36 | ret | ||
37 | CFI_ENDPROC | ||
38 | END(__read_lock_failed) | ||
diff --git a/arch/x86/lib/rwsem_64.S b/arch/x86/lib/rwsem.S index 67743977398b..5dff5f042468 100644 --- a/arch/x86/lib/rwsem_64.S +++ b/arch/x86/lib/rwsem.S | |||
@@ -1,4 +1,51 @@ | |||
1 | /* | 1 | /* |
2 | * x86 semaphore implementation. | ||
3 | * | ||
4 | * (C) Copyright 1999 Linus Torvalds | ||
5 | * | ||
6 | * Portions Copyright 1999 Red Hat, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org> | ||
14 | */ | ||
15 | |||
16 | #include <linux/linkage.h> | ||
17 | #include <asm/alternative-asm.h> | ||
18 | #include <asm/dwarf2.h> | ||
19 | |||
20 | #define __ASM_HALF_REG(reg) __ASM_SEL(reg, e##reg) | ||
21 | #define __ASM_HALF_SIZE(inst) __ASM_SEL(inst##w, inst##l) | ||
22 | |||
23 | #ifdef CONFIG_X86_32 | ||
24 | |||
25 | /* | ||
26 | * The semaphore operations have a special calling sequence that | ||
27 | * allow us to do a simpler in-line version of them. These routines | ||
28 | * need to convert that sequence back into the C sequence when | ||
29 | * there is contention on the semaphore. | ||
30 | * | ||
31 | * %eax contains the semaphore pointer on entry. Save the C-clobbered | ||
32 | * registers (%eax, %edx and %ecx) except %eax whish is either a return | ||
33 | * value or just clobbered.. | ||
34 | */ | ||
35 | |||
36 | #define save_common_regs \ | ||
37 | pushl_cfi %ecx; CFI_REL_OFFSET ecx, 0 | ||
38 | |||
39 | #define restore_common_regs \ | ||
40 | popl_cfi %ecx; CFI_RESTORE ecx | ||
41 | |||
42 | /* Avoid uglifying the argument copying x86-64 needs to do. */ | ||
43 | .macro movq src, dst | ||
44 | .endm | ||
45 | |||
46 | #else | ||
47 | |||
48 | /* | ||
2 | * x86-64 rwsem wrappers | 49 | * x86-64 rwsem wrappers |
3 | * | 50 | * |
4 | * This interfaces the inline asm code to the slow-path | 51 | * This interfaces the inline asm code to the slow-path |
@@ -16,12 +63,6 @@ | |||
16 | * but %rdi, %rsi, %rcx, %r8-r11 always need saving. | 63 | * but %rdi, %rsi, %rcx, %r8-r11 always need saving. |
17 | */ | 64 | */ |
18 | 65 | ||
19 | #include <linux/linkage.h> | ||
20 | #include <asm/rwlock.h> | ||
21 | #include <asm/alternative-asm.h> | ||
22 | #include <asm/frame.h> | ||
23 | #include <asm/dwarf2.h> | ||
24 | |||
25 | #define save_common_regs \ | 66 | #define save_common_regs \ |
26 | pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \ | 67 | pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \ |
27 | pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \ | 68 | pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \ |
@@ -40,16 +81,18 @@ | |||
40 | popq_cfi %rsi; CFI_RESTORE rsi; \ | 81 | popq_cfi %rsi; CFI_RESTORE rsi; \ |
41 | popq_cfi %rdi; CFI_RESTORE rdi | 82 | popq_cfi %rdi; CFI_RESTORE rdi |
42 | 83 | ||
84 | #endif | ||
85 | |||
43 | /* Fix up special calling conventions */ | 86 | /* Fix up special calling conventions */ |
44 | ENTRY(call_rwsem_down_read_failed) | 87 | ENTRY(call_rwsem_down_read_failed) |
45 | CFI_STARTPROC | 88 | CFI_STARTPROC |
46 | save_common_regs | 89 | save_common_regs |
47 | pushq_cfi %rdx | 90 | __ASM_SIZE(push,_cfi) %__ASM_REG(dx) |
48 | CFI_REL_OFFSET rdx, 0 | 91 | CFI_REL_OFFSET __ASM_REG(dx), 0 |
49 | movq %rax,%rdi | 92 | movq %rax,%rdi |
50 | call rwsem_down_read_failed | 93 | call rwsem_down_read_failed |
51 | popq_cfi %rdx | 94 | __ASM_SIZE(pop,_cfi) %__ASM_REG(dx) |
52 | CFI_RESTORE rdx | 95 | CFI_RESTORE __ASM_REG(dx) |
53 | restore_common_regs | 96 | restore_common_regs |
54 | ret | 97 | ret |
55 | CFI_ENDPROC | 98 | CFI_ENDPROC |
@@ -67,7 +110,8 @@ ENDPROC(call_rwsem_down_write_failed) | |||
67 | 110 | ||
68 | ENTRY(call_rwsem_wake) | 111 | ENTRY(call_rwsem_wake) |
69 | CFI_STARTPROC | 112 | CFI_STARTPROC |
70 | decl %edx /* do nothing if still outstanding active readers */ | 113 | /* do nothing if still outstanding active readers */ |
114 | __ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx) | ||
71 | jnz 1f | 115 | jnz 1f |
72 | save_common_regs | 116 | save_common_regs |
73 | movq %rax,%rdi | 117 | movq %rax,%rdi |
@@ -77,16 +121,15 @@ ENTRY(call_rwsem_wake) | |||
77 | CFI_ENDPROC | 121 | CFI_ENDPROC |
78 | ENDPROC(call_rwsem_wake) | 122 | ENDPROC(call_rwsem_wake) |
79 | 123 | ||
80 | /* Fix up special calling conventions */ | ||
81 | ENTRY(call_rwsem_downgrade_wake) | 124 | ENTRY(call_rwsem_downgrade_wake) |
82 | CFI_STARTPROC | 125 | CFI_STARTPROC |
83 | save_common_regs | 126 | save_common_regs |
84 | pushq_cfi %rdx | 127 | __ASM_SIZE(push,_cfi) %__ASM_REG(dx) |
85 | CFI_REL_OFFSET rdx, 0 | 128 | CFI_REL_OFFSET __ASM_REG(dx), 0 |
86 | movq %rax,%rdi | 129 | movq %rax,%rdi |
87 | call rwsem_downgrade_wake | 130 | call rwsem_downgrade_wake |
88 | popq_cfi %rdx | 131 | __ASM_SIZE(pop,_cfi) %__ASM_REG(dx) |
89 | CFI_RESTORE rdx | 132 | CFI_RESTORE __ASM_REG(dx) |
90 | restore_common_regs | 133 | restore_common_regs |
91 | ret | 134 | ret |
92 | CFI_ENDPROC | 135 | CFI_ENDPROC |
diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S deleted file mode 100644 index 06691daa4108..000000000000 --- a/arch/x86/lib/semaphore_32.S +++ /dev/null | |||
@@ -1,124 +0,0 @@ | |||
1 | /* | ||
2 | * i386 semaphore implementation. | ||
3 | * | ||
4 | * (C) Copyright 1999 Linus Torvalds | ||
5 | * | ||
6 | * Portions Copyright 1999 Red Hat, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org> | ||
14 | */ | ||
15 | |||
16 | #include <linux/linkage.h> | ||
17 | #include <asm/rwlock.h> | ||
18 | #include <asm/alternative-asm.h> | ||
19 | #include <asm/frame.h> | ||
20 | #include <asm/dwarf2.h> | ||
21 | |||
22 | /* | ||
23 | * The semaphore operations have a special calling sequence that | ||
24 | * allow us to do a simpler in-line version of them. These routines | ||
25 | * need to convert that sequence back into the C sequence when | ||
26 | * there is contention on the semaphore. | ||
27 | * | ||
28 | * %eax contains the semaphore pointer on entry. Save the C-clobbered | ||
29 | * registers (%eax, %edx and %ecx) except %eax whish is either a return | ||
30 | * value or just clobbered.. | ||
31 | */ | ||
32 | .section .sched.text, "ax" | ||
33 | |||
34 | /* | ||
35 | * rw spinlock fallbacks | ||
36 | */ | ||
37 | #ifdef CONFIG_SMP | ||
38 | ENTRY(__write_lock_failed) | ||
39 | CFI_STARTPROC | ||
40 | FRAME | ||
41 | 2: LOCK_PREFIX | ||
42 | addl $ RW_LOCK_BIAS,(%eax) | ||
43 | 1: rep; nop | ||
44 | cmpl $ RW_LOCK_BIAS,(%eax) | ||
45 | jne 1b | ||
46 | LOCK_PREFIX | ||
47 | subl $ RW_LOCK_BIAS,(%eax) | ||
48 | jnz 2b | ||
49 | ENDFRAME | ||
50 | ret | ||
51 | CFI_ENDPROC | ||
52 | ENDPROC(__write_lock_failed) | ||
53 | |||
54 | ENTRY(__read_lock_failed) | ||
55 | CFI_STARTPROC | ||
56 | FRAME | ||
57 | 2: LOCK_PREFIX | ||
58 | incl (%eax) | ||
59 | 1: rep; nop | ||
60 | cmpl $1,(%eax) | ||
61 | js 1b | ||
62 | LOCK_PREFIX | ||
63 | decl (%eax) | ||
64 | js 2b | ||
65 | ENDFRAME | ||
66 | ret | ||
67 | CFI_ENDPROC | ||
68 | ENDPROC(__read_lock_failed) | ||
69 | |||
70 | #endif | ||
71 | |||
72 | #ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM | ||
73 | |||
74 | /* Fix up special calling conventions */ | ||
75 | ENTRY(call_rwsem_down_read_failed) | ||
76 | CFI_STARTPROC | ||
77 | pushl_cfi %ecx | ||
78 | CFI_REL_OFFSET ecx,0 | ||
79 | pushl_cfi %edx | ||
80 | CFI_REL_OFFSET edx,0 | ||
81 | call rwsem_down_read_failed | ||
82 | popl_cfi %edx | ||
83 | popl_cfi %ecx | ||
84 | ret | ||
85 | CFI_ENDPROC | ||
86 | ENDPROC(call_rwsem_down_read_failed) | ||
87 | |||
88 | ENTRY(call_rwsem_down_write_failed) | ||
89 | CFI_STARTPROC | ||
90 | pushl_cfi %ecx | ||
91 | CFI_REL_OFFSET ecx,0 | ||
92 | calll rwsem_down_write_failed | ||
93 | popl_cfi %ecx | ||
94 | ret | ||
95 | CFI_ENDPROC | ||
96 | ENDPROC(call_rwsem_down_write_failed) | ||
97 | |||
98 | ENTRY(call_rwsem_wake) | ||
99 | CFI_STARTPROC | ||
100 | decw %dx /* do nothing if still outstanding active readers */ | ||
101 | jnz 1f | ||
102 | pushl_cfi %ecx | ||
103 | CFI_REL_OFFSET ecx,0 | ||
104 | call rwsem_wake | ||
105 | popl_cfi %ecx | ||
106 | 1: ret | ||
107 | CFI_ENDPROC | ||
108 | ENDPROC(call_rwsem_wake) | ||
109 | |||
110 | /* Fix up special calling conventions */ | ||
111 | ENTRY(call_rwsem_downgrade_wake) | ||
112 | CFI_STARTPROC | ||
113 | pushl_cfi %ecx | ||
114 | CFI_REL_OFFSET ecx,0 | ||
115 | pushl_cfi %edx | ||
116 | CFI_REL_OFFSET edx,0 | ||
117 | call rwsem_downgrade_wake | ||
118 | popl_cfi %edx | ||
119 | popl_cfi %ecx | ||
120 | ret | ||
121 | CFI_ENDPROC | ||
122 | ENDPROC(call_rwsem_downgrade_wake) | ||
123 | |||
124 | #endif | ||
diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S index 782b082c9ff7..a63efd6bb6a5 100644 --- a/arch/x86/lib/thunk_64.S +++ b/arch/x86/lib/thunk_64.S | |||
@@ -5,50 +5,41 @@ | |||
5 | * Added trace_hardirqs callers - Copyright 2007 Steven Rostedt, Red Hat, Inc. | 5 | * Added trace_hardirqs callers - Copyright 2007 Steven Rostedt, Red Hat, Inc. |
6 | * Subject to the GNU public license, v.2. No warranty of any kind. | 6 | * Subject to the GNU public license, v.2. No warranty of any kind. |
7 | */ | 7 | */ |
8 | #include <linux/linkage.h> | ||
9 | #include <asm/dwarf2.h> | ||
10 | #include <asm/calling.h> | ||
8 | 11 | ||
9 | #include <linux/linkage.h> | 12 | /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ |
10 | #include <asm/dwarf2.h> | 13 | .macro THUNK name, func, put_ret_addr_in_rdi=0 |
11 | #include <asm/calling.h> | ||
12 | #include <asm/rwlock.h> | ||
13 | |||
14 | /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ | ||
15 | .macro thunk name,func | ||
16 | .globl \name | ||
17 | \name: | ||
18 | CFI_STARTPROC | ||
19 | SAVE_ARGS | ||
20 | call \func | ||
21 | jmp restore | ||
22 | CFI_ENDPROC | ||
23 | .endm | ||
24 | |||
25 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
26 | /* put return address in rdi (arg1) */ | ||
27 | .macro thunk_ra name,func | ||
28 | .globl \name | 14 | .globl \name |
29 | \name: | 15 | \name: |
30 | CFI_STARTPROC | 16 | CFI_STARTPROC |
17 | |||
18 | /* this one pushes 9 elems, the next one would be %rIP */ | ||
31 | SAVE_ARGS | 19 | SAVE_ARGS |
32 | /* SAVE_ARGS pushs 9 elements */ | 20 | |
33 | /* the next element would be the rip */ | 21 | .if \put_ret_addr_in_rdi |
34 | movq 9*8(%rsp), %rdi | 22 | movq_cfi_restore 9*8, rdi |
23 | .endif | ||
24 | |||
35 | call \func | 25 | call \func |
36 | jmp restore | 26 | jmp restore |
37 | CFI_ENDPROC | 27 | CFI_ENDPROC |
38 | .endm | 28 | .endm |
39 | 29 | ||
40 | thunk_ra trace_hardirqs_on_thunk,trace_hardirqs_on_caller | 30 | #ifdef CONFIG_TRACE_IRQFLAGS |
41 | thunk_ra trace_hardirqs_off_thunk,trace_hardirqs_off_caller | 31 | THUNK trace_hardirqs_on_thunk,trace_hardirqs_on_caller,1 |
32 | THUNK trace_hardirqs_off_thunk,trace_hardirqs_off_caller,1 | ||
42 | #endif | 33 | #endif |
43 | 34 | ||
44 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 35 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
45 | thunk lockdep_sys_exit_thunk,lockdep_sys_exit | 36 | THUNK lockdep_sys_exit_thunk,lockdep_sys_exit |
46 | #endif | 37 | #endif |
47 | 38 | ||
48 | /* SAVE_ARGS below is used only for the .cfi directives it contains. */ | 39 | /* SAVE_ARGS below is used only for the .cfi directives it contains. */ |
49 | CFI_STARTPROC | 40 | CFI_STARTPROC |
50 | SAVE_ARGS | 41 | SAVE_ARGS |
51 | restore: | 42 | restore: |
52 | RESTORE_ARGS | 43 | RESTORE_ARGS |
53 | ret | 44 | ret |
54 | CFI_ENDPROC | 45 | CFI_ENDPROC |