#include <machine/asm.h>
__KERNEL_RCSID(0, "$NetBSD: lock_stubs.S,v 1.38 2022/09/08 06:57:44 knakahara Exp $");
#include "opt_lockdebug.h"
#include <machine/cputypes.h>
#include <machine/frameasm.h>
#include "assym.h"
#define ALIGN64 .align 64
#define ALIGN32 .align 32
#define LOCK(num) \
HOTPATCH(HP_NAME_NOLOCK, 1) ; \
lock
#define RET(num) \
HOTPATCH(HP_NAME_RETFENCE, 3) ; \
ret; nop; nop ; \
ret
#define ENDLABEL(name,a) .align a; LABEL(name)
#if !defined(LOCKDEBUG)
ALIGN64
ENTRY(mutex_enter)
movl 4(%esp), %edx
xorl %eax, %eax
movl %fs:CPU_INFO_CURLWP(%eax), %ecx
LOCK(1)
cmpxchgl %ecx, (%edx)
jnz 1f
RET(1)
1:
jmp _C_LABEL(mutex_vector_enter)
END(mutex_enter)
ENTRY(mutex_exit)
movl 4(%esp), %edx
xorl %ecx, %ecx
movl %fs:CPU_INFO_CURLWP(%ecx), %eax
cmpxchgl %ecx, (%edx)
jnz 1f
ret
1:
jmp _C_LABEL(mutex_vector_exit)
END(mutex_exit)
ENTRY(rw_enter)
movl 4(%esp), %edx
cmpl $RW_READER, 8(%esp)
jne 2f
movl (%edx), %eax
0:
testb $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
jnz 3f
leal RW_READ_INCR(%eax), %ecx
LOCK(2)
cmpxchgl %ecx, (%edx)
jnz 1f
RET(2)
1:
jmp 0b
2: xorl %eax, %eax
movl %fs:CPU_INFO_CURLWP(%eax), %ecx
orl $RW_WRITE_LOCKED, %ecx
LOCK(3)
cmpxchgl %ecx, (%edx)
jnz 3f
RET(3)
3:
jmp _C_LABEL(rw_vector_enter)
END(rw_enter)
ENTRY(rw_exit)
movl 4(%esp), %edx
movl (%edx), %eax
testb $RW_WRITE_LOCKED, %al
jnz 2f
0: testb $RW_HAS_WAITERS, %al
jnz 3f
cmpl $RW_READ_INCR, %eax
jb 3f
leal -RW_READ_INCR(%eax), %ecx
LOCK(4)
cmpxchgl %ecx, (%edx)
jnz 1f
ret
1:
jmp 0b
2: leal -RW_WRITE_LOCKED(%eax), %ecx
subl CPUVAR(CURLWP), %ecx
jnz 3f
LOCK(5)
cmpxchgl %ecx, (%edx)
jnz 3f
ret
3: jmp _C_LABEL(rw_vector_exit)
END(rw_exit)
ENTRY(rw_tryenter)
movl 4(%esp), %edx
cmpl $RW_READER, 8(%esp)
jne 2f
movl (%edx), %eax
0:
testb $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
jnz 4f
leal RW_READ_INCR(%eax), %ecx
LOCK(12)
cmpxchgl %ecx, (%edx)
jnz 1f
movl %edx, %eax
RET(4)
1:
jmp 0b
2:
xorl %eax, %eax
movl %fs:CPU_INFO_CURLWP(%eax), %ecx
orl $RW_WRITE_LOCKED, %ecx
LOCK(13)
cmpxchgl %ecx, (%edx)
movl $0, %eax
setz %al
3:
RET(5)
4:
xorl %eax, %eax
jmp 3b
END(rw_tryenter)
ENTRY(mutex_spin_enter)
movl 4(%esp), %edx
movb CPUVAR(ILEVEL), %cl
movb MTX_IPL(%edx), %ch
movl $0x01, %eax
cmpb %ch, %cl
jg 1f
movb %ch, CPUVAR(ILEVEL)
1:
subl %eax, CPUVAR(MTX_COUNT)
jnc 2f
movb %cl, CPUVAR(MTX_OLDSPL)
2:
xchgb %al, MTX_LOCK(%edx)
testb %al, %al
jnz 3f
RET(6)
3:
jmp _C_LABEL(mutex_spin_retry)
ALIGN64
LABEL(mutex_spin_enter_end)
END(mutex_spin_enter)
#ifndef XENPV
ENTRY(mutex_spin_exit)
HOTPATCH(HP_NAME_MUTEX_EXIT, 128)
movl 4(%esp), %edx
movl CPUVAR(MTX_OLDSPL), %ecx
incl CPUVAR(MTX_COUNT)
movb $0, MTX_LOCK(%edx)
jnz 1f
movl CPUVAR(IUNMASK)(,%ecx,8), %edx
movl CPUVAR(IUNMASK)+4(,%ecx,8), %eax
cli
testl CPUVAR(IPENDING), %edx
movl %ecx, 4(%esp)
jnz _C_LABEL(Xspllower)
testl CPUVAR(IPENDING)+4, %eax
jnz _C_LABEL(Xspllower)
movb %cl, CPUVAR(ILEVEL)
sti
1: ret
.space 32, 0xCC
.align 32
END(mutex_spin_exit)
#else
STRONG_ALIAS(mutex_spin_exit, i686_mutex_spin_exit)
#endif
ENTRY(i686_mutex_spin_exit)
mov 4(%esp),%edx
movl CPUVAR(MTX_OLDSPL), %ecx
incl CPUVAR(MTX_COUNT)
movb $0, MTX_LOCK(%edx)
jnz 1f
pushl %ebx
pushl %esi
pushl %edi
movl %ecx, %esi
movl %ecx, %edi
shll $24, %edi
0:
movl CPUVAR(IPENDING), %eax
testl %eax, CPUVAR(IUNMASK)(,%esi,8)
jnz 2f
movl CPUVAR(IPENDING)+4, %edx
testl %edx, CPUVAR(IUNMASK)+4(,%esi,8)
jnz 2f
movl %eax, %ebx
movl %edx, %ecx
andl $0x00ffffff, %ecx
orl %edi, %ecx
cmpxchg8b CPUVAR(ISTATE)
jnz 0b
popl %edi
popl %esi
popl %ebx
1:
ret
2:
movl %esi,%ecx
popl %edi
popl %esi
popl %ebx
movl %ecx,4(%esp)
movl $Xspllower,%eax
jmp *%eax
.space 16, 0xCC
.align 32
LABEL(i686_mutex_spin_exit_end)
END(i686_mutex_spin_exit)
#endif
ENTRY(__cpu_simple_lock_init)
movl 4(%esp), %edx
movb $0, (%edx)
ret
END(__cpu_simple_lock_init)
ENTRY(__cpu_simple_lock)
movl 4(%esp), %edx
movl $0x0100, %eax
1:
LOCK(6)
cmpxchgb %ah, (%edx)
jnz 2f
RET(7)
2:
movl $0x0100, %eax
pause
nop
nop
cmpb $0, (%edx)
je 1b
jmp 2b
END(__cpu_simple_lock)
ENTRY(__cpu_simple_unlock)
movl 4(%esp), %edx
movb $0, (%edx)
ret
END(__cpu_simple_unlock)
ENTRY(__cpu_simple_lock_try)
movl 4(%esp), %edx
movl $0x0100, %eax
LOCK(7)
cmpxchgb %ah, (%edx)
movl $0, %eax
setz %al
RET(8)
END(__cpu_simple_lock_try)