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 <sys/cdefs.h>
36 __FBSDID("$FreeBSD: releng/11.2/sys/riscv/riscv/vm_machdep.c 301961 2016-06-16 12:05:44Z kib $");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/limits.h>
41 #include <sys/proc.h>
42 #include <sys/sf_buf.h>
43 #include <sys/signal.h>
44 #include <sys/unistd.h>
45
46 #include <vm/vm.h>
47 #include <vm/vm_page.h>
48 #include <vm/vm_map.h>
49 #include <vm/uma.h>
50 #include <vm/uma_int.h>
51
52 #include <machine/riscvreg.h>
53 #include <machine/cpu.h>
54 #include <machine/pcb.h>
55 #include <machine/frame.h>
56
57 /*
58 * Finish a fork operation, with process p2 nearly set up.
59 * Copy and update the pcb, set up the stack so that the child
60 * ready to run and return to user mode.
61 */
62 void
63 cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
64 {
65 struct pcb *pcb2;
66 struct trapframe *tf;
67
68 if ((flags & RFPROC) == 0)
69 return;
70
71 pcb2 = (struct pcb *)(td2->td_kstack +
72 td2->td_kstack_pages * PAGE_SIZE) - 1;
73
74 td2->td_pcb = pcb2;
75 bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
76
77 td2->td_pcb->pcb_l1addr =
78 vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l1);
79
80 tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
81 bcopy(td1->td_frame, tf, sizeof(*tf));
82
83 /* Clear syscall error flag */
84 tf->tf_t[0] = 0;
85
86 /* Arguments for child */
87 tf->tf_a[0] = 0;
88 tf->tf_a[1] = 0;
89 tf->tf_sstatus = SSTATUS_PIE;
90
91 td2->td_frame = tf;
92
93 /* Set the return value registers for fork() */
94 td2->td_pcb->pcb_s[0] = (uintptr_t)fork_return;
95 td2->td_pcb->pcb_s[1] = (uintptr_t)td2;
96 td2->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
97 td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
98
99 /* Setup to release spin count in fork_exit(). */
100 td2->td_md.md_spinlock_count = 1;
101 td2->td_md.md_saved_sstatus_ie = 1;
102 }
103
104 void
105 cpu_reset(void)
106 {
107
108 printf("cpu_reset");
109 while(1)
110 __asm volatile("wfi" ::: "memory");
111 }
112
113 void
114 cpu_thread_swapin(struct thread *td)
115 {
116 }
117
118 void
119 cpu_thread_swapout(struct thread *td)
120 {
121 }
122
123 void
124 cpu_set_syscall_retval(struct thread *td, int error)
125 {
126 struct trapframe *frame;
127
128 frame = td->td_frame;
129
130 switch (error) {
131 case 0:
132 frame->tf_a[0] = td->td_retval[0];
133 frame->tf_a[1] = td->td_retval[1];
134 frame->tf_t[0] = 0; /* syscall succeeded */
135 break;
136 case ERESTART:
137 frame->tf_sepc -= 4; /* prev instruction */
138 break;
139 case EJUSTRETURN:
140 break;
141 default:
142 frame->tf_a[0] = error;
143 frame->tf_t[0] = 1; /* syscall error */
144 break;
145 }
146 }
147
148 /*
149 * Initialize machine state, mostly pcb and trap frame for a new
150 * thread, about to return to userspace. Put enough state in the new
151 * thread's PCB to get it to go back to the fork_return(), which
152 * finalizes the thread state and handles peculiarities of the first
153 * return to userspace for the new thread.
154 */
155 void
156 cpu_copy_thread(struct thread *td, struct thread *td0)
157 {
158
159 bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
160 bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
161
162 td->td_pcb->pcb_s[0] = (uintptr_t)fork_return;
163 td->td_pcb->pcb_s[1] = (uintptr_t)td;
164 td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
165 td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
166
167 /* Setup to release spin count in fork_exit(). */
168 td->td_md.md_spinlock_count = 1;
169 td->td_md.md_saved_sstatus_ie = 1;
170 }
171
172 /*
173 * Set that machine state for performing an upcall that starts
174 * the entry function with the given argument.
175 */
176 void
177 cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
178 stack_t *stack)
179 {
180 struct trapframe *tf = td->td_frame;
181
182 tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
183 tf->tf_sepc = (register_t)entry;
184 tf->tf_a[0] = (register_t)arg;
185 }
186
187 int
188 cpu_set_user_tls(struct thread *td, void *tls_base)
189 {
190 struct pcb *pcb;
191
192 if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS)
193 return (EINVAL);
194
195 pcb = td->td_pcb;
196 pcb->pcb_tp = (register_t)tls_base;
197
198 return (0);
199 }
200
201 void
202 cpu_thread_exit(struct thread *td)
203 {
204 }
205
206 void
207 cpu_thread_alloc(struct thread *td)
208 {
209
210 td->td_pcb = (struct pcb *)(td->td_kstack +
211 td->td_kstack_pages * PAGE_SIZE) - 1;
212 td->td_frame = (struct trapframe *)STACKALIGN(
213 (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe));
214 }
215
216 void
217 cpu_thread_free(struct thread *td)
218 {
219 }
220
221 void
222 cpu_thread_clean(struct thread *td)
223 {
224 }
225
226 /*
227 * Intercept the return address from a freshly forked process that has NOT
228 * been scheduled yet.
229 *
230 * This is needed to make kernel threads stay in kernel mode.
231 */
232 void
233 cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg)
234 {
235
236 td->td_pcb->pcb_s[0] = (uintptr_t)func;
237 td->td_pcb->pcb_s[1] = (uintptr_t)arg;
238 td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
239 td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
240 }
241
242 void
243 cpu_exit(struct thread *td)
244 {
245 }
246
247 void
248 swi_vm(void *v)
249 {
250
251 /* Nothing to do here - busdma bounce buffers are not implemented. */
252 }
Cache object: 7034f7a72d343cf4431ba029fdb0ce5a
|