Home | History | Annotate | Line # | Download | only in rumpkern
rumpcopy.c revision 1.17.20.1
      1  1.17.20.1  rmind /*	$NetBSD: rumpcopy.c,v 1.17.20.1 2013/08/28 23:59:37 rmind Exp $	*/
      2        1.1  pooka 
      3        1.1  pooka /*
      4        1.1  pooka  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
      5        1.1  pooka  *
      6        1.1  pooka  * Redistribution and use in source and binary forms, with or without
      7        1.1  pooka  * modification, are permitted provided that the following conditions
      8        1.1  pooka  * are met:
      9        1.1  pooka  * 1. Redistributions of source code must retain the above copyright
     10        1.1  pooka  *    notice, this list of conditions and the following disclaimer.
     11        1.1  pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1  pooka  *    notice, this list of conditions and the following disclaimer in the
     13        1.1  pooka  *    documentation and/or other materials provided with the distribution.
     14        1.1  pooka  *
     15        1.1  pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16        1.1  pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17        1.1  pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18        1.1  pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19        1.1  pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20        1.1  pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21        1.1  pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22        1.1  pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23        1.1  pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24        1.1  pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25        1.1  pooka  * SUCH DAMAGE.
     26        1.1  pooka  */
     27        1.1  pooka 
     28        1.1  pooka #include <sys/cdefs.h>
     29  1.17.20.1  rmind __KERNEL_RCSID(0, "$NetBSD: rumpcopy.c,v 1.17.20.1 2013/08/28 23:59:37 rmind Exp $");
     30        1.1  pooka 
     31        1.1  pooka #include <sys/param.h>
     32        1.1  pooka #include <sys/lwp.h>
     33        1.1  pooka #include <sys/systm.h>
     34       1.11  pooka #include <sys/uio.h>
     35        1.1  pooka 
     36       1.11  pooka #include <rump/rumpuser.h>
     37        1.1  pooka 
     38        1.1  pooka #include "rump_private.h"
     39        1.1  pooka 
     40        1.1  pooka int
     41        1.1  pooka copyin(const void *uaddr, void *kaddr, size_t len)
     42        1.1  pooka {
     43       1.11  pooka 	int error = 0;
     44        1.7  pooka 
     45        1.6  pooka 	if (__predict_false(uaddr == NULL && len)) {
     46        1.6  pooka 		return EFAULT;
     47        1.6  pooka 	}
     48        1.1  pooka 
     49       1.16  pooka 	if (RUMP_LOCALPROC_P(curproc)) {
     50        1.1  pooka 		memcpy(kaddr, uaddr, len);
     51       1.15  pooka 	} else if (len) {
     52       1.11  pooka 		error = rumpuser_sp_copyin(curproc->p_vmspace->vm_map.pmap,
     53       1.11  pooka 		    uaddr, kaddr, len);
     54        1.4  pooka 	}
     55       1.11  pooka 
     56       1.11  pooka 	return error;
     57        1.1  pooka }
     58        1.1  pooka 
     59        1.1  pooka int
     60        1.1  pooka copyout(const void *kaddr, void *uaddr, size_t len)
     61        1.1  pooka {
     62       1.11  pooka 	int error = 0;
     63        1.7  pooka 
     64        1.6  pooka 	if (__predict_false(uaddr == NULL && len)) {
     65        1.6  pooka 		return EFAULT;
     66        1.6  pooka 	}
     67        1.1  pooka 
     68       1.16  pooka 	if (RUMP_LOCALPROC_P(curproc)) {
     69        1.1  pooka 		memcpy(uaddr, kaddr, len);
     70       1.15  pooka 	} else if (len) {
     71       1.11  pooka 		error = rumpuser_sp_copyout(curproc->p_vmspace->vm_map.pmap,
     72       1.11  pooka 		    kaddr, uaddr, len);
     73        1.4  pooka 	}
     74       1.11  pooka 	return error;
     75        1.1  pooka }
     76        1.1  pooka 
     77        1.1  pooka int
     78        1.1  pooka subyte(void *uaddr, int byte)
     79        1.1  pooka {
     80       1.11  pooka 	int error = 0;
     81        1.1  pooka 
     82       1.16  pooka 	if (RUMP_LOCALPROC_P(curproc))
     83        1.1  pooka 		*(char *)uaddr = byte;
     84        1.1  pooka 	else
     85       1.11  pooka 		error = rumpuser_sp_copyout(curproc->p_vmspace->vm_map.pmap,
     86       1.11  pooka 		    &byte, uaddr, 1);
     87       1.11  pooka 
     88       1.11  pooka 	return error;
     89        1.1  pooka }
     90        1.1  pooka 
     91        1.1  pooka int
     92        1.1  pooka copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
     93        1.1  pooka {
     94        1.8  pooka 	uint8_t *to = kdaddr;
     95        1.8  pooka 	const uint8_t *from = kfaddr;
     96        1.8  pooka 	size_t actlen = 0;
     97        1.8  pooka 
     98        1.8  pooka 	while (len-- > 0 && (*to++ = *from++) != 0)
     99        1.8  pooka 		actlen++;
    100        1.8  pooka 
    101        1.8  pooka 	if (len+1 == 0 && *(to-1) != 0)
    102        1.8  pooka 		return ENAMETOOLONG;
    103        1.1  pooka 
    104        1.6  pooka 	if (done)
    105        1.8  pooka 		*done = actlen+1; /* + '\0' */
    106        1.6  pooka 	return 0;
    107        1.1  pooka }
    108        1.1  pooka 
    109        1.1  pooka int
    110        1.1  pooka copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
    111        1.1  pooka {
    112        1.8  pooka 	uint8_t *to;
    113        1.8  pooka 	int rv;
    114        1.1  pooka 
    115        1.9  pooka 	if (len == 0)
    116        1.9  pooka 		return 0;
    117        1.9  pooka 
    118  1.17.20.1  rmind 	if (__predict_false(uaddr == NULL)) {
    119  1.17.20.1  rmind 		return EFAULT;
    120  1.17.20.1  rmind 	}
    121  1.17.20.1  rmind 
    122       1.16  pooka 	if (RUMP_LOCALPROC_P(curproc))
    123        1.8  pooka 		return copystr(uaddr, kaddr, len, done);
    124        1.8  pooka 
    125       1.13  pooka 	if ((rv = rumpuser_sp_copyinstr(curproc->p_vmspace->vm_map.pmap,
    126       1.13  pooka 	    uaddr, kaddr, &len)) != 0)
    127        1.8  pooka 		return rv;
    128        1.8  pooka 
    129        1.9  pooka 	/* figure out if we got a terminated string or not */
    130        1.9  pooka 	to = (uint8_t *)kaddr + (len-1);
    131       1.14  pooka 	while (to >= (uint8_t *)kaddr) {
    132        1.8  pooka 		if (*to == 0)
    133        1.8  pooka 			goto found;
    134        1.8  pooka 		to--;
    135        1.8  pooka 	}
    136        1.8  pooka 	return ENAMETOOLONG;
    137        1.8  pooka 
    138        1.8  pooka  found:
    139        1.1  pooka 	if (done)
    140        1.1  pooka 		*done = strlen(kaddr)+1; /* includes termination */
    141        1.8  pooka 
    142        1.1  pooka 	return 0;
    143        1.1  pooka }
    144        1.1  pooka 
    145        1.1  pooka int
    146        1.1  pooka copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
    147        1.1  pooka {
    148        1.8  pooka 	size_t slen;
    149       1.11  pooka 	int error;
    150        1.1  pooka 
    151  1.17.20.1  rmind 	if (__predict_false(uaddr == NULL && len)) {
    152  1.17.20.1  rmind 		return EFAULT;
    153  1.17.20.1  rmind 	}
    154  1.17.20.1  rmind 
    155       1.16  pooka 	if (RUMP_LOCALPROC_P(curproc))
    156        1.8  pooka 		return copystr(kaddr, uaddr, len, done);
    157        1.8  pooka 
    158        1.8  pooka 	slen = strlen(kaddr)+1;
    159        1.8  pooka 	if (slen > len)
    160        1.8  pooka 		return ENAMETOOLONG;
    161        1.8  pooka 
    162       1.13  pooka 	error = rumpuser_sp_copyoutstr(curproc->p_vmspace->vm_map.pmap,
    163       1.13  pooka 	    kaddr, uaddr, &slen);
    164        1.1  pooka 	if (done)
    165        1.8  pooka 		*done = slen;
    166        1.8  pooka 
    167       1.11  pooka 	return error;
    168        1.1  pooka }
    169        1.1  pooka 
    170        1.1  pooka int
    171        1.1  pooka kcopy(const void *src, void *dst, size_t len)
    172        1.1  pooka {
    173        1.1  pooka 
    174        1.1  pooka 	memcpy(dst, src, len);
    175        1.1  pooka 	return 0;
    176        1.1  pooka }
    177       1.11  pooka 
    178       1.11  pooka /*
    179       1.11  pooka  * Low-level I/O routine.  This is used only when "all else fails",
    180       1.11  pooka  * i.e. the current thread does not have an appropriate vm context.
    181       1.11  pooka  */
    182       1.11  pooka int
    183       1.11  pooka uvm_io(struct vm_map *vm, struct uio *uio)
    184       1.11  pooka {
    185       1.12  pooka 	int error = 0;
    186       1.11  pooka 
    187       1.11  pooka 	/* loop over iovecs one-by-one and copyout */
    188       1.11  pooka 	for (; uio->uio_resid && uio->uio_iovcnt;
    189       1.11  pooka 	    uio->uio_iovcnt--, uio->uio_iov++) {
    190       1.11  pooka 		struct iovec *iov = uio->uio_iov;
    191       1.11  pooka 		size_t curlen = MIN(uio->uio_resid, iov->iov_len);
    192       1.11  pooka 
    193       1.11  pooka 		if (__predict_false(curlen == 0))
    194       1.11  pooka 			continue;
    195       1.11  pooka 
    196       1.11  pooka 		if (uio->uio_rw == UIO_READ) {
    197       1.11  pooka 			error = rumpuser_sp_copyin(vm->pmap,
    198       1.11  pooka 			    (void *)(vaddr_t)uio->uio_offset, iov->iov_base,
    199       1.11  pooka 			    curlen);
    200       1.11  pooka 		} else {
    201       1.11  pooka 			error = rumpuser_sp_copyout(vm->pmap,
    202       1.11  pooka 			    iov->iov_base, (void *)(vaddr_t)uio->uio_offset,
    203       1.11  pooka 			    curlen);
    204       1.11  pooka 		}
    205       1.11  pooka 		if (error)
    206       1.11  pooka 			break;
    207       1.11  pooka 
    208       1.11  pooka 		iov->iov_base = (uint8_t *)iov->iov_base + curlen;
    209       1.11  pooka 		iov->iov_len -= curlen;
    210       1.11  pooka 
    211       1.11  pooka 		uio->uio_resid -= curlen;
    212       1.11  pooka 		uio->uio_offset += curlen;
    213       1.11  pooka 	}
    214       1.11  pooka 
    215       1.11  pooka 	return error;
    216       1.11  pooka }
    217       1.17   haad 
    218       1.17   haad /*
    219       1.17   haad  * Copy one byte from userspace to kernel.
    220       1.17   haad  */
    221       1.17   haad int
    222       1.17   haad fubyte(const void *base)
    223       1.17   haad {
    224       1.17   haad 	unsigned char val;
    225       1.17   haad 	int error;
    226       1.17   haad 
    227       1.17   haad 	error = copyin(base, &val, sizeof(char));
    228       1.17   haad 	if (error != 0)
    229       1.17   haad 		return -1;
    230       1.17   haad 
    231       1.17   haad 	return (int)val;
    232       1.17   haad }
    233