Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/amd64/support.S
Show First 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | |||||
* Access user memory from inside the kernel. These routines should be | * Access user memory from inside the kernel. These routines should be | ||||
* the only places that do this. | * the only places that do this. | ||||
* | * | ||||
* These routines set curpcb->pcb_onfault for the time they execute. When a | * These routines set curpcb->pcb_onfault for the time they execute. When a | ||||
* protection violation occurs inside the functions, the trap handler | * protection violation occurs inside the functions, the trap handler | ||||
* returns to *curpcb->pcb_onfault instead of the function. | * returns to *curpcb->pcb_onfault instead of the function. | ||||
*/ | */ | ||||
.macro SMAP_DISABLE smap | |||||
.if \smap | |||||
stac | |||||
.endif | |||||
.endmacro | |||||
.macro SMAP_ENABLE smap | |||||
.if \smap | |||||
clac | |||||
.endif | |||||
.endmacro | |||||
/* | /* | ||||
* copyout(from_kernel, to_user, len) | * copyout(from_kernel, to_user, len) | ||||
* %rdi, %rsi, %rdx | * %rdi, %rsi, %rdx | ||||
*/ | */ | ||||
ENTRY(copyout_nosmap) | .macro COPYOUT smap erms | ||||
PUSH_FRAME_POINTER | PUSH_FRAME_POINTER | ||||
movq PCPU(CURPCB),%rax | movq PCPU(CURPCB),%rax | ||||
movq $copyout_fault,PCB_ONFAULT(%rax) | |||||
testq %rdx,%rdx /* anything to do? */ | |||||
jz done_copyout | |||||
/* | |||||
* Check explicitly for non-user addresses. This check is essential | |||||
* because it prevents usermode from writing into the kernel. We do | |||||
* not verify anywhere else that the user did not specify a rogue | |||||
* address. | |||||
*/ | |||||
/* | |||||
* First, prevent address wrapping. | |||||
*/ | |||||
movq %rsi,%rax | |||||
addq %rdx,%rax | |||||
jc copyout_fault | |||||
/* | |||||
* XXX STOP USING VM_MAXUSER_ADDRESS. | |||||
* It is an end address, not a max, so every time it is used correctly it | |||||
* looks like there is an off by one error, and of course it caused an off | |||||
* by one error in several places. | |||||
*/ | |||||
movq $VM_MAXUSER_ADDRESS,%rcx | |||||
cmpq %rcx,%rax | |||||
ja copyout_fault | |||||
xchgq %rdi,%rsi | |||||
/* bcopy(%rsi, %rdi, %rdx) */ | |||||
movq %rdx,%rcx | |||||
shrq $3,%rcx | |||||
rep | |||||
movsq | |||||
movb %dl,%cl | |||||
andb $7,%cl | |||||
je done_copyout | |||||
rep | |||||
movsb | |||||
jmp done_copyout | |||||
END(copyout_nosmap) | |||||
ENTRY(copyout_smap) | |||||
PUSH_FRAME_POINTER | |||||
movq PCPU(CURPCB),%rax | |||||
/* Trap entry clears PSL.AC */ | /* Trap entry clears PSL.AC */ | ||||
movq $copyout_fault,PCB_ONFAULT(%rax) | movq $copyout_fault,PCB_ONFAULT(%rax) | ||||
testq %rdx,%rdx /* anything to do? */ | testq %rdx,%rdx /* anything to do? */ | ||||
jz done_copyout | jz 2f | ||||
/* | /* | ||||
* Check explicitly for non-user addresses. If 486 write protection | * Check explicitly for non-user addresses. If 486 write protection | ||||
* is being used, this check is essential because we are in kernel | * is being used, this check is essential because we are in kernel | ||||
* mode so the h/w does not provide any protection against writing | * mode so the h/w does not provide any protection against writing | ||||
* kernel addresses. | * kernel addresses. | ||||
*/ | */ | ||||
Show All 12 Lines | */ | ||||
movq $VM_MAXUSER_ADDRESS,%rcx | movq $VM_MAXUSER_ADDRESS,%rcx | ||||
cmpq %rcx,%rax | cmpq %rcx,%rax | ||||
ja copyout_fault | ja copyout_fault | ||||
xchgq %rdi,%rsi | xchgq %rdi,%rsi | ||||
/* bcopy(%rsi, %rdi, %rdx) */ | /* bcopy(%rsi, %rdi, %rdx) */ | ||||
movq %rdx,%rcx | movq %rdx,%rcx | ||||
SMAP_DISABLE \smap | |||||
.if \erms == 0 | |||||
shrq $3,%rcx | shrq $3,%rcx | ||||
stac | |||||
rep | rep | ||||
movsq | movsq | ||||
movb %dl,%cl | movb %dl,%cl | ||||
andb $7,%cl | andb $7,%cl | ||||
je 1f | je 1f | ||||
.endif | |||||
rep | rep | ||||
movsb | movsb | ||||
1: clac | 1: | ||||
SMAP_ENABLE \smap | |||||
done_copyout: | 2: | ||||
xorl %eax,%eax | xorl %eax,%eax | ||||
movq PCPU(CURPCB),%rdx | movq PCPU(CURPCB),%rdx | ||||
movq %rax,PCB_ONFAULT(%rdx) | movq %rax,PCB_ONFAULT(%rdx) | ||||
POP_FRAME_POINTER | POP_FRAME_POINTER | ||||
ret | ret | ||||
.endmacro | |||||
ENTRY(copyout_nosmap_std) | |||||
COPYOUT smap=0 erms=0 | |||||
END(copyout_nosmap_std) | |||||
ENTRY(copyout_smap_std) | |||||
COPYOUT smap=1 erms=0 | |||||
END(copyout_smap_std) | |||||
ENTRY(copyout_nosmap_erms) | |||||
COPYOUT smap=0 erms=1 | |||||
END(copyout_nosmap_erms) | |||||
ENTRY(copyout_smap_erms) | |||||
COPYOUT smap=1 erms=1 | |||||
END(copyout_smap_erms) | |||||
ALIGN_TEXT | ALIGN_TEXT | ||||
copyout_fault: | copyout_fault: | ||||
movq PCPU(CURPCB),%rdx | movq PCPU(CURPCB),%rdx | ||||
movq $0,PCB_ONFAULT(%rdx) | movq $0,PCB_ONFAULT(%rdx) | ||||
movq $EFAULT,%rax | movq $EFAULT,%rax | ||||
POP_FRAME_POINTER | POP_FRAME_POINTER | ||||
ret | ret | ||||
END(copyout_smap) | |||||
/* | /* | ||||
* copyin(from_user, to_kernel, len) | * copyin(from_user, to_kernel, len) | ||||
* %rdi, %rsi, %rdx | * %rdi, %rsi, %rdx | ||||
*/ | */ | ||||
ENTRY(copyin_nosmap) | .macro COPYIN smap erms | ||||
PUSH_FRAME_POINTER | PUSH_FRAME_POINTER | ||||
movq PCPU(CURPCB),%rax | movq PCPU(CURPCB),%rax | ||||
movq $copyin_fault,PCB_ONFAULT(%rax) | movq $copyin_fault,PCB_ONFAULT(%rax) | ||||
testq %rdx,%rdx /* anything to do? */ | testq %rdx,%rdx /* anything to do? */ | ||||
jz done_copyin | jz 2f | ||||
/* | /* | ||||
* make sure address is valid | * make sure address is valid | ||||
*/ | */ | ||||
movq %rdi,%rax | movq %rdi,%rax | ||||
addq %rdx,%rax | addq %rdx,%rax | ||||
jc copyin_fault | jc copyin_fault | ||||
movq $VM_MAXUSER_ADDRESS,%rcx | movq $VM_MAXUSER_ADDRESS,%rcx | ||||
cmpq %rcx,%rax | cmpq %rcx,%rax | ||||
ja copyin_fault | ja copyin_fault | ||||
xchgq %rdi,%rsi | xchgq %rdi,%rsi | ||||
movq %rdx,%rcx | movq %rdx,%rcx | ||||
movb %cl,%al | movb %cl,%al | ||||
shrq $3,%rcx /* copy longword-wise */ | |||||
rep | |||||
movsq | |||||
movb %al,%cl | |||||
andb $7,%cl /* copy remaining bytes */ | |||||
je done_copyin | |||||
rep | |||||
movsb | |||||
jmp done_copyin | SMAP_DISABLE \smap | ||||
END(copyin_nosmap) | .if \erms == 0 | ||||
ENTRY(copyin_smap) | |||||
PUSH_FRAME_POINTER | |||||
movq PCPU(CURPCB),%rax | |||||
movq $copyin_fault,PCB_ONFAULT(%rax) | |||||
testq %rdx,%rdx /* anything to do? */ | |||||
jz done_copyin | |||||
/* | |||||
* make sure address is valid | |||||
*/ | |||||
movq %rdi,%rax | |||||
addq %rdx,%rax | |||||
jc copyin_fault | |||||
movq $VM_MAXUSER_ADDRESS,%rcx | |||||
cmpq %rcx,%rax | |||||
ja copyin_fault | |||||
xchgq %rdi,%rsi | |||||
movq %rdx,%rcx | |||||
movb %cl,%al | |||||
shrq $3,%rcx /* copy longword-wise */ | shrq $3,%rcx /* copy longword-wise */ | ||||
stac | |||||
rep | rep | ||||
movsq | movsq | ||||
movb %al,%cl | movb %al,%cl | ||||
andb $7,%cl /* copy remaining bytes */ | andb $7,%cl /* copy remaining bytes */ | ||||
je 1f | je 1 | ||||
.endif | |||||
rep | rep | ||||
movsb | movsb | ||||
1: clac | |||||
done_copyin: | 1: | ||||
SMAP_ENABLE \smap | |||||
2: | |||||
xorl %eax,%eax | xorl %eax,%eax | ||||
movq PCPU(CURPCB),%rdx | movq PCPU(CURPCB),%rdx | ||||
movq %rax,PCB_ONFAULT(%rdx) | movq %rax,PCB_ONFAULT(%rdx) | ||||
POP_FRAME_POINTER | POP_FRAME_POINTER | ||||
ret | ret | ||||
END(copyin_smap) | .endmacro | ||||
ENTRY(copyin_nosmap_std) | |||||
COPYIN smap=0 erms=0 | |||||
END(copyin_nosmap_std) | |||||
ENTRY(copyin_smap_std) | |||||
COPYIN smap=1 erms=0 | |||||
END(copyin_smap_std) | |||||
ENTRY(copyin_nosmap_erms) | |||||
COPYIN smap=0 erms=1 | |||||
END(copyin_nosmap_erms) | |||||
ENTRY(copyin_smap_erms) | |||||
COPYIN smap=1 erms=1 | |||||
END(copyin_smap_erms) | |||||
ALIGN_TEXT | ALIGN_TEXT | ||||
copyin_fault: | copyin_fault: | ||||
movq PCPU(CURPCB),%rdx | movq PCPU(CURPCB),%rdx | ||||
movq $0,PCB_ONFAULT(%rdx) | movq $0,PCB_ONFAULT(%rdx) | ||||
movq $EFAULT,%rax | movq $EFAULT,%rax | ||||
POP_FRAME_POINTER | POP_FRAME_POINTER | ||||
ret | ret | ||||
▲ Show 20 Lines • Show All 850 Lines • Show Last 20 Lines |