The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/riscv/riscv/vm_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2015-2018 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/12.0/sys/riscv/riscv/vm_machdep.c 338467 2018-09-05 11:34:58Z br $");
   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 #include <machine/sbi.h>
   57 
   58 #if __riscv_xlen == 64
   59 #define TP_OFFSET       16      /* sizeof(struct tcb) */
   60 #endif
   61 
   62 /*
   63  * Finish a fork operation, with process p2 nearly set up.
   64  * Copy and update the pcb, set up the stack so that the child
   65  * ready to run and return to user mode.
   66  */
   67 void
   68 cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
   69 {
   70         struct pcb *pcb2;
   71         struct trapframe *tf;
   72         register_t val;
   73 
   74         if ((flags & RFPROC) == 0)
   75                 return;
   76 
   77         if (td1 == curthread) {
   78                 /*
   79                  * Save the tp. These normally happen in cpu_switch,
   80                  * but if userland changes this then forks this may
   81                  * not have happened.
   82                  */
   83                 __asm __volatile("mv %0, tp" : "=&r"(val));
   84                 td1->td_pcb->pcb_tp = val;
   85 
   86                 /* RISCVTODO: save the FPU state here */
   87         }
   88 
   89         pcb2 = (struct pcb *)(td2->td_kstack +
   90             td2->td_kstack_pages * PAGE_SIZE) - 1;
   91 
   92         td2->td_pcb = pcb2;
   93         bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
   94 
   95         td2->td_pcb->pcb_l1addr =
   96             vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l1);
   97 
   98         tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
   99         bcopy(td1->td_frame, tf, sizeof(*tf));
  100 
  101         /* Clear syscall error flag */
  102         tf->tf_t[0] = 0;
  103 
  104         /* Arguments for child */
  105         tf->tf_a[0] = 0;
  106         tf->tf_a[1] = 0;
  107         tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */
  108         tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */
  109 
  110         td2->td_frame = tf;
  111 
  112         /* Set the return value registers for fork() */
  113         td2->td_pcb->pcb_s[0] = (uintptr_t)fork_return;
  114         td2->td_pcb->pcb_s[1] = (uintptr_t)td2;
  115         td2->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
  116         td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
  117 
  118         /* Setup to release spin count in fork_exit(). */
  119         td2->td_md.md_spinlock_count = 1;
  120         td2->td_md.md_saved_sstatus_ie = (SSTATUS_SIE);
  121 }
  122 
  123 void
  124 cpu_reset(void)
  125 {
  126 
  127         sbi_shutdown();
  128 
  129         while(1);
  130 }
  131 
  132 void
  133 cpu_thread_swapin(struct thread *td)
  134 {
  135 }
  136 
  137 void
  138 cpu_thread_swapout(struct thread *td)
  139 {
  140 }
  141 
  142 void
  143 cpu_set_syscall_retval(struct thread *td, int error)
  144 {
  145         struct trapframe *frame;
  146 
  147         frame = td->td_frame;
  148 
  149         switch (error) {
  150         case 0:
  151                 frame->tf_a[0] = td->td_retval[0];
  152                 frame->tf_a[1] = td->td_retval[1];
  153                 frame->tf_t[0] = 0;             /* syscall succeeded */
  154                 break;
  155         case ERESTART:
  156                 frame->tf_sepc -= 4;            /* prev instruction */
  157                 break;
  158         case EJUSTRETURN:
  159                 break;
  160         default:
  161                 frame->tf_a[0] = error;
  162                 frame->tf_t[0] = 1;             /* syscall error */
  163                 break;
  164         }
  165 }
  166 
  167 /*
  168  * Initialize machine state, mostly pcb and trap frame for a new
  169  * thread, about to return to userspace.  Put enough state in the new
  170  * thread's PCB to get it to go back to the fork_return(), which
  171  * finalizes the thread state and handles peculiarities of the first
  172  * return to userspace for the new thread.
  173  */
  174 void
  175 cpu_copy_thread(struct thread *td, struct thread *td0)
  176 {
  177 
  178         bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
  179         bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
  180 
  181         td->td_pcb->pcb_s[0] = (uintptr_t)fork_return;
  182         td->td_pcb->pcb_s[1] = (uintptr_t)td;
  183         td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
  184         td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
  185 
  186         /* Setup to release spin count in fork_exit(). */
  187         td->td_md.md_spinlock_count = 1;
  188         td->td_md.md_saved_sstatus_ie = (SSTATUS_SIE);
  189 }
  190 
  191 /*
  192  * Set that machine state for performing an upcall that starts
  193  * the entry function with the given argument.
  194  */
  195 void
  196 cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
  197         stack_t *stack)
  198 {
  199         struct trapframe *tf;
  200 
  201         tf = td->td_frame;
  202 
  203         tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
  204         tf->tf_sepc = (register_t)entry;
  205         tf->tf_a[0] = (register_t)arg;
  206 }
  207 
  208 int
  209 cpu_set_user_tls(struct thread *td, void *tls_base)
  210 {
  211         struct pcb *pcb;
  212 
  213         if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS)
  214                 return (EINVAL);
  215 
  216         pcb = td->td_pcb;
  217         pcb->pcb_tp = (register_t)tls_base + TP_OFFSET;
  218         if (td == curthread)
  219                 __asm __volatile("mv tp, %0" :: "r"(pcb->pcb_tp));
  220 
  221         return (0);
  222 }
  223 
  224 void
  225 cpu_thread_exit(struct thread *td)
  226 {
  227 }
  228 
  229 void
  230 cpu_thread_alloc(struct thread *td)
  231 {
  232 
  233         td->td_pcb = (struct pcb *)(td->td_kstack +
  234             td->td_kstack_pages * PAGE_SIZE) - 1;
  235         td->td_frame = (struct trapframe *)STACKALIGN(
  236             (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe));
  237 }
  238 
  239 void
  240 cpu_thread_free(struct thread *td)
  241 {
  242 }
  243 
  244 void
  245 cpu_thread_clean(struct thread *td)
  246 {
  247 }
  248 
  249 /*
  250  * Intercept the return address from a freshly forked process that has NOT
  251  * been scheduled yet.
  252  *
  253  * This is needed to make kernel threads stay in kernel mode.
  254  */
  255 void
  256 cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg)
  257 {
  258 
  259         td->td_pcb->pcb_s[0] = (uintptr_t)func;
  260         td->td_pcb->pcb_s[1] = (uintptr_t)arg;
  261         td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
  262         td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
  263 }
  264 
  265 void
  266 cpu_exit(struct thread *td)
  267 {
  268 }
  269 
  270 void
  271 swi_vm(void *v)
  272 {
  273 
  274         /* Nothing to do here - busdma bounce buffers are not implemented. */
  275 }

Cache object: af9f39b2c84c96bac5d3354143f739e0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.