1/*- 2 * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 5 * Portions of this software were developed by SRI International and the 6 * University of Cambridge Computer Laboratory under DARPA/AFRL contract 7 * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. 8 * 9 * Portions of this software were developed by the University of Cambridge 10 * Computer Laboratory as part of the CTSRD Project, with support from the 11 * UK Higher Education Innovation Fund (HEIF). 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <machine/asm.h> 36__FBSDID("$FreeBSD$"); 37 38#include <sys/errno.h> 39 40#include "assym.s" 41 42/* 43 * Fault handler for the copy{in,out} functions below. 44 */ 45ENTRY(copyio_fault) 46 SET_FAULT_HANDLER(x0, a1) /* Clear the handler */ 47copyio_fault_nopcb: 48 li a0, EFAULT 49 ret 50END(copyio_fault) 51 52/* 53 * Copies from a kernel to user address 54 * 55 * int copyout(const void *kaddr, void *udaddr, size_t len) 56 */ 57ENTRY(copyout) 58 beqz a2, 2f /* If len == 0 then skip loop */ 59 add a3, a1, a2 60 li a4, VM_MAXUSER_ADDRESS 61 bgt a3, a4, copyio_fault_nopcb 62 63 la a6, copyio_fault /* Get the handler address */ 64 SET_FAULT_HANDLER(a6, a7) /* Set the handler */ 65 661: lb a4, 0(a0) /* Load from kaddr */ 67 addi a0, a0, 1 68 sb a4, 0(a1) /* Store in uaddr */ 69 addi a1, a1, 1 70 addi a2, a2, -1 /* len-- */ 71 bnez a2, 1b 72 73 SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ 74 752: li a0, 0 /* return 0 */ 76 ret 77END(copyout) 78 79/* 80 * Copies from a user to kernel address 81 * 82 * int copyin(const void *uaddr, void *kdaddr, size_t len) 83 */ 84ENTRY(copyin) 85 beqz a2, 2f /* If len == 0 then skip loop */ 86 add a3, a0, a2 87 li a4, VM_MAXUSER_ADDRESS 88 bgt a3, a4, copyio_fault_nopcb 89 90 la a6, copyio_fault /* Get the handler address */ 91 SET_FAULT_HANDLER(a6, a7) /* Set the handler */ 92 931: lb a4, 0(a0) /* Load from uaddr */ 94 addi a0, a0, 1 95 sb a4, 0(a1) /* Store in kaddr */ 96 addi a1, a1, 1 97 addi a2, a2, -1 /* len-- */ 98 bnez a2, 1b 99 100 SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ 101 1022: li a0, 0 /* return 0 */ 103 ret 104END(copyin) 105 106/* 107 * Copies a string from a user to kernel address 108 * 109 * int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) 110 */ 111ENTRY(copyinstr) 112 mv a5, x0 /* count = 0 */ 113 beqz a2, 3f /* If len == 0 then skip loop */ 114 li a7, VM_MAXUSER_ADDRESS 115 116 la a6, copyio_fault /* Get the handler address */ 117 SET_FAULT_HANDLER(a6, a7) /* Set the handler */ 118 1191: bgt a7, a0, copyio_fault 120 lb a4, 0(a0) /* Load from uaddr */ 121 addi a0, a0, 1 122 sb a4, 0(a1) /* Store in kaddr */ 123 addi a1, a1, 1 124 beqz a4, 2f 125 addi a2, a2, -1 /* len-- */ 126 addi a5, a5, 1 /* count++ */ 127 bnez a2, 1b 128 1292: SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ 130 1313: beqz a3, 4f /* Check if done != NULL */ 132 addi a5, a5, 1 /* count++ */ 133 sd a5, 0(a3) /* done = count */ 134 1354: mv a0, x0 /* return 0 */ 136 ret 137END(copyinstr) 138