1295041Sbr/*- 2295972Sbr * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com> 3295041Sbr * All rights reserved. 4295041Sbr * 5295041Sbr * Portions of this software were developed by SRI International and the 6295041Sbr * University of Cambridge Computer Laboratory under DARPA/AFRL contract 7295041Sbr * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. 8295041Sbr * 9295041Sbr * Portions of this software were developed by the University of Cambridge 10295041Sbr * Computer Laboratory as part of the CTSRD Project, with support from the 11295041Sbr * UK Higher Education Innovation Fund (HEIF). 12295041Sbr * 13295041Sbr * Redistribution and use in source and binary forms, with or without 14295041Sbr * modification, are permitted provided that the following conditions 15295041Sbr * are met: 16295041Sbr * 1. Redistributions of source code must retain the above copyright 17295041Sbr * notice, this list of conditions and the following disclaimer. 18295041Sbr * 2. Redistributions in binary form must reproduce the above copyright 19295041Sbr * notice, this list of conditions and the following disclaimer in the 20295041Sbr * documentation and/or other materials provided with the distribution. 21295041Sbr * 22295041Sbr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23295041Sbr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24295041Sbr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25295041Sbr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26295041Sbr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27295041Sbr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28295041Sbr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29295041Sbr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30295041Sbr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31295041Sbr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32295041Sbr * SUCH DAMAGE. 33295041Sbr */ 34295041Sbr 35295041Sbr#include "assym.s" 36295041Sbr#include "opt_sched.h" 37295041Sbr 38295041Sbr#include <machine/param.h> 39295041Sbr#include <machine/asm.h> 40295041Sbr#include <machine/riscvreg.h> 41295041Sbr#include <machine/pte.h> 42295041Sbr 43295041Sbr__FBSDID("$FreeBSD: releng/11.0/sys/riscv/riscv/swtch.S 298580 2016-04-25 14:47:51Z br $"); 44295041Sbr 45295041Sbr/* 46295041Sbr * void cpu_throw(struct thread *old, struct thread *new) 47295041Sbr */ 48295041SbrENTRY(cpu_throw) 49295041Sbr /* Store the new curthread */ 50295258Sbr sd a1, PC_CURTHREAD(gp) 51295041Sbr /* And the new pcb */ 52295041Sbr ld x13, TD_PCB(a1) 53295258Sbr sd x13, PC_CURPCB(gp) 54295041Sbr 55295041Sbr sfence.vm 56295041Sbr 57295041Sbr /* Switch to the new pmap */ 58298580Sbr ld t0, PCB_L1ADDR(x13) 59298580Sbr csrw sptbr, t0 60295041Sbr 61295041Sbr /* TODO: Invalidate the TLB */ 62295041Sbr 63295041Sbr sfence.vm 64295041Sbr 65295041Sbr /* Load registers */ 66295041Sbr ld ra, (PCB_RA)(x13) 67295041Sbr ld sp, (PCB_SP)(x13) 68295041Sbr 69295041Sbr /* s[0-11] */ 70295041Sbr ld s0, (PCB_S + 0 * 8)(x13) 71295041Sbr ld s1, (PCB_S + 1 * 8)(x13) 72295041Sbr ld s2, (PCB_S + 2 * 8)(x13) 73295041Sbr ld s3, (PCB_S + 3 * 8)(x13) 74295041Sbr ld s4, (PCB_S + 4 * 8)(x13) 75295041Sbr ld s5, (PCB_S + 5 * 8)(x13) 76295041Sbr ld s6, (PCB_S + 6 * 8)(x13) 77295041Sbr ld s7, (PCB_S + 7 * 8)(x13) 78295041Sbr ld s8, (PCB_S + 8 * 8)(x13) 79295041Sbr ld s9, (PCB_S + 9 * 8)(x13) 80295041Sbr ld s10, (PCB_S + 10 * 8)(x13) 81295041Sbr ld s11, (PCB_S + 11 * 8)(x13) 82295041Sbr ret 83295041Sbr 84295041Sbr.Lcpu_throw_panic_str: 85295041Sbr .asciz "cpu_throw: %p\0" 86295041SbrEND(cpu_throw) 87295041Sbr 88295041Sbr/* 89295041Sbr * void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx) 90295041Sbr * 91295041Sbr * a0 = old 92295041Sbr * a1 = new 93295041Sbr * a2 = mtx 94295041Sbr * x3 to x7, x16 and x17 are caller saved 95295041Sbr */ 96295041SbrENTRY(cpu_switch) 97295041Sbr /* Store the new curthread */ 98295258Sbr sd a1, PC_CURTHREAD(gp) 99295041Sbr /* And the new pcb */ 100295041Sbr ld x13, TD_PCB(a1) 101295258Sbr sd x13, PC_CURPCB(gp) 102295041Sbr 103295041Sbr /* Save the old context. */ 104295041Sbr ld x13, TD_PCB(a0) 105295041Sbr 106295697Sbr /* Store ra, sp and the callee-saved registers */ 107295041Sbr sd ra, (PCB_RA)(x13) 108295041Sbr sd sp, (PCB_SP)(x13) 109295041Sbr 110295041Sbr /* s[0-11] */ 111295041Sbr sd s0, (PCB_S + 0 * 8)(x13) 112295041Sbr sd s1, (PCB_S + 1 * 8)(x13) 113295041Sbr sd s2, (PCB_S + 2 * 8)(x13) 114295041Sbr sd s3, (PCB_S + 3 * 8)(x13) 115295041Sbr sd s4, (PCB_S + 4 * 8)(x13) 116295041Sbr sd s5, (PCB_S + 5 * 8)(x13) 117295041Sbr sd s6, (PCB_S + 6 * 8)(x13) 118295041Sbr sd s7, (PCB_S + 7 * 8)(x13) 119295041Sbr sd s8, (PCB_S + 8 * 8)(x13) 120295041Sbr sd s9, (PCB_S + 9 * 8)(x13) 121295041Sbr sd s10, (PCB_S + 10 * 8)(x13) 122295041Sbr sd s11, (PCB_S + 11 * 8)(x13) 123295041Sbr 124295041Sbr /* 125295041Sbr * Restore the saved context. 126295041Sbr */ 127295041Sbr ld x13, TD_PCB(a1) 128295041Sbr 129295041Sbr /* 130295041Sbr * TODO: We may need to flush the cache here if switching 131295041Sbr * to a user process. 132295041Sbr */ 133295041Sbr 134295041Sbr sfence.vm 135295041Sbr 136295041Sbr /* Switch to the new pmap */ 137298580Sbr ld t0, PCB_L1ADDR(x13) 138298580Sbr csrw sptbr, t0 139295041Sbr 140295041Sbr /* TODO: Invalidate the TLB */ 141295041Sbr 142295041Sbr sfence.vm 143295041Sbr 144295041Sbr /* Release the old thread */ 145295041Sbr sd a2, TD_LOCK(a0) 146295041Sbr#if defined(SCHED_ULE) && defined(SMP) 147295972Sbr /* Spin if TD_LOCK points to a blocked_lock */ 148295972Sbr la a2, _C_LABEL(blocked_lock) 149295972Sbr1: 150295972Sbr ld t0, TD_LOCK(a1) 151295972Sbr beq t0, a2, 1b 152295041Sbr#endif 153295041Sbr 154295041Sbr /* Restore the registers */ 155295041Sbr ld ra, (PCB_RA)(x13) 156295041Sbr ld sp, (PCB_SP)(x13) 157295041Sbr 158295041Sbr /* s[0-11] */ 159295041Sbr ld s0, (PCB_S + 0 * 8)(x13) 160295041Sbr ld s1, (PCB_S + 1 * 8)(x13) 161295041Sbr ld s2, (PCB_S + 2 * 8)(x13) 162295041Sbr ld s3, (PCB_S + 3 * 8)(x13) 163295041Sbr ld s4, (PCB_S + 4 * 8)(x13) 164295041Sbr ld s5, (PCB_S + 5 * 8)(x13) 165295041Sbr ld s6, (PCB_S + 6 * 8)(x13) 166295041Sbr ld s7, (PCB_S + 7 * 8)(x13) 167295041Sbr ld s8, (PCB_S + 8 * 8)(x13) 168295041Sbr ld s9, (PCB_S + 9 * 8)(x13) 169295041Sbr ld s10, (PCB_S + 10 * 8)(x13) 170295041Sbr ld s11, (PCB_S + 11 * 8)(x13) 171295041Sbr ret 172295041Sbr.Lcpu_switch_panic_str: 173295041Sbr .asciz "cpu_switch: %p\0" 174295041SbrEND(cpu_switch) 175295041Sbr 176295041Sbr/* 177295041Sbr * fork_exit(void (*callout)(void *, struct trapframe *), void *arg, 178295041Sbr * struct trapframe *frame) 179295041Sbr */ 180295041Sbr 181295041SbrENTRY(fork_trampoline) 182295697Sbr mv a0, s0 183295697Sbr mv a1, s1 184295041Sbr mv a2, sp 185295041Sbr call _C_LABEL(fork_exit) 186295041Sbr 187295041Sbr /* Restore sstatus */ 188295041Sbr ld t0, (TF_SSTATUS)(sp) 189295041Sbr /* Ensure interrupts disabled */ 190295041Sbr li t1, ~SSTATUS_IE 191295041Sbr and t0, t0, t1 192295041Sbr csrw sstatus, t0 193295041Sbr 194295041Sbr /* Restore exception program counter */ 195295041Sbr ld t0, (TF_SEPC)(sp) 196295041Sbr csrw sepc, t0 197295041Sbr 198295041Sbr /* Restore the registers */ 199295041Sbr ld t0, (TF_T + 0 * 8)(sp) 200295041Sbr ld t1, (TF_T + 1 * 8)(sp) 201295041Sbr ld t2, (TF_T + 2 * 8)(sp) 202295041Sbr ld t3, (TF_T + 3 * 8)(sp) 203295041Sbr ld t4, (TF_T + 4 * 8)(sp) 204295041Sbr ld t5, (TF_T + 5 * 8)(sp) 205295041Sbr ld t6, (TF_T + 6 * 8)(sp) 206295041Sbr 207295041Sbr ld s0, (TF_S + 0 * 8)(sp) 208295041Sbr ld s1, (TF_S + 1 * 8)(sp) 209295041Sbr ld s2, (TF_S + 2 * 8)(sp) 210295041Sbr ld s3, (TF_S + 3 * 8)(sp) 211295041Sbr ld s4, (TF_S + 4 * 8)(sp) 212295041Sbr ld s5, (TF_S + 5 * 8)(sp) 213295041Sbr ld s6, (TF_S + 6 * 8)(sp) 214295041Sbr ld s7, (TF_S + 7 * 8)(sp) 215295041Sbr ld s8, (TF_S + 8 * 8)(sp) 216295041Sbr ld s9, (TF_S + 9 * 8)(sp) 217295041Sbr ld s10, (TF_S + 10 * 8)(sp) 218295041Sbr ld s11, (TF_S + 11 * 8)(sp) 219295041Sbr 220295041Sbr ld a0, (TF_A + 0 * 8)(sp) 221295041Sbr ld a1, (TF_A + 1 * 8)(sp) 222295041Sbr ld a2, (TF_A + 2 * 8)(sp) 223295041Sbr ld a3, (TF_A + 3 * 8)(sp) 224295041Sbr ld a4, (TF_A + 4 * 8)(sp) 225295041Sbr ld a5, (TF_A + 5 * 8)(sp) 226295041Sbr ld a6, (TF_A + 6 * 8)(sp) 227295041Sbr ld a7, (TF_A + 7 * 8)(sp) 228295041Sbr 229295253Sbr /* Load user ra and sp */ 230295253Sbr ld tp, (TF_TP)(sp) 231295253Sbr ld ra, (TF_RA)(sp) 232295253Sbr 233295253Sbr /* 234295253Sbr * Store our pcpup on stack, we will load it back 235295253Sbr * on kernel mode trap. 236295253Sbr */ 237295253Sbr sd gp, (TF_SIZE)(sp) 238295253Sbr ld gp, (TF_GP)(sp) 239295253Sbr 240295041Sbr /* Save kernel stack so we can use it doing a user trap */ 241295253Sbr addi sp, sp, TF_SIZE 242295041Sbr csrw sscratch, sp 243295041Sbr 244295253Sbr /* Load user stack */ 245295253Sbr ld sp, (TF_SP - TF_SIZE)(sp) 246295041Sbr 247295041Sbr eret 248295041SbrEND(fork_trampoline) 249295041Sbr 250295041SbrENTRY(savectx) 251295698Sbr /* Store ra, sp and the callee-saved registers */ 252295698Sbr sd ra, (PCB_RA)(a0) 253295698Sbr sd sp, (PCB_SP)(a0) 254295698Sbr 255295698Sbr /* s[0-11] */ 256295698Sbr sd s0, (PCB_S + 0 * 8)(a0) 257295698Sbr sd s1, (PCB_S + 1 * 8)(a0) 258295698Sbr sd s2, (PCB_S + 2 * 8)(a0) 259295698Sbr sd s3, (PCB_S + 3 * 8)(a0) 260295698Sbr sd s4, (PCB_S + 4 * 8)(a0) 261295698Sbr sd s5, (PCB_S + 5 * 8)(a0) 262295698Sbr sd s6, (PCB_S + 6 * 8)(a0) 263295698Sbr sd s7, (PCB_S + 7 * 8)(a0) 264295698Sbr sd s8, (PCB_S + 8 * 8)(a0) 265295698Sbr sd s9, (PCB_S + 9 * 8)(a0) 266295698Sbr sd s10, (PCB_S + 10 * 8)(a0) 267295698Sbr sd s11, (PCB_S + 11 * 8)(a0) 268295698Sbr 269295698Sbr /* Store the VFP registers */ 270295698Sbr#ifdef VFP 271295698Sbr /* TODO */ 272295698Sbr#endif 273295698Sbr ret 274295041SbrEND(savectx) 275