Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/copyinout.S
| Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| copyio_fault_nopcb: | copyio_fault_nopcb: | ||||
| mov x0, #EFAULT | mov x0, #EFAULT | ||||
| ret | ret | ||||
| END(copyio_fault) | END(copyio_fault) | ||||
| /* | /* | ||||
| * Copies from a kernel to user address | * Copies from a kernel to user address | ||||
| * | * | ||||
| * int copyout(const void *kaddr, void *udaddr, size_t len) | * int copyout_std(const void *kaddr, void *udaddr, size_t len) | ||||
| */ | */ | ||||
| ENTRY(copyout) | ENTRY(copyout_std) | ||||
| cbz x2, 1f | cbz x2, 1f | ||||
| check_user_access 1, 2, copyio_fault_nopcb | check_user_access 1, 2, copyio_fault_nopcb | ||||
| b copycommon | b copycommon | ||||
| 1: mov x0, xzr /* return 0 */ | 1: mov x0, xzr /* return 0 */ | ||||
| ret | ret | ||||
| END(copyout) | END(copyout_std) | ||||
| /* | /* | ||||
| * Copies from a kernel to user address | |||||
| * | |||||
| * int copyout_mops(const void *kaddr, void *udaddr, size_t len) | |||||
| */ | |||||
| ENTRY(copyout_mops) | |||||
| cbz x2, 1f | |||||
| check_user_access 1, 2, copyio_fault_nopcb | |||||
| b copycommon_mops | |||||
andrew: You can use `cpyf*rt` and `cpyf*wt` directly to implement copyin & copyout.
As they execute… | |||||
| 1: mov x0, xzr /* return 0 */ | |||||
| ret | |||||
| END(copyout_mops) | |||||
| /* | |||||
| * Copies from a user to kernel address | * Copies from a user to kernel address | ||||
| * | * | ||||
| * int copyin(const void *uaddr, void *kdaddr, size_t len) | * int copyin_std(const void *uaddr, void *kdaddr, size_t len) | ||||
| */ | */ | ||||
| ENTRY(copyin) | ENTRY(copyin_std) | ||||
| cbz x2, 1f | cbz x2, 1f | ||||
| check_user_access 0, 2, copyio_fault_nopcb | check_user_access 0, 2, copyio_fault_nopcb | ||||
| b copycommon | b copycommon | ||||
| 1: mov x0, xzr /* return 0 */ | 1: mov x0, xzr /* return 0 */ | ||||
| ret | ret | ||||
| END(copyin) | END(copyin_std) | ||||
| /* | /* | ||||
| * Copies from a user to kernel address | |||||
| * | |||||
| * int copyin_mops(const void *uaddr, void *kdaddr, size_t len) | |||||
| */ | |||||
| ENTRY(copyin_mops) | |||||
| cbz x2, 1f | |||||
| check_user_access 0, 2, copyio_fault_nopcb | |||||
| b copycommon | |||||
| 1: mov x0, xzr /* return 0 */ | |||||
| ret | |||||
| END(copyin_mops) | |||||
| /* | |||||
| * Copies a string from a user to kernel address | * Copies a string from a user to kernel address | ||||
| * | * | ||||
| * int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) | * int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) | ||||
| */ | */ | ||||
| ENTRY(copyinstr) | ENTRY(copyinstr) | ||||
| mov x5, xzr /* count = 0 */ | mov x5, xzr /* count = 0 */ | ||||
| mov w4, #1 /* If zero return faulure */ | mov w4, #1 /* If zero return faulure */ | ||||
| cbz x2, 3f /* If len == 0 then skip loop */ | cbz x2, 3f /* If len == 0 then skip loop */ | ||||
| ▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | |||||
| ending: | ending: | ||||
| EXIT_USER_ACCESS_CHECK(w6, x7) | EXIT_USER_ACCESS_CHECK(w6, x7) | ||||
| SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */ | SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */ | ||||
| mov x0, xzr /* return 0 */ | mov x0, xzr /* return 0 */ | ||||
| ret | ret | ||||
| .size copycommon, . - copycommon | .size copycommon, . - copycommon | ||||
| /* | |||||
| * Local helper (MOPS version) | |||||
| * | |||||
| * x0 - src pointer | |||||
| * x1 - dst pointer | |||||
| * x2 - size | |||||
| * lr - the return address, so jump here instead of calling | |||||
| */ | |||||
| .text | |||||
| .align 4 | |||||
| .local copycommon_mops | |||||
| .type copycommon_mops,@function | |||||
| copycommon_mops: | |||||
| adr x6, copyio_fault /* Get the handler address */ | |||||
| SET_FAULT_HANDLER(x6, x7) /* Set the handler */ | |||||
| ENTER_USER_ACCESS(w6, x7) | |||||
| .inst 0x19000441 /* cpyfp [x1]!, [x0]!, x2! */ | |||||
| .inst 0x19400441 /* cpyfm [x1]!, [x0]!, x2! */ | |||||
| .inst 0x19800441 /* cpyfe [x1]!, [x0]!, x2! */ | |||||
| EXIT_USER_ACCESS_CHECK(w6, x7) | |||||
| SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */ | |||||
| mov x0, xzr /* return 0 */ | |||||
| ret | |||||
| .size copycommon_mops, . - copycommon_mops | |||||
| GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL) | GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL) | ||||
You can use cpyf*rt and cpyf*wt directly to implement copyin & copyout.
As they execute the load/store as unprivileged operations you will need to set the fault handler, but don't need to enable user access.