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 | |||||
| adr x6, copyio_fault /* Get the handler address */ | |||||
andrew: You can use `cpyf*rt` and `cpyf*wt` directly to implement copyin & copyout.
As they execute… | |||||
| SET_FAULT_HANDLER(x6, x7) /* Set the handler */ | |||||
| .inst 0x19001441 /* cpyfpwt [x1]!, [x0]!, x2! */ | |||||
| .inst 0x19401441 /* cpyfmwt [x1]!, [x0]!, x2! */ | |||||
| .inst 0x19801441 /* cpyfewt [x1]!, [x0]!, x2! */ | |||||
| SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */ | |||||
| 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 | |||||
| adr x6, copyio_fault /* Get the handler address */ | |||||
| SET_FAULT_HANDLER(x6, x7) /* Set the handler */ | |||||
| .inst 0x19002441 /* cpyfprt [x1]!, [x0]!, x2! */ | |||||
| .inst 0x19402441 /* cpyfmrt [x1]!, [x0]!, x2! */ | |||||
| .inst 0x19802441 /* cpyfert [x1]!, [x0]!, x2! */ | |||||
| SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */ | |||||
| 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 */ | ||||
| ▲ Show 20 Lines • Show All 136 Lines • Show Last 20 Lines | |||||
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.