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