xref: /freebsd/sys/riscv/riscv/copyinout.S (revision b0b1dbdd)
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