mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 06:18:54 +00:00 
			
		
		
		
	 a66f6375bd
			
		
	
	
		a66f6375bd
		
	
	
	
	
		
			
			The x86_64 call_rwsem_wait() treats the active state counter part of the R/W semaphore state as being 16-bit when it's actually 32-bit (it's half of the 64-bit state). It should do "decl %edx" not "decw %dx". Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
			
				
	
	
		
			82 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * x86-64 rwsem wrappers
 | |
|  *
 | |
|  * This interfaces the inline asm code to the slow-path
 | |
|  * C routines. We need to save the call-clobbered regs
 | |
|  * that the asm does not mark as clobbered, and move the
 | |
|  * argument from %rax to %rdi.
 | |
|  *
 | |
|  * NOTE! We don't need to save %rax, because the functions
 | |
|  * will always return the semaphore pointer in %rax (which
 | |
|  * is also the input argument to these helpers)
 | |
|  *
 | |
|  * The following can clobber %rdx because the asm clobbers it:
 | |
|  *   call_rwsem_down_write_failed
 | |
|  *   call_rwsem_wake
 | |
|  * but %rdi, %rsi, %rcx, %r8-r11 always need saving.
 | |
|  */
 | |
| 
 | |
| #include <linux/linkage.h>
 | |
| #include <asm/rwlock.h>
 | |
| #include <asm/alternative-asm.h>
 | |
| #include <asm/frame.h>
 | |
| #include <asm/dwarf2.h>
 | |
| 
 | |
| #define save_common_regs \
 | |
| 	pushq %rdi; \
 | |
| 	pushq %rsi; \
 | |
| 	pushq %rcx; \
 | |
| 	pushq %r8; \
 | |
| 	pushq %r9; \
 | |
| 	pushq %r10; \
 | |
| 	pushq %r11
 | |
| 
 | |
| #define restore_common_regs \
 | |
| 	popq %r11; \
 | |
| 	popq %r10; \
 | |
| 	popq %r9; \
 | |
| 	popq %r8; \
 | |
| 	popq %rcx; \
 | |
| 	popq %rsi; \
 | |
| 	popq %rdi
 | |
| 
 | |
| /* Fix up special calling conventions */
 | |
| ENTRY(call_rwsem_down_read_failed)
 | |
| 	save_common_regs
 | |
| 	pushq %rdx
 | |
| 	movq %rax,%rdi
 | |
| 	call rwsem_down_read_failed
 | |
| 	popq %rdx
 | |
| 	restore_common_regs
 | |
| 	ret
 | |
| 	ENDPROC(call_rwsem_down_read_failed)
 | |
| 
 | |
| ENTRY(call_rwsem_down_write_failed)
 | |
| 	save_common_regs
 | |
| 	movq %rax,%rdi
 | |
| 	call rwsem_down_write_failed
 | |
| 	restore_common_regs
 | |
| 	ret
 | |
| 	ENDPROC(call_rwsem_down_write_failed)
 | |
| 
 | |
| ENTRY(call_rwsem_wake)
 | |
| 	decl %edx	/* do nothing if still outstanding active readers */
 | |
| 	jnz 1f
 | |
| 	save_common_regs
 | |
| 	movq %rax,%rdi
 | |
| 	call rwsem_wake
 | |
| 	restore_common_regs
 | |
| 1:	ret
 | |
| 	ENDPROC(call_rwsem_wake)
 | |
| 
 | |
| /* Fix up special calling conventions */
 | |
| ENTRY(call_rwsem_downgrade_wake)
 | |
| 	save_common_regs
 | |
| 	pushq %rdx
 | |
| 	movq %rax,%rdi
 | |
| 	call rwsem_downgrade_wake
 | |
| 	popq %rdx
 | |
| 	restore_common_regs
 | |
| 	ret
 | |
| 	ENDPROC(call_rwsem_downgrade_wake)
 |