Home | History | Annotate | Line # | Download | only in rumpkern
rumpcopy.c revision 1.22.18.1
      1  1.22.18.1  christos /*	$NetBSD: rumpcopy.c,v 1.22.18.1 2019/06/10 22:09:53 christos 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.22.18.1  christos __KERNEL_RCSID(0, "$NetBSD: rumpcopy.c,v 1.22.18.1 2019/06/10 22:09:53 christos Exp $");
     30  1.22.18.1  christos 
     31  1.22.18.1  christos #define	__UFETCHSTORE_PRIVATE
     32  1.22.18.1  christos #define	__UCAS_PRIVATE
     33        1.1     pooka 
     34        1.1     pooka #include <sys/param.h>
     35        1.1     pooka #include <sys/lwp.h>
     36        1.1     pooka #include <sys/systm.h>
     37       1.11     pooka #include <sys/uio.h>
     38        1.1     pooka 
     39       1.21     pooka #include <rump-sys/kern.h>
     40       1.21     pooka 
     41       1.11     pooka #include <rump/rumpuser.h>
     42        1.1     pooka 
     43        1.1     pooka int
     44        1.1     pooka copyin(const void *uaddr, void *kaddr, size_t len)
     45        1.1     pooka {
     46       1.11     pooka 	int error = 0;
     47        1.7     pooka 
     48        1.6     pooka 	if (__predict_false(uaddr == NULL && len)) {
     49        1.6     pooka 		return EFAULT;
     50        1.6     pooka 	}
     51        1.1     pooka 
     52       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc)) {
     53        1.1     pooka 		memcpy(kaddr, uaddr, len);
     54       1.15     pooka 	} else if (len) {
     55       1.20     pooka 		error = rump_sysproxy_copyin(RUMP_SPVM2CTL(curproc->p_vmspace),
     56       1.11     pooka 		    uaddr, kaddr, len);
     57        1.4     pooka 	}
     58       1.11     pooka 
     59       1.11     pooka 	return error;
     60        1.1     pooka }
     61        1.1     pooka 
     62        1.1     pooka int
     63        1.1     pooka copyout(const void *kaddr, void *uaddr, size_t len)
     64        1.1     pooka {
     65       1.11     pooka 	int error = 0;
     66        1.7     pooka 
     67        1.6     pooka 	if (__predict_false(uaddr == NULL && len)) {
     68        1.6     pooka 		return EFAULT;
     69        1.6     pooka 	}
     70        1.1     pooka 
     71       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc)) {
     72        1.1     pooka 		memcpy(uaddr, kaddr, len);
     73       1.15     pooka 	} else if (len) {
     74       1.20     pooka 		error = rump_sysproxy_copyout(RUMP_SPVM2CTL(curproc->p_vmspace),
     75       1.11     pooka 		    kaddr, uaddr, len);
     76        1.4     pooka 	}
     77       1.11     pooka 	return error;
     78        1.1     pooka }
     79        1.1     pooka 
     80        1.1     pooka int
     81        1.1     pooka copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
     82        1.1     pooka {
     83        1.8     pooka 	uint8_t *to = kdaddr;
     84        1.8     pooka 	const uint8_t *from = kfaddr;
     85        1.8     pooka 	size_t actlen = 0;
     86        1.8     pooka 
     87        1.8     pooka 	while (len-- > 0 && (*to++ = *from++) != 0)
     88        1.8     pooka 		actlen++;
     89        1.8     pooka 
     90        1.8     pooka 	if (len+1 == 0 && *(to-1) != 0)
     91        1.8     pooka 		return ENAMETOOLONG;
     92        1.1     pooka 
     93        1.6     pooka 	if (done)
     94        1.8     pooka 		*done = actlen+1; /* + '\0' */
     95        1.6     pooka 	return 0;
     96        1.1     pooka }
     97        1.1     pooka 
     98        1.1     pooka int
     99        1.1     pooka copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
    100        1.1     pooka {
    101        1.8     pooka 	uint8_t *to;
    102        1.8     pooka 	int rv;
    103        1.1     pooka 
    104        1.9     pooka 	if (len == 0)
    105        1.9     pooka 		return 0;
    106        1.9     pooka 
    107       1.18     njoly 	if (__predict_false(uaddr == NULL)) {
    108       1.18     njoly 		return EFAULT;
    109       1.18     njoly 	}
    110       1.18     njoly 
    111       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc))
    112        1.8     pooka 		return copystr(uaddr, kaddr, len, done);
    113        1.8     pooka 
    114       1.20     pooka 	if ((rv = rump_sysproxy_copyinstr(RUMP_SPVM2CTL(curproc->p_vmspace),
    115       1.13     pooka 	    uaddr, kaddr, &len)) != 0)
    116        1.8     pooka 		return rv;
    117        1.8     pooka 
    118        1.9     pooka 	/* figure out if we got a terminated string or not */
    119        1.9     pooka 	to = (uint8_t *)kaddr + (len-1);
    120       1.14     pooka 	while (to >= (uint8_t *)kaddr) {
    121        1.8     pooka 		if (*to == 0)
    122        1.8     pooka 			goto found;
    123        1.8     pooka 		to--;
    124        1.8     pooka 	}
    125        1.8     pooka 	return ENAMETOOLONG;
    126        1.8     pooka 
    127        1.8     pooka  found:
    128        1.1     pooka 	if (done)
    129        1.1     pooka 		*done = strlen(kaddr)+1; /* includes termination */
    130        1.8     pooka 
    131        1.1     pooka 	return 0;
    132        1.1     pooka }
    133        1.1     pooka 
    134        1.1     pooka int
    135        1.1     pooka copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
    136        1.1     pooka {
    137        1.8     pooka 	size_t slen;
    138       1.11     pooka 	int error;
    139        1.1     pooka 
    140       1.18     njoly 	if (__predict_false(uaddr == NULL && len)) {
    141       1.18     njoly 		return EFAULT;
    142       1.18     njoly 	}
    143       1.18     njoly 
    144       1.16     pooka 	if (RUMP_LOCALPROC_P(curproc))
    145        1.8     pooka 		return copystr(kaddr, uaddr, len, done);
    146        1.8     pooka 
    147        1.8     pooka 	slen = strlen(kaddr)+1;
    148        1.8     pooka 	if (slen > len)
    149        1.8     pooka 		return ENAMETOOLONG;
    150        1.8     pooka 
    151       1.20     pooka 	error = rump_sysproxy_copyoutstr(RUMP_SPVM2CTL(curproc->p_vmspace),
    152       1.13     pooka 	    kaddr, uaddr, &slen);
    153        1.1     pooka 	if (done)
    154        1.8     pooka 		*done = slen;
    155        1.8     pooka 
    156       1.11     pooka 	return error;
    157        1.1     pooka }
    158        1.1     pooka 
    159        1.1     pooka int
    160        1.1     pooka kcopy(const void *src, void *dst, size_t len)
    161        1.1     pooka {
    162        1.1     pooka 
    163        1.1     pooka 	memcpy(dst, src, len);
    164        1.1     pooka 	return 0;
    165        1.1     pooka }
    166       1.11     pooka 
    167       1.11     pooka /*
    168       1.11     pooka  * Low-level I/O routine.  This is used only when "all else fails",
    169       1.11     pooka  * i.e. the current thread does not have an appropriate vm context.
    170       1.11     pooka  */
    171       1.11     pooka int
    172       1.22  christos uvm_io(struct vm_map *vm, struct uio *uio, int flag)
    173       1.11     pooka {
    174       1.12     pooka 	int error = 0;
    175       1.11     pooka 
    176       1.11     pooka 	/* loop over iovecs one-by-one and copyout */
    177       1.11     pooka 	for (; uio->uio_resid && uio->uio_iovcnt;
    178       1.11     pooka 	    uio->uio_iovcnt--, uio->uio_iov++) {
    179       1.11     pooka 		struct iovec *iov = uio->uio_iov;
    180       1.11     pooka 		size_t curlen = MIN(uio->uio_resid, iov->iov_len);
    181       1.11     pooka 
    182       1.11     pooka 		if (__predict_false(curlen == 0))
    183       1.11     pooka 			continue;
    184       1.11     pooka 
    185       1.11     pooka 		if (uio->uio_rw == UIO_READ) {
    186       1.20     pooka 			error = rump_sysproxy_copyin(RUMP_SPVM2CTL(vm),
    187       1.11     pooka 			    (void *)(vaddr_t)uio->uio_offset, iov->iov_base,
    188       1.11     pooka 			    curlen);
    189       1.11     pooka 		} else {
    190       1.20     pooka 			error = rump_sysproxy_copyout(RUMP_SPVM2CTL(vm),
    191       1.11     pooka 			    iov->iov_base, (void *)(vaddr_t)uio->uio_offset,
    192       1.11     pooka 			    curlen);
    193       1.11     pooka 		}
    194       1.11     pooka 		if (error)
    195       1.11     pooka 			break;
    196       1.11     pooka 
    197       1.11     pooka 		iov->iov_base = (uint8_t *)iov->iov_base + curlen;
    198       1.11     pooka 		iov->iov_len -= curlen;
    199       1.11     pooka 
    200       1.11     pooka 		uio->uio_resid -= curlen;
    201       1.11     pooka 		uio->uio_offset += curlen;
    202       1.11     pooka 	}
    203       1.11     pooka 
    204       1.11     pooka 	return error;
    205       1.11     pooka }
    206       1.17      haad 
    207       1.17      haad int
    208  1.22.18.1  christos _ucas_32(volatile uint32_t *uaddr, uint32_t old, uint32_t new, uint32_t *ret)
    209  1.22.18.1  christos {
    210  1.22.18.1  christos 	uint32_t *uva = ((void *)(uintptr_t)uaddr);
    211  1.22.18.1  christos 	int error;
    212  1.22.18.1  christos 
    213  1.22.18.1  christos 	/* XXXXJRT do we need a MP CPU gate? */
    214  1.22.18.1  christos 
    215  1.22.18.1  christos 	kpreempt_disable();
    216  1.22.18.1  christos 	error = _ufetch_32(uva, ret);
    217  1.22.18.1  christos 	if (error == 0 && *ret == old) {
    218  1.22.18.1  christos 		error = _ustore_32(uva, new);
    219  1.22.18.1  christos 	}
    220  1.22.18.1  christos 	kpreempt_enable();
    221  1.22.18.1  christos 
    222  1.22.18.1  christos 	return error;
    223  1.22.18.1  christos }
    224  1.22.18.1  christos 
    225  1.22.18.1  christos #ifdef _LP64
    226  1.22.18.1  christos int
    227  1.22.18.1  christos _ucas_64(volatile uint64_t *uaddr, uint64_t old, uint64_t new, uint64_t *ret)
    228       1.17      haad {
    229  1.22.18.1  christos 	uint64_t *uva = ((void *)(uintptr_t)uaddr);
    230       1.17      haad 	int error;
    231       1.17      haad 
    232  1.22.18.1  christos 	/* XXXXJRT do we need a MP CPU gate? */
    233  1.22.18.1  christos 
    234  1.22.18.1  christos 	kpreempt_disable();
    235  1.22.18.1  christos 	error = _ufetch_64(uva, ret);
    236  1.22.18.1  christos 	if (error == 0 && *ret == old) {
    237  1.22.18.1  christos 		error = _ustore_64(uva, new);
    238  1.22.18.1  christos 	}
    239  1.22.18.1  christos 	kpreempt_enable();
    240  1.22.18.1  christos 
    241  1.22.18.1  christos 	return error;
    242  1.22.18.1  christos }
    243  1.22.18.1  christos #endif /* _LP64 */
    244       1.17      haad 
    245  1.22.18.1  christos #define	UFETCH(sz)							\
    246  1.22.18.1  christos int									\
    247  1.22.18.1  christos _ufetch_ ## sz(const uint ## sz ##_t *uaddr, uint ## sz ## _t *valp)	\
    248  1.22.18.1  christos {									\
    249  1.22.18.1  christos 	int error = 0;							\
    250  1.22.18.1  christos 									\
    251  1.22.18.1  christos 	if (RUMP_LOCALPROC_P(curproc)) {				\
    252  1.22.18.1  christos 		*valp = *uaddr;						\
    253  1.22.18.1  christos 	} else {							\
    254  1.22.18.1  christos 		error = rump_sysproxy_copyin(				\
    255  1.22.18.1  christos 		    RUMP_SPVM2CTL(curproc->p_vmspace),			\
    256  1.22.18.1  christos 		    uaddr, valp, sizeof(*valp));			\
    257  1.22.18.1  christos 	}								\
    258  1.22.18.1  christos 	return error;							\
    259       1.17      haad }
    260  1.22.18.1  christos 
    261  1.22.18.1  christos UFETCH(8)
    262  1.22.18.1  christos UFETCH(16)
    263  1.22.18.1  christos UFETCH(32)
    264  1.22.18.1  christos #ifdef _LP64
    265  1.22.18.1  christos UFETCH(64)
    266  1.22.18.1  christos #endif
    267  1.22.18.1  christos 
    268  1.22.18.1  christos #undef UFETCH
    269  1.22.18.1  christos 
    270  1.22.18.1  christos #define	USTORE(sz)							\
    271  1.22.18.1  christos int									\
    272  1.22.18.1  christos _ustore_ ## sz(uint ## sz ## _t *uaddr, uint ## sz ## _t val)		\
    273  1.22.18.1  christos {									\
    274  1.22.18.1  christos 	int error = 0;							\
    275  1.22.18.1  christos 									\
    276  1.22.18.1  christos 	if (RUMP_LOCALPROC_P(curproc)) {				\
    277  1.22.18.1  christos 		*uaddr = val;						\
    278  1.22.18.1  christos 	} else {							\
    279  1.22.18.1  christos 		error = rump_sysproxy_copyout(				\
    280  1.22.18.1  christos 		    RUMP_SPVM2CTL(curproc->p_vmspace),			\
    281  1.22.18.1  christos 		    &val, uaddr, sizeof(val));				\
    282  1.22.18.1  christos 	}								\
    283  1.22.18.1  christos 	return error;							\
    284  1.22.18.1  christos }
    285  1.22.18.1  christos 
    286  1.22.18.1  christos USTORE(8)
    287  1.22.18.1  christos USTORE(16)
    288  1.22.18.1  christos USTORE(32)
    289  1.22.18.1  christos #ifdef _LP64
    290  1.22.18.1  christos USTORE(64)
    291  1.22.18.1  christos #endif
    292  1.22.18.1  christos 
    293  1.22.18.1  christos #undef USTORE
    294