aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/powerpc/powerpc/copyinout.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/sys/powerpc/powerpc/copyinout.c b/sys/powerpc/powerpc/copyinout.c
index 76965ad996b8..1528accc0e0e 100644
--- a/sys/powerpc/powerpc/copyinout.c
+++ b/sys/powerpc/powerpc/copyinout.c
@@ -236,31 +236,51 @@ REMAP(copyin)(const void *udaddr, void *kaddr, size_t len)
int
REMAP(copyinstr)(const void *udaddr, void *kaddr, size_t len, size_t *done)
{
+ struct thread *td;
+ pmap_t pm;
+ jmp_buf env;
const char *up;
- char *kp;
- size_t l;
- int rv, c;
+ char *kp, *p;
+ size_t i, l, t;
+ int rv;
- kp = kaddr;
- up = udaddr;
+ td = curthread;
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ t = 0;
rv = ENAMETOOLONG;
- for (l = 0; len-- > 0; l++) {
- if ((c = fubyte(up++)) < 0) {
+ td->td_pcb->pcb_onfault = &env;
+ if (setjmp(env)) {
+ rv = EFAULT;
+ goto done;
+ }
+
+ kp = kaddr;
+ up = udaddr;
+
+ while (len > 0) {
+ if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
rv = EFAULT;
- break;
+ goto done;
}
- if (!(*kp++ = c)) {
- l++;
- rv = 0;
- break;
+ for (i = 0; len > 0 && i < l; i++, t++, len--) {
+ if ((*kp++ = *p++) == 0) {
+ i++, t++;
+ rv = 0;
+ goto done;
+ }
}
+
+ up += l;
}
+done:
+ td->td_pcb->pcb_onfault = NULL;
+
if (done != NULL) {
- *done = l;
+ *done = t;
}
return (rv);