xref: /openbsd/sys/arch/riscv64/riscv64/cpuswitch.S (revision d415bd75)
1/*	$OpenBSD: cpuswitch.S,v 1.8 2023/10/24 13:20:10 claudio Exp $	*/
2
3/*
4 * Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com>
5 * Copyright (c) 2020 Brian Bamsch <bbamsch@google.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "machine/asm.h"
21#include "assym.h"
22
23/*
24 * cpu_switchto(struct proc *oldproc, struct proc *newproc)
25 *      a0	'struct proc *' of the old context
26 *      a1	'struct proc *' of the new context
27 */
28ENTRY(cpu_switchto_asm)
29	// check if old context needs to be saved
30	beqz	a0, 1f
31
32	// create switchframe
33	addi	sp, sp, -SWITCHFRAME_SIZEOF
34	sd	s0, (SF_S + 0 * 8)(sp)
35	sd	s1, (SF_S + 1 * 8)(sp)
36	sd	s2, (SF_S + 2 * 8)(sp)
37	sd	s3, (SF_S + 3 * 8)(sp)
38	sd	s4, (SF_S + 4 * 8)(sp)
39	sd	s5, (SF_S + 5 * 8)(sp)
40	sd	s6, (SF_S + 6 * 8)(sp)
41	sd	s7, (SF_S + 7 * 8)(sp)
42	sd	s8, (SF_S + 8 * 8)(sp)
43	sd	s9, (SF_S + 9 * 8)(sp)
44	sd	s10, (SF_S + 10 * 8)(sp)
45	sd	s11, (SF_S + 11 * 8)(sp)
46	sd	ra, SF_RA(sp)
47
48	// store switchframe
49	ld	a5, CI_CURPCB(tp)
50	sd	sp, PCB_SP(a5)
51
521:
53	RETGUARD_SYMBOL(cpu_switchto)
54	RETGUARD_LOAD_RANDOM(cpu_switchto, s0)
55
56	li	a5, SONPROC
57	sb	a5, P_STAT(a1)		// Mark new on cpu
58	sd	tp, P_CPU(a1)		// Store curcpu
59	ld	a5, P_ADDR(a1)		// Load new pcb
60	sd	a5, CI_CURPCB(tp)
61	sd	a1, CI_CURPROC(tp)
62
63	// Unlike AArch64, RISC-V does not have a dedicated register in which
64	// we can also store pcb_tcb. Supervisor must access tcb indirectly.
65
66	ld	s1, PCB_SP(a5)		// load new stack pointer
67	mv	a0, a1
68	la	t0, pmap_set_satp
69	jalr	t0
70
71	mv	a7, s0			// move retguard random
72	mv	sp, s1			// restore stack pointer
73
74	ld	s0, (SF_S + 0 * 8)(sp)
75	ld	s1, (SF_S + 1 * 8)(sp)
76	ld	s2, (SF_S + 2 * 8)(sp)
77	ld	s3, (SF_S + 3 * 8)(sp)
78	ld	s4, (SF_S + 4 * 8)(sp)
79	ld	s5, (SF_S + 5 * 8)(sp)
80	ld	s6, (SF_S + 6 * 8)(sp)
81	ld	s7, (SF_S + 7 * 8)(sp)
82	ld	s8, (SF_S + 8 * 8)(sp)
83	ld	s9, (SF_S + 9 * 8)(sp)
84	ld	s10, (SF_S + 10 * 8)(sp)
85	ld	s11, (SF_S + 11 * 8)(sp)
86	ld	ra, SF_RA(sp)
87
88	RETGUARD_CALC_COOKIE(a7)
89	addi	sp, sp, SWITCHFRAME_SIZEOF
90	RETGUARD_CHECK(cpu_switchto, a7)
91	ret
92END(cpu_switch_asm)
93
94ENTRY(proc_trampoline)
95	la	t0, proc_trampoline_mi
96	jalr	t0
97	mv	a0, s2
98	jalr	s1
99	la	t0, syscall_return
100	jr	t0
101END(cpu_switch)
102