1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Western Digital Corporation or its affiliates.
*
* Authors:
* Anup Patel <anup.patel@wdc.com>
*/
#include <linux/linkage.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/csr.h>
.text
.altmacro
.option norelax
ENTRY(__kvm_riscv_switch_to)
/* Save Host GPRs (except A0 and T0-T6) */
REG_S ra, (KVM_ARCH_HOST_RA)(a0)
REG_S sp, (KVM_ARCH_HOST_SP)(a0)
REG_S gp, (KVM_ARCH_HOST_GP)(a0)
REG_S tp, (KVM_ARCH_HOST_TP)(a0)
REG_S s0, (KVM_ARCH_HOST_S0)(a0)
REG_S s1, (KVM_ARCH_HOST_S1)(a0)
REG_S a1, (KVM_ARCH_HOST_A1)(a0)
REG_S a2, (KVM_ARCH_HOST_A2)(a0)
REG_S a3, (KVM_ARCH_HOST_A3)(a0)
REG_S a4, (KVM_ARCH_HOST_A4)(a0)
REG_S a5, (KVM_ARCH_HOST_A5)(a0)
REG_S a6, (KVM_ARCH_HOST_A6)(a0)
REG_S a7, (KVM_ARCH_HOST_A7)(a0)
REG_S s2, (KVM_ARCH_HOST_S2)(a0)
REG_S s3, (KVM_ARCH_HOST_S3)(a0)
REG_S s4, (KVM_ARCH_HOST_S4)(a0)
REG_S s5, (KVM_ARCH_HOST_S5)(a0)
REG_S s6, (KVM_ARCH_HOST_S6)(a0)
REG_S s7, (KVM_ARCH_HOST_S7)(a0)
REG_S s8, (KVM_ARCH_HOST_S8)(a0)
REG_S s9, (KVM_ARCH_HOST_S9)(a0)
REG_S s10, (KVM_ARCH_HOST_S10)(a0)
REG_S s11, (KVM_ARCH_HOST_S11)(a0)
/* Save Host and Restore Guest SSTATUS */
REG_L t0, (KVM_ARCH_GUEST_SSTATUS)(a0)
csrrw t0, CSR_SSTATUS, t0
REG_S t0, (KVM_ARCH_HOST_SSTATUS)(a0)
/* Save Host and Restore Guest HSTATUS */
REG_L t1, (KVM_ARCH_GUEST_HSTATUS)(a0)
csrrw t1, CSR_HSTATUS, t1
REG_S t1, (KVM_ARCH_HOST_HSTATUS)(a0)
/* Save Host and Restore Guest SCOUNTEREN */
REG_L t2, (KVM_ARCH_GUEST_SCOUNTEREN)(a0)
csrrw t2, CSR_SCOUNTEREN, t2
REG_S t2, (KVM_ARCH_HOST_SCOUNTEREN)(a0)
/* Save Host SSCRATCH and change it to struct kvm_vcpu_arch pointer */
csrrw t3, CSR_SSCRATCH, a0
REG_S t3, (KVM_ARCH_HOST_SSCRATCH)(a0)
/* Save Host STVEC and change it to return path */
la t4, __kvm_switch_return
csrrw t4, CSR_STVEC, t4
REG_S t4, (KVM_ARCH_HOST_STVEC)(a0)
/* Restore Guest SEPC */
REG_L t0, (KVM_ARCH_GUEST_SEPC)(a0)
csrw CSR_SEPC, t0
/* Restore Guest GPRs (except A0) */
REG_L ra, (KVM_ARCH_GUEST_RA)(a0)
REG_L sp, (KVM_ARCH_GUEST_SP)(a0)
REG_L gp, (KVM_ARCH_GUEST_GP)(a0)
REG_L tp, (KVM_ARCH_GUEST_TP)(a0)
REG_L t0, (KVM_ARCH_GUEST_T0)(a0)
REG_L t1, (KVM_ARCH_GUEST_T1)(a0)
REG_L t2, (KVM_ARCH_GUEST_T2)(a0)
REG_L s0, (KVM_ARCH_GUEST_S0)(a0)
REG_L s1, (KVM_ARCH_GUEST_S1)(a0)
REG_L a1, (KVM_ARCH_GUEST_A1)(a0)
REG_L a2, (KVM_ARCH_GUEST_A2)(a0)
REG_L a3, (KVM_ARCH_GUEST_A3)(a0)
REG_L a4, (KVM_ARCH_GUEST_A4)(a0)
REG_L a5, (KVM_ARCH_GUEST_A5)(a0)
REG_L a6, (KVM_ARCH_GUEST_A6)(a0)
REG_L a7, (KVM_ARCH_GUEST_A7)(a0)
REG_L s2, (KVM_ARCH_GUEST_S2)(a0)
REG_L s3, (KVM_ARCH_GUEST_S3)(a0)
REG_L s4, (KVM_ARCH_GUEST_S4)(a0)
REG_L s5, (KVM_ARCH_GUEST_S5)(a0)
REG_L s6, (KVM_ARCH_GUEST_S6)(a0)
REG_L s7, (KVM_ARCH_GUEST_S7)(a0)
REG_L s8, (KVM_ARCH_GUEST_S8)(a0)
REG_L s9, (KVM_ARCH_GUEST_S9)(a0)
REG_L s10, (KVM_ARCH_GUEST_S10)(a0)
REG_L s11, (KVM_ARCH_GUEST_S11)(a0)
REG_L t3, (KVM_ARCH_GUEST_T3)(a0)
REG_L t4, (KVM_ARCH_GUEST_T4)(a0)
REG_L t5, (KVM_ARCH_GUEST_T5)(a0)
REG_L t6, (KVM_ARCH_GUEST_T6)(a0)
/* Restore Guest A0 */
REG_L a0, (KVM_ARCH_GUEST_A0)(a0)
/* Resume Guest */
sret
/* Back to Host */
.align 2
__kvm_switch_return:
/* Swap Guest A0 with SSCRATCH */
csrrw a0, CSR_SSCRATCH, a0
/* Save Guest GPRs (except A0) */
REG_S ra, (KVM_ARCH_GUEST_RA)(a0)
REG_S sp, (KVM_ARCH_GUEST_SP)(a0)
REG_S gp, (KVM_ARCH_GUEST_GP)(a0)
REG_S tp, (KVM_ARCH_GUEST_TP)(a0)
REG_S t0, (KVM_ARCH_GUEST_T0)(a0)
REG_S t1, (KVM_ARCH_GUEST_T1)(a0)
REG_S t2, (KVM_ARCH_GUEST_T2)(a0)
REG_S s0, (KVM_ARCH_GUEST_S0)(a0)
REG_S s1, (KVM_ARCH_GUEST_S1)(a0)
REG_S a1, (KVM_ARCH_GUEST_A1)(a0)
REG_S a2, (KVM_ARCH_GUEST_A2)(a0)
REG_S a3, (KVM_ARCH_GUEST_A3)(a0)
REG_S a4, (KVM_ARCH_GUEST_A4)(a0)
REG_S a5, (KVM_ARCH_GUEST_A5)(a0)
REG_S a6, (KVM_ARCH_GUEST_A6)(a0)
REG_S a7, (KVM_ARCH_GUEST_A7)(a0)
REG_S s2, (KVM_ARCH_GUEST_S2)(a0)
REG_S s3, (KVM_ARCH_GUEST_S3)(a0)
REG_S s4, (KVM_ARCH_GUEST_S4)(a0)
REG_S s5, (KVM_ARCH_GUEST_S5)(a0)
REG_S s6, (KVM_ARCH_GUEST_S6)(a0)
REG_S s7, (KVM_ARCH_GUEST_S7)(a0)
REG_S s8, (KVM_ARCH_GUEST_S8)(a0)
REG_S s9, (KVM_ARCH_GUEST_S9)(a0)
REG_S s10, (KVM_ARCH_GUEST_S10)(a0)
REG_S s11, (KVM_ARCH_GUEST_S11)(a0)
REG_S t3, (KVM_ARCH_GUEST_T3)(a0)
REG_S t4, (KVM_ARCH_GUEST_T4)(a0)
REG_S t5, (KVM_ARCH_GUEST_T5)(a0)
REG_S t6, (KVM_ARCH_GUEST_T6)(a0)
/* Save Guest SEPC */
csrr t0, CSR_SEPC
REG_S t0, (KVM_ARCH_GUEST_SEPC)(a0)
/* Restore Host STVEC */
REG_L t1, (KVM_ARCH_HOST_STVEC)(a0)
csrw CSR_STVEC, t1
/* Save Guest A0 and Restore Host SSCRATCH */
REG_L t2, (KVM_ARCH_HOST_SSCRATCH)(a0)
csrrw t2, CSR_SSCRATCH, t2
REG_S t2, (KVM_ARCH_GUEST_A0)(a0)
/* Save Guest and Restore Host SCOUNTEREN */
REG_L t3, (KVM_ARCH_HOST_SCOUNTEREN)(a0)
csrrw t3, CSR_SCOUNTEREN, t3
REG_S t3, (KVM_ARCH_GUEST_SCOUNTEREN)(a0)
/* Save Guest and Restore Host HSTATUS */
REG_L t4, (KVM_ARCH_HOST_HSTATUS)(a0)
csrrw t4, CSR_HSTATUS, t4
REG_S t4, (KVM_ARCH_GUEST_HSTATUS)(a0)
/* Save Guest and Restore Host SSTATUS */
REG_L t5, (KVM_ARCH_HOST_SSTATUS)(a0)
csrrw t5, CSR_SSTATUS, t5
REG_S t5, (KVM_ARCH_GUEST_SSTATUS)(a0)
/* Restore Host GPRs (except A0 and T0-T6) */
REG_L ra, (KVM_ARCH_HOST_RA)(a0)
REG_L sp, (KVM_ARCH_HOST_SP)(a0)
REG_L gp, (KVM_ARCH_HOST_GP)(a0)
REG_L tp, (KVM_ARCH_HOST_TP)(a0)
REG_L s0, (KVM_ARCH_HOST_S0)(a0)
REG_L s1, (KVM_ARCH_HOST_S1)(a0)
REG_L a1, (KVM_ARCH_HOST_A1)(a0)
REG_L a2, (KVM_ARCH_HOST_A2)(a0)
REG_L a3, (KVM_ARCH_HOST_A3)(a0)
REG_L a4, (KVM_ARCH_HOST_A4)(a0)
REG_L a5, (KVM_ARCH_HOST_A5)(a0)
REG_L a6, (KVM_ARCH_HOST_A6)(a0)
REG_L a7, (KVM_ARCH_HOST_A7)(a0)
REG_L s2, (KVM_ARCH_HOST_S2)(a0)
REG_L s3, (KVM_ARCH_HOST_S3)(a0)
REG_L s4, (KVM_ARCH_HOST_S4)(a0)
REG_L s5, (KVM_ARCH_HOST_S5)(a0)
REG_L s6, (KVM_ARCH_HOST_S6)(a0)
REG_L s7, (KVM_ARCH_HOST_S7)(a0)
REG_L s8, (KVM_ARCH_HOST_S8)(a0)
REG_L s9, (KVM_ARCH_HOST_S9)(a0)
REG_L s10, (KVM_ARCH_HOST_S10)(a0)
REG_L s11, (KVM_ARCH_HOST_S11)(a0)
/* Return to C code */
ret
ENDPROC(__kvm_riscv_switch_to)
|