#include <machine/asm.h>
__KERNEL_RCSID(0, "$NetBSD: copy.S,v 1.32 2020/06/30 16:20:01 maxv Exp $");
#include "assym.h"
#include <sys/errno.h>
#include <machine/frameasm.h>
#include <machine/cputypes.h>
#define GET_CURPCB(reg) \
movl CPUVAR(CURLWP),reg; \
movl L_PCB(reg),reg
#define DEFERRED_SWITCH_CHECK \
CHECK_DEFERRED_SWITCH ; \
jnz 99f ; \
98:
#define DEFERRED_SWITCH_CALL \
99: ; \
call _C_LABEL(do_pmap_load) ; \
jmp 98b
.text
LABEL(x86_copyfunc_start)
ENTRY(do_pmap_load)
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl CPUVAR(CURLWP),%ebx
1:
incl L_NOPREEMPT(%ebx)
call _C_LABEL(pmap_load)
decl L_NOPREEMPT(%ebx)
jnz 2f
cmpl $0,L_DOPREEMPT(%ebx)
jz 2f
pushl $0
call _C_LABEL(kpreempt)
addl $4,%esp
2:
cmpl $0,CPUVAR(WANT_PMAPLOAD)
jnz 1b
popl %ebx
leave
ret
END(do_pmap_load)
ENTRY(return_address)
movl %ebp,%eax
movl 4(%esp),%ecx
movl CPUVAR(CURLWP),%edx
movl L_PCB(%edx),%edx
movl $_C_LABEL(return_address_fault),PCB_ONFAULT(%edx)
cmpl $0,%ecx
je 2f
1:
movl (%eax),%eax
decl %ecx
jnz 1b
2:
movl 0x4(%eax),%eax
movl $0,PCB_ONFAULT(%edx)
ret
END(return_address)
ENTRY(kcopy)
pushl %esi
pushl %edi
movl 12(%esp),%esi
movl 16(%esp),%edi
movl 20(%esp),%ecx
.Lkcopy_start:
movl %edi,%eax
subl %esi,%eax
cmpl %ecx,%eax
movl %ecx,%edx
jb 1f
shrl $2,%ecx
rep
movsl
movl %edx,%ecx
andl $3,%ecx
jz 0f
rep
movsb
0:
popl %edi
popl %esi
xorl %eax,%eax
ret
ALIGN_TEXT
1: addl %ecx,%edi
addl %ecx,%esi
std
andl $3,%ecx
decl %edi
decl %esi
rep
movsb
movl %edx,%ecx
shrl $2,%ecx
subl $3,%esi
subl $3,%edi
rep
movsl
cld
.Lkcopy_end:
popl %edi
popl %esi
xorl %eax,%eax
ret
END(kcopy)
ENTRY(copyout)
DEFERRED_SWITCH_CHECK
pushl %esi
pushl %edi
movl 12(%esp),%esi
movl 16(%esp),%edi
movl 20(%esp),%eax
movl %edi,%edx
addl %eax,%edx
jc _C_LABEL(copy_efault)
cmpl $VM_MAXUSER_ADDRESS,%edx
ja _C_LABEL(copy_efault)
SMAP_DISABLE
.Lcopyout_start:
movl %eax,%ecx
shrl $2,%ecx
rep
movsl
andl $3,%eax
jz .Lcopyout_end
movl %eax,%ecx
rep
movsb
.Lcopyout_end:
SMAP_ENABLE
popl %edi
popl %esi
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(copyout)
ENTRY(copyin)
DEFERRED_SWITCH_CHECK
pushl %esi
pushl %edi
movl 12(%esp),%esi
movl 16(%esp),%edi
movl 20(%esp),%eax
movl %esi,%edx
addl %eax,%edx
jc _C_LABEL(copy_efault)
cmpl $VM_MAXUSER_ADDRESS,%edx
ja _C_LABEL(copy_efault)
SMAP_DISABLE
.Lcopyin_start:
movl %eax,%ecx
shrl $2,%ecx
rep
movsl
andl $3,%eax
jz .Lcopyin_end
movl %eax,%ecx
rep
movsb
.Lcopyin_end:
SMAP_ENABLE
popl %edi
popl %esi
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(copyin)
ENTRY(copy_efault)
movl $EFAULT,%eax
popl %edi
popl %esi
ret
END(copy_efault)
ENTRY(kcopy_fault)
cld
popl %edi
popl %esi
ret
END(kcopy_fault)
ENTRY(copy_fault)
SMAP_ENABLE
popl %edi
popl %esi
ret
END(copy_fault)
ENTRY(return_address_fault)
movl $0,PCB_ONFAULT(%edx)
movl $0,%eax
ret
END(return_address_fault)
ENTRY(copyoutstr)
DEFERRED_SWITCH_CHECK
pushl %esi
pushl %edi
movl 12(%esp),%esi
movl 16(%esp),%edi
movl 20(%esp),%edx
movl $VM_MAXUSER_ADDRESS,%eax
subl %edi,%eax
jc _C_LABEL(copystr_efault)
cmpl %edx,%eax
jae 1f
movl %eax,%edx
movl %eax,20(%esp)
1: incl %edx
SMAP_DISABLE
.Lcopyoutstr_start:
1: decl %edx
jz 2f
lodsb
stosb
testb %al,%al
jnz 1b
.Lcopyoutstr_end:
SMAP_ENABLE
decl %edx
xorl %eax,%eax
jmp copystr_return
2:
SMAP_ENABLE
cmpl $VM_MAXUSER_ADDRESS,%edi
jae _C_LABEL(copystr_efault)
movl $ENAMETOOLONG,%eax
jmp copystr_return
DEFERRED_SWITCH_CALL
END(copyoutstr)
ENTRY(copyinstr)
DEFERRED_SWITCH_CHECK
pushl %esi
pushl %edi
movl 12(%esp),%esi
movl 16(%esp),%edi
movl 20(%esp),%edx
movl $VM_MAXUSER_ADDRESS,%eax
subl %esi,%eax
jc _C_LABEL(copystr_efault)
cmpl %edx,%eax
jae 1f
movl %eax,%edx
movl %eax,20(%esp)
1: incl %edx
SMAP_DISABLE
.Lcopyinstr_start:
1: decl %edx
jz 2f
lodsb
stosb
testb %al,%al
jnz 1b
.Lcopyinstr_end:
SMAP_ENABLE
decl %edx
xorl %eax,%eax
jmp copystr_return
2:
SMAP_ENABLE
cmpl $VM_MAXUSER_ADDRESS,%esi
jae _C_LABEL(copystr_efault)
movl $ENAMETOOLONG,%eax
jmp copystr_return
DEFERRED_SWITCH_CALL
END(copyinstr)
ENTRY(copystr_efault)
movl $EFAULT,%eax
jmp copystr_return
END(copystr_efault)
ENTRY(copystr_fault)
SMAP_ENABLE
copystr_return:
movl 20(%esp),%ecx
subl %edx,%ecx
movl 24(%esp),%edx
testl %edx,%edx
jz 8f
movl %ecx,(%edx)
8: popl %edi
popl %esi
ret
END(copystr_fault)
#define UFETCHSTORE_PROLOGUE(x) \
movl 4(%esp),%edx ; \
cmpl $VM_MAXUSER_ADDRESS-x,%edx ; \
ja _C_LABEL(ufetchstore_efault)
ENTRY(_ufetch_8)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(1)
SMAP_DISABLE
.L_ufetch_8_start:
movb (%edx),%al
.L_ufetch_8_end:
SMAP_ENABLE
movl 8(%esp),%edx
movb %al,(%edx)
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_8)
ENTRY(_ufetch_16)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(2)
SMAP_DISABLE
.L_ufetch_16_start:
movw (%edx),%ax
.L_ufetch_16_end:
SMAP_ENABLE
movl 8(%esp),%edx
movw %ax,(%edx)
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_16)
ENTRY(_ufetch_32)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(4)
SMAP_DISABLE
.L_ufetch_32_start:
movl (%edx),%eax
.L_ufetch_32_end:
SMAP_ENABLE
movl 8(%esp),%edx
movl %eax,(%edx)
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_32)
ENTRY(_ustore_8)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(1)
movb 8(%esp),%al
SMAP_DISABLE
.L_ustore_8_start:
movb %al,(%edx)
.L_ustore_8_end:
SMAP_ENABLE
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ustore_8)
ENTRY(_ustore_16)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(2)
movw 8(%esp),%ax
SMAP_DISABLE
.L_ustore_16_start:
movw %ax,(%edx)
.L_ustore_16_end:
SMAP_ENABLE
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ustore_16)
ENTRY(_ustore_32)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(4)
movl 8(%esp),%eax
SMAP_DISABLE
.L_ustore_32_start:
movl %eax,(%edx)
.L_ustore_32_end:
SMAP_ENABLE
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ustore_32)
ENTRY(ufetchstore_efault)
movl $EFAULT,%eax
ret
END(ufetchstore_efault)
ENTRY(ufetchstore_fault)
SMAP_ENABLE
ret
END(ufetchstore_fault)
ENTRY(_ucas_32)
DEFERRED_SWITCH_CHECK
movl 4(%esp),%edx
movl 8(%esp),%eax
movl 12(%esp),%ecx
cmpl $VM_MAXUSER_ADDRESS-4,%edx
ja _C_LABEL(ucas_efault)
SMAP_DISABLE
.Lucas32_start:
lock
cmpxchgl %ecx,(%edx)
.Lucas32_end:
SMAP_ENABLE
movl 16(%esp),%edx
movl %eax,(%edx)
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(_ucas_32)
ENTRY(ucas_efault)
movl $EFAULT,%eax
ret
END(ucas_efault)
ENTRY(ucas_fault)
SMAP_ENABLE
ret
END(ucas_fault)
ENTRY(x86_copyargs)
DEFERRED_SWITCH_CHECK
pushl %esi
movl 8(%esp),%esi
movl 12(%esp),%edx
movl 16(%esp),%ecx
movl %esi,%eax
addl $(10 * 4),%eax
jc _C_LABEL(x86_copyargs_efault)
cmpl $VM_MAXUSER_ADDRESS,%eax
ja _C_LABEL(x86_copyargs_efault)
SMAP_DISABLE
.Lx86_copyargs_start:
cmp $16,%ecx
movl (%esi),%eax
movl 4(%esi),%ecx
movl %eax,(%edx)
movl %ecx,4(%edx)
movl 8(%esi),%eax
movl 12(%esi),%ecx
movl %eax,8(%edx)
movl %ecx,12(%edx)
ja 2f
jmp .Lx86_copyargs_end
2:
movl 16(%esi),%eax
movl 20(%esi),%ecx
movl %eax,16(%edx)
movl %ecx,20(%edx)
movl 24(%esi),%eax
movl 28(%esi),%ecx
movl %eax,24(%edx)
movl %ecx,28(%edx)
movl 32(%esi),%eax
movl 36(%esi),%ecx
movl %eax,32(%edx)
movl %ecx,36(%edx)
.Lx86_copyargs_end:
SMAP_ENABLE
popl %esi
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(x86_copyargs)
ENTRY(x86_copyargs_efault)
movl $EFAULT,%eax
popl %esi
ret
END(x86_copyargs_efault)
ENTRY(x86_copyargs_fault)
SMAP_ENABLE
popl %esi
ret
END(x86_copyargs_fault)
LABEL(x86_copyfunc_end)
.section ".rodata"
.globl _C_LABEL(onfault_table)
_C_LABEL(onfault_table):
.long .Lcopyin_start
.long .Lcopyin_end
.long _C_LABEL(copy_fault)
.long .Lcopyout_start
.long .Lcopyout_end
.long _C_LABEL(copy_fault)
.long .Lkcopy_start
.long .Lkcopy_end
.long _C_LABEL(kcopy_fault)
.long .Lcopyoutstr_start
.long .Lcopyoutstr_end
.long _C_LABEL(copystr_fault)
.long .Lcopyinstr_start
.long .Lcopyinstr_end
.long _C_LABEL(copystr_fault)
.long .Lucas32_start
.long .Lucas32_end
.long _C_LABEL(ucas_fault)
.long .L_ufetch_8_start
.long .L_ufetch_8_end
.long _C_LABEL(ufetchstore_fault)
.long .L_ufetch_16_start
.long .L_ufetch_16_end
.long _C_LABEL(ufetchstore_fault)
.long .L_ufetch_32_start
.long .L_ufetch_32_end
.long _C_LABEL(ufetchstore_fault)
.long .L_ustore_8_start
.long .L_ustore_8_end
.long _C_LABEL(ufetchstore_fault)
.long .L_ustore_16_start
.long .L_ustore_16_end
.long _C_LABEL(ufetchstore_fault)
.long .L_ustore_32_start
.long .L_ustore_32_end
.long _C_LABEL(ufetchstore_fault)
.long .Lx86_copyargs_start
.long .Lx86_copyargs_end
.long _C_LABEL(x86_copyargs_fault)
.long 0
.text