#include "assym.h"
#include <sys/errno.h>
#include <sys/syscall.h>
#include <machine/asm.h>
#include <machine/codepatch.h>
#define DECLARE_ONFAULT(x) \
.pushsection .nofault.0, "a" ;\
.quad x ;\
.popsection
ENTRY(kcopy)
RETGUARD_SETUP(kcopy, r10)
movq CPUVAR(CURPCB),%rax
pushq PCB_ONFAULT(%rax)
leaq copy_fault(%rip),%r11
movq %r11, PCB_ONFAULT(%rax)
xchgq %rdi,%rsi
movq %rdx,%rcx
movq %rdi,%rax
subq %rsi,%rax
cmpq %rcx,%rax # overlapping?
jb 1f
shrq $3,%rcx # nope, copy forward by 64-bit words
rep
movsq
movq %rdx,%rcx
andl $7,%ecx # any bytes left?
rep
movsb
movq CPUVAR(CURPCB),%rdx
popq PCB_ONFAULT(%rdx)
xorq %rax,%rax
RETGUARD_CHECK(kcopy, r10)
ret
lfence
1: addq %rcx,%rdi # copy backward
addq %rcx,%rsi
std
andq $7,%rcx # any fractional bytes?
decq %rdi
decq %rsi
rep
movsb
movq %rdx,%rcx # copy remainder by 64-bit words
shrq $3,%rcx
subq $7,%rsi
subq $7,%rdi
rep
movsq
cld
movq CPUVAR(CURPCB),%rdx
popq PCB_ONFAULT(%rdx)
xorq %rax,%rax
RETGUARD_CHECK(kcopy, r10)
ret
lfence
ENTRY(copyout)
RETGUARD_SETUP(kcopy, r10)
movq CPUVAR(CURPCB),%rax
pushq PCB_ONFAULT(%rax)
xchgq %rdi,%rsi
movq %rdx,%rax
movq %rdi,%rdx
addq %rax,%rdx
jc copy_fault
movq $VM_MAXUSER_ADDRESS,%r8
cmpq %r8,%rdx
ja copy_fault
movq CPUVAR(CURPCB),%rdx
leaq copy_fault(%rip),%r11
movq %r11,PCB_ONFAULT(%rdx)
SMAP_STAC
movq %rax,%rcx
shrq $3,%rcx
rep
movsq
movb %al,%cl
shrb $2,%cl
andb $1,%cl
rep
movsl
movb %al,%cl
andb $3,%cl
rep
movsb
SMAP_CLAC
popq PCB_ONFAULT(%rdx)
xorl %eax,%eax
RETGUARD_CHECK(kcopy, r10)
ret
lfence
ENTRY(_copyin)
RETGUARD_SETUP(kcopy, r10)
movq CPUVAR(CURPCB),%rax
pushq PCB_ONFAULT(%rax)
leaq copy_fault(%rip),%r11
movq %r11,PCB_ONFAULT(%rax)
SMAP_STAC
xchgq %rdi,%rsi
movq %rdx,%rax
movq %rsi,%rdx
addq %rax,%rdx
jc copy_fault
movq $VM_MAXUSER_ADDRESS,%r8
cmpq %r8,%rdx
ja copy_fault
3:
movq %rax,%rcx
shrq $3,%rcx
rep
movsq
movb %al,%cl
shrb $2,%cl
andb $1,%cl
rep
movsl
movb %al,%cl
andb $3,%cl
rep
movsb
SMAP_CLAC
movq CPUVAR(CURPCB),%rdx
popq PCB_ONFAULT(%rdx)
xorl %eax,%eax
RETGUARD_CHECK(kcopy, r10)
ret
lfence
NENTRY(copy_fault)
DECLARE_ONFAULT(copy_fault)
cld
SMAP_CLAC
movq CPUVAR(CURPCB),%rdx
popq PCB_ONFAULT(%rdx)
movl $EFAULT,%eax
RETGUARD_CHECK(kcopy, r10)
ret
lfence
ENTRY(copyoutstr)
RETGUARD_SETUP(copyoutstr, r10)
xchgq %rdi,%rsi
movq %rdx,%r8
movq %rcx,%r9
movq CPUVAR(CURPCB),%rax
pushq PCB_ONFAULT(%rax)
leaq copystr_fault(%rip),%r11
movq %r11,PCB_ONFAULT(%rax)
SMAP_STAC
movq $VM_MAXUSER_ADDRESS,%rax
subq %rdi,%rax
jbe copystr_fault
cmpq %rdx,%rax
jae 1f
movq %rax,%rdx
movq %rax,%r8
1: incq %rdx
1: decq %rdx
jz 2f
lodsb
stosb
testb %al,%al
jnz 1b
decq %rdx
xorq %rax,%rax
jmp copystr_return
2:
movq $VM_MAXUSER_ADDRESS,%r11
cmpq %r11,%rdi
jae copystr_fault
movl $ENAMETOOLONG,%eax
jmp copystr_return
ENTRY(_copyinstr)
RETGUARD_SETUP(copyoutstr, r10)
xchgq %rdi,%rsi
movq %rdx,%r8
movq %rcx,%r9
movq CPUVAR(CURPCB),%rcx
pushq PCB_ONFAULT(%rcx)
leaq copystr_fault(%rip),%r11
movq %r11,PCB_ONFAULT(%rcx)
SMAP_STAC
movq $VM_MAXUSER_ADDRESS,%rax
subq %rsi,%rax
jbe copystr_fault
cmpq %rdx,%rax
jae 1f
movq %rax,%rdx
movq %rax,%r8
1: incq %rdx
1: decq %rdx
jz 2f
lodsb
stosb
testb %al,%al
jnz 1b
decq %rdx
xorq %rax,%rax
jmp copystr_return
2:
movq $VM_MAXUSER_ADDRESS,%r11
cmpq %r11,%rsi
jae copystr_fault
movl $ENAMETOOLONG,%eax
jmp copystr_return
ENTRY(copystr_fault)
DECLARE_ONFAULT(copystr_fault)
movl $EFAULT,%eax
copystr_return:
SMAP_CLAC
movq CPUVAR(CURPCB),%rcx
popq PCB_ONFAULT(%rcx)
testq %r9,%r9
jz 8f
subq %rdx,%r8
movq %r8,(%r9)
8:
RETGUARD_CHECK(copyoutstr, r10)
ret
lfence
CODEPATCH_CODE(_stac, stac)
CODEPATCH_CODE(_clac, clac)