#include "assym.h"
#include <sys/errno.h>
#include <sys/syscall.h>
#include <machine/asm.h>
#include <machine/frameasm.h>
#define GET_CURPCB(reg) \
movq CPUVAR(CURLWP),reg; \
movq 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
x86_copyfunc_start: .globl x86_copyfunc_start
ENTRY(do_pmap_load)
pushq %rbp
movq %rsp,%rbp
pushq %rdi
pushq %rsi
pushq %rdx
pushq %rcx
pushq %rbx
movq CPUVAR(CURLWP),%rbx
1:
incl L_NOPREEMPT(%rbx)
call _C_LABEL(pmap_load)
decl L_NOPREEMPT(%rbx)
jnz 2f
cmpl $0,L_DOPREEMPT(%rbx)
jz 2f
xorq %rdi,%rdi
call _C_LABEL(kpreempt)
2:
cmpl $0,CPUVAR(WANT_PMAPLOAD)
jnz 1b
popq %rbx
popq %rcx
popq %rdx
popq %rsi
popq %rdi
leaveq
ret
END(do_pmap_load)
ENTRY(kcopy)
xchgq %rdi,%rsi
movq %rdx,%rcx
.Lkcopy_start:
movq %rdi,%rax
subq %rsi,%rax
cmpq %rcx,%rax
jb 1f
shrq $3,%rcx
rep
movsq
movq %rdx,%rcx
andl $7,%ecx
rep
movsb
xorq %rax,%rax
ret
1: addq %rcx,%rdi
addq %rcx,%rsi
std
andq $7,%rcx
decq %rdi
decq %rsi
rep
movsb
movq %rdx,%rcx
shrq $3,%rcx
subq $7,%rsi
subq $7,%rdi
rep
movsq
cld
.Lkcopy_end:
xorq %rax,%rax
ret
END(kcopy)
ENTRY(copyout)
DEFERRED_SWITCH_CHECK
xchgq %rdi,%rsi
movq %rdx,%rax
addq %rdi,%rdx
jc _C_LABEL(copy_efault)
movq $VM_MAXUSER_ADDRESS,%r8
cmpq %r8,%rdx
ja _C_LABEL(copy_efault)
SMAP_DISABLE
.Lcopyout_start:
movq %rax,%rcx
shrq $3,%rcx
rep
movsq
movb %al,%cl
andb $7,%cl
rep
movsb
.Lcopyout_end:
SMAP_ENABLE
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(copyout)
ENTRY(copyin)
DEFERRED_SWITCH_CHECK
xchgq %rdi,%rsi
movq %rdx,%rax
addq %rsi,%rdx
jc _C_LABEL(copy_efault)
movq $VM_MAXUSER_ADDRESS,%r8
cmpq %r8,%rdx
ja _C_LABEL(copy_efault)
SMAP_DISABLE
.Lcopyin_start:
3:
movq %rax,%rcx
shrq $3,%rcx
rep
movsq
movb %al,%cl
andb $7,%cl
rep
movsb
.Lcopyin_end:
SMAP_ENABLE
xorl %eax,%eax
ret
DEFERRED_SWITCH_CALL
END(copyin)
ENTRY(copy_efault)
movq $EFAULT,%rax
ret
END(copy_efault)
ENTRY(kcopy_fault)
cld
ret
END(kcopy_fault)
ENTRY(copy_fault)
SMAP_ENABLE
ret
END(copy_fault)
ENTRY(copyoutstr)
DEFERRED_SWITCH_CHECK
xchgq %rdi,%rsi
movq %rdx,%r8
movq %rcx,%r9
movq $VM_MAXUSER_ADDRESS,%rax
subq %rdi,%rax
jc _C_LABEL(copystr_efault)
cmpq %rdx,%rax
jae 1f
movq %rax,%rdx
movq %rax,%r8
1: incq %rdx
SMAP_DISABLE
.Lcopyoutstr_start:
1: decq %rdx
jz 2f
lodsb
stosb
testb %al,%al
jnz 1b
.Lcopyoutstr_end:
SMAP_ENABLE
decq %rdx
xorq %rax,%rax
jmp copystr_return
2:
SMAP_ENABLE
movq $VM_MAXUSER_ADDRESS,%r11
cmpq %r11,%rdi
jae _C_LABEL(copystr_efault)
movq $ENAMETOOLONG,%rax
jmp copystr_return
DEFERRED_SWITCH_CALL
END(copyoutstr)
ENTRY(copyinstr)
DEFERRED_SWITCH_CHECK
xchgq %rdi,%rsi
movq %rdx,%r8
movq %rcx,%r9
movq $VM_MAXUSER_ADDRESS,%rax
subq %rsi,%rax
jc _C_LABEL(copystr_efault)
cmpq %rdx,%rax
jae 1f
movq %rax,%rdx
movq %rax,%r8
1: incq %rdx
SMAP_DISABLE
.Lcopyinstr_start:
1: decq %rdx
jz 2f
lodsb
stosb
testb %al,%al
jnz 1b
.Lcopyinstr_end:
SMAP_ENABLE
decq %rdx
xorq %rax,%rax
jmp copystr_return
2:
SMAP_ENABLE
movq $VM_MAXUSER_ADDRESS,%r11
cmpq %r11,%rsi
jae _C_LABEL(copystr_efault)
movq $ENAMETOOLONG,%rax
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:
testq %r9,%r9
jz 8f
subq %rdx,%r8
movq %r8,(%r9)
8: ret
END(copystr_fault)
#define UFETCHSTORE_PROLOGUE(x) \
movq $VM_MAXUSER_ADDRESS-x,%r11 ; \
cmpq %r11,%rdi ; \
ja _C_LABEL(copy_efault)
ENTRY(_ufetch_8)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(1)
SMAP_DISABLE
.L_ufetch_8_start:
movb (%rdi),%al
.L_ufetch_8_end:
SMAP_ENABLE
movb %al,(%rsi)
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_8)
ENTRY(_ufetch_16)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(2)
SMAP_DISABLE
.L_ufetch_16_start:
movw (%rdi),%ax
.L_ufetch_16_end:
SMAP_ENABLE
movw %ax,(%rsi)
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_16)
ENTRY(_ufetch_32)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(4)
SMAP_DISABLE
.L_ufetch_32_start:
movl (%rdi),%eax
.L_ufetch_32_end:
SMAP_ENABLE
movl %eax,(%rsi)
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_32)
ENTRY(_ufetch_64)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(8)
SMAP_DISABLE
.L_ufetch_64_start:
movq (%rdi),%rax
.L_ufetch_64_end:
SMAP_ENABLE
movq %rax,(%rsi)
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ufetch_64)
ENTRY(_ustore_8)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(1)
SMAP_DISABLE
.L_ustore_8_start:
movb %sil,(%rdi)
.L_ustore_8_end:
SMAP_ENABLE
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ustore_8)
ENTRY(_ustore_16)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(2)
SMAP_DISABLE
.L_ustore_16_start:
movw %si,(%rdi)
.L_ustore_16_end:
SMAP_ENABLE
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ustore_16)
ENTRY(_ustore_32)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(4)
SMAP_DISABLE
.L_ustore_32_start:
movl %esi,(%rdi)
.L_ustore_32_end:
SMAP_ENABLE
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ustore_32)
ENTRY(_ustore_64)
DEFERRED_SWITCH_CHECK
UFETCHSTORE_PROLOGUE(8)
SMAP_DISABLE
.L_ustore_64_start:
movq %rsi,(%rdi)
.L_ustore_64_end:
SMAP_ENABLE
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ustore_64)
ENTRY(_ucas_64)
DEFERRED_SWITCH_CHECK
movq $VM_MAXUSER_ADDRESS-8,%r8
cmpq %r8,%rdi
ja _C_LABEL(ucas_efault)
movq %rsi,%rax
SMAP_DISABLE
.Lucas64_start:
lock
cmpxchgq %rdx,(%rdi)
.Lucas64_end:
SMAP_ENABLE
movq %rax,(%rcx)
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ucas_64)
ENTRY(_ucas_32)
DEFERRED_SWITCH_CHECK
movq $VM_MAXUSER_ADDRESS-4,%r8
cmpq %r8,%rdi
ja _C_LABEL(ucas_efault)
movl %esi,%eax
SMAP_DISABLE
.Lucas32_start:
lock
cmpxchgl %edx,(%rdi)
.Lucas32_end:
SMAP_ENABLE
movl %eax,(%rcx)
xorq %rax,%rax
ret
DEFERRED_SWITCH_CALL
END(_ucas_32)
ENTRY(ucas_efault)
movq $EFAULT,%rax
ret
END(ucas_efault)
ENTRY(ucas_fault)
SMAP_ENABLE
ret
END(ucas_fault)
x86_copyfunc_end: .globl x86_copyfunc_end
.section ".rodata"
.globl _C_LABEL(onfault_table)
_C_LABEL(onfault_table):
.quad .Lcopyin_start
.quad .Lcopyin_end
.quad _C_LABEL(copy_fault)
.quad .Lcopyout_start
.quad .Lcopyout_end
.quad _C_LABEL(copy_fault)
.quad .Lkcopy_start
.quad .Lkcopy_end
.quad _C_LABEL(kcopy_fault)
.quad .Lcopyoutstr_start
.quad .Lcopyoutstr_end
.quad _C_LABEL(copystr_fault)
.quad .Lcopyinstr_start
.quad .Lcopyinstr_end
.quad _C_LABEL(copystr_fault)
.quad .Lucas64_start
.quad .Lucas64_end
.quad _C_LABEL(ucas_fault)
.quad .Lucas32_start
.quad .Lucas32_end
.quad _C_LABEL(ucas_fault)
.quad .L_ufetch_8_start
.quad .L_ufetch_8_end
.quad _C_LABEL(copy_fault)
.quad .L_ufetch_16_start
.quad .L_ufetch_16_end
.quad _C_LABEL(copy_fault)
.quad .L_ufetch_32_start
.quad .L_ufetch_32_end
.quad _C_LABEL(copy_fault)
.quad .L_ufetch_64_start
.quad .L_ufetch_64_end
.quad _C_LABEL(copy_fault)
.quad .L_ustore_8_start
.quad .L_ustore_8_end
.quad _C_LABEL(copy_fault)
.quad .L_ustore_16_start
.quad .L_ustore_16_end
.quad _C_LABEL(copy_fault)
.quad .L_ustore_32_start
.quad .L_ustore_32_end
.quad _C_LABEL(copy_fault)
.quad .L_ustore_64_start
.quad .L_ustore_64_end
.quad _C_LABEL(copy_fault)
.quad 0
.text