hc
2023-02-13 e440ec23c5a540cdd3f7464e8779219be6fd3d95
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Derived from book3s_hv_rmhandlers.S, which is:
 *
 * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
 *
 */
 
#include <asm/reg.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/export.h>
#include <asm/tm.h>
#include <asm/cputable.h>
 
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
#define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
 
/*
 * Save transactional state and TM-related registers.
 * Called with:
 * - r3 pointing to the vcpu struct
 * - r4 points to the MSR with current TS bits:
 *     (For HV KVM, it is VCPU_MSR ; For PR KVM, it is host MSR).
 * This can modify all checkpointed registers, but
 * restores r1, r2 before exit.
 */
_GLOBAL(__kvmppc_save_tm)
   mflr    r0
   std    r0, PPC_LR_STKOFF(r1)
 
   /* Turn on TM. */
   mfmsr    r8
   li    r0, 1
   rldimi    r8, r0, MSR_TM_LG, 63-MSR_TM_LG
   ori     r8, r8, MSR_FP
   oris    r8, r8, (MSR_VEC | MSR_VSX)@h
   mtmsrd    r8
 
   rldicl. r4, r4, 64 - MSR_TS_S_LG, 62
   beq    1f    /* TM not active in guest. */
 
   std    r1, HSTATE_SCRATCH2(r13)
   std    r3, HSTATE_SCRATCH1(r13)
 
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
BEGIN_FTR_SECTION
   /* Emulation of the treclaim instruction needs TEXASR before treclaim */
   mfspr    r6, SPRN_TEXASR
   std    r6, VCPU_ORIG_TEXASR(r3)
END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
#endif
 
   /* Clear the MSR RI since r1, r13 are all going to be foobar. */
   li    r5, 0
   mtmsrd    r5, 1
 
   li    r3, TM_CAUSE_KVM_RESCHED
 
   /* All GPRs are volatile at this point. */
   TRECLAIM(R3)
 
   /* Temporarily store r13 and r9 so we have some regs to play with */
   SET_SCRATCH0(r13)
   GET_PACA(r13)
   std    r9, PACATMSCRATCH(r13)
   ld    r9, HSTATE_SCRATCH1(r13)
 
   /* Get a few more GPRs free. */
   std    r29, VCPU_GPRS_TM(29)(r9)
   std    r30, VCPU_GPRS_TM(30)(r9)
   std    r31, VCPU_GPRS_TM(31)(r9)
 
   /* Save away PPR and DSCR soon so don't run with user values. */
   mfspr    r31, SPRN_PPR
   HMT_MEDIUM
   mfspr    r30, SPRN_DSCR
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
   ld    r29, HSTATE_DSCR(r13)
   mtspr    SPRN_DSCR, r29
#endif
 
   /* Save all but r9, r13 & r29-r31 */
   reg = 0
   .rept    29
   .if (reg != 9) && (reg != 13)
   std    reg, VCPU_GPRS_TM(reg)(r9)
   .endif
   reg = reg + 1
   .endr
   /* ... now save r13 */
   GET_SCRATCH0(r4)
   std    r4, VCPU_GPRS_TM(13)(r9)
   /* ... and save r9 */
   ld    r4, PACATMSCRATCH(r13)
   std    r4, VCPU_GPRS_TM(9)(r9)
 
   /* Reload stack pointer and TOC. */
   ld    r1, HSTATE_SCRATCH2(r13)
   ld    r2, PACATOC(r13)
 
   /* Set MSR RI now we have r1 and r13 back. */
   li    r5, MSR_RI
   mtmsrd    r5, 1
 
   /* Save away checkpinted SPRs. */
   std    r31, VCPU_PPR_TM(r9)
   std    r30, VCPU_DSCR_TM(r9)
   mflr    r5
   mfcr    r6
   mfctr    r7
   mfspr    r8, SPRN_AMR
   mfspr    r10, SPRN_TAR
   mfxer    r11
   std    r5, VCPU_LR_TM(r9)
   stw    r6, VCPU_CR_TM(r9)
   std    r7, VCPU_CTR_TM(r9)
   std    r8, VCPU_AMR_TM(r9)
   std    r10, VCPU_TAR_TM(r9)
   std    r11, VCPU_XER_TM(r9)
 
   /* Restore r12 as trap number. */
   lwz    r12, VCPU_TRAP(r9)
 
   /* Save FP/VSX. */
   addi    r3, r9, VCPU_FPRS_TM
   bl    store_fp_state
   addi    r3, r9, VCPU_VRS_TM
   bl    store_vr_state
   mfspr    r6, SPRN_VRSAVE
   stw    r6, VCPU_VRSAVE_TM(r9)
1:
   /*
    * We need to save these SPRs after the treclaim so that the software
    * error code is recorded correctly in the TEXASR.  Also the user may
    * change these outside of a transaction, so they must always be
    * context switched.
    */
   mfspr    r7, SPRN_TEXASR
   std    r7, VCPU_TEXASR(r9)
11:
   mfspr    r5, SPRN_TFHAR
   mfspr    r6, SPRN_TFIAR
   std    r5, VCPU_TFHAR(r9)
   std    r6, VCPU_TFIAR(r9)
 
   ld    r0, PPC_LR_STKOFF(r1)
   mtlr    r0
   blr
 
/*
 * _kvmppc_save_tm_pr() is a wrapper around __kvmppc_save_tm(), so that it can
 * be invoked from C function by PR KVM only.
 */
_GLOBAL(_kvmppc_save_tm_pr)
   mflr    r5
   std    r5, PPC_LR_STKOFF(r1)
   stdu    r1, -SWITCH_FRAME_SIZE(r1)
   SAVE_NVGPRS(r1)
 
   /* save MSR since TM/math bits might be impacted
    * by __kvmppc_save_tm().
    */
   mfmsr    r5
   SAVE_GPR(5, r1)
 
   /* also save DSCR/CR/TAR so that it can be recovered later */
   mfspr   r6, SPRN_DSCR
   SAVE_GPR(6, r1)
 
   mfcr    r7
   stw     r7, _CCR(r1)
 
   mfspr   r8, SPRN_TAR
   SAVE_GPR(8, r1)
 
   bl    __kvmppc_save_tm
 
   REST_GPR(8, r1)
   mtspr   SPRN_TAR, r8
 
   ld      r7, _CCR(r1)
   mtcr    r7
 
   REST_GPR(6, r1)
   mtspr   SPRN_DSCR, r6
 
   /* need preserve current MSR's MSR_TS bits */
   REST_GPR(5, r1)
   mfmsr   r6
   rldicl  r6, r6, 64 - MSR_TS_S_LG, 62
   rldimi  r5, r6, MSR_TS_S_LG, 63 - MSR_TS_T_LG
   mtmsrd  r5
 
   REST_NVGPRS(r1)
   addi    r1, r1, SWITCH_FRAME_SIZE
   ld    r5, PPC_LR_STKOFF(r1)
   mtlr    r5
   blr
 
EXPORT_SYMBOL_GPL(_kvmppc_save_tm_pr);
 
/*
 * Restore transactional state and TM-related registers.
 * Called with:
 *  - r3 pointing to the vcpu struct.
 *  - r4 is the guest MSR with desired TS bits:
 *     For HV KVM, it is VCPU_MSR
 *     For PR KVM, it is provided by caller
 * This potentially modifies all checkpointed registers.
 * It restores r1, r2 from the PACA.
 */
_GLOBAL(__kvmppc_restore_tm)
   mflr    r0
   std    r0, PPC_LR_STKOFF(r1)
 
   /* Turn on TM/FP/VSX/VMX so we can restore them. */
   mfmsr    r5
   li    r6, MSR_TM >> 32
   sldi    r6, r6, 32
   or    r5, r5, r6
   ori    r5, r5, MSR_FP
   oris    r5, r5, (MSR_VEC | MSR_VSX)@h
   mtmsrd    r5
 
   /*
    * The user may change these outside of a transaction, so they must
    * always be context switched.
    */
   ld    r5, VCPU_TFHAR(r3)
   ld    r6, VCPU_TFIAR(r3)
   ld    r7, VCPU_TEXASR(r3)
   mtspr    SPRN_TFHAR, r5
   mtspr    SPRN_TFIAR, r6
   mtspr    SPRN_TEXASR, r7
 
   mr    r5, r4
   rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
   beqlr        /* TM not active in guest */
   std    r1, HSTATE_SCRATCH2(r13)
 
   /* Make sure the failure summary is set, otherwise we'll program check
    * when we trechkpt.  It's possible that this might have been not set
    * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
    * host.
    */
   oris    r7, r7, (TEXASR_FS)@h
   mtspr    SPRN_TEXASR, r7
 
   /*
    * We need to load up the checkpointed state for the guest.
    * We need to do this early as it will blow away any GPRs, VSRs and
    * some SPRs.
    */
 
   mr    r31, r3
   addi    r3, r31, VCPU_FPRS_TM
   bl    load_fp_state
   addi    r3, r31, VCPU_VRS_TM
   bl    load_vr_state
   mr    r3, r31
   lwz    r7, VCPU_VRSAVE_TM(r3)
   mtspr    SPRN_VRSAVE, r7
 
   ld    r5, VCPU_LR_TM(r3)
   lwz    r6, VCPU_CR_TM(r3)
   ld    r7, VCPU_CTR_TM(r3)
   ld    r8, VCPU_AMR_TM(r3)
   ld    r9, VCPU_TAR_TM(r3)
   ld    r10, VCPU_XER_TM(r3)
   mtlr    r5
   mtcr    r6
   mtctr    r7
   mtspr    SPRN_AMR, r8
   mtspr    SPRN_TAR, r9
   mtxer    r10
 
   /*
    * Load up PPR and DSCR values but don't put them in the actual SPRs
    * till the last moment to avoid running with userspace PPR and DSCR for
    * too long.
    */
   ld    r29, VCPU_DSCR_TM(r3)
   ld    r30, VCPU_PPR_TM(r3)
 
   std    r2, PACATMSCRATCH(r13) /* Save TOC */
 
   /* Clear the MSR RI since r1, r13 are all going to be foobar. */
   li    r5, 0
   mtmsrd    r5, 1
 
   /* Load GPRs r0-r28 */
   reg = 0
   .rept    29
   ld    reg, VCPU_GPRS_TM(reg)(r31)
   reg = reg + 1
   .endr
 
   mtspr    SPRN_DSCR, r29
   mtspr    SPRN_PPR, r30
 
   /* Load final GPRs */
   ld    29, VCPU_GPRS_TM(29)(r31)
   ld    30, VCPU_GPRS_TM(30)(r31)
   ld    31, VCPU_GPRS_TM(31)(r31)
 
   /* TM checkpointed state is now setup.  All GPRs are now volatile. */
   TRECHKPT
 
   /* Now let's get back the state we need. */
   HMT_MEDIUM
   GET_PACA(r13)
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
   ld    r29, HSTATE_DSCR(r13)
   mtspr    SPRN_DSCR, r29
#endif
   ld    r1, HSTATE_SCRATCH2(r13)
   ld    r2, PACATMSCRATCH(r13)
 
   /* Set the MSR RI since we have our registers back. */
   li    r5, MSR_RI
   mtmsrd    r5, 1
   ld    r0, PPC_LR_STKOFF(r1)
   mtlr    r0
   blr
 
/*
 * _kvmppc_restore_tm_pr() is a wrapper around __kvmppc_restore_tm(), so that it
 * can be invoked from C function by PR KVM only.
 */
_GLOBAL(_kvmppc_restore_tm_pr)
   mflr    r5
   std    r5, PPC_LR_STKOFF(r1)
   stdu    r1, -SWITCH_FRAME_SIZE(r1)
   SAVE_NVGPRS(r1)
 
   /* save MSR to avoid TM/math bits change */
   mfmsr    r5
   SAVE_GPR(5, r1)
 
   /* also save DSCR/CR/TAR so that it can be recovered later */
   mfspr   r6, SPRN_DSCR
   SAVE_GPR(6, r1)
 
   mfcr    r7
   stw     r7, _CCR(r1)
 
   mfspr   r8, SPRN_TAR
   SAVE_GPR(8, r1)
 
   bl    __kvmppc_restore_tm
 
   REST_GPR(8, r1)
   mtspr   SPRN_TAR, r8
 
   ld      r7, _CCR(r1)
   mtcr    r7
 
   REST_GPR(6, r1)
   mtspr   SPRN_DSCR, r6
 
   /* need preserve current MSR's MSR_TS bits */
   REST_GPR(5, r1)
   mfmsr   r6
   rldicl  r6, r6, 64 - MSR_TS_S_LG, 62
   rldimi  r5, r6, MSR_TS_S_LG, 63 - MSR_TS_T_LG
   mtmsrd  r5
 
   REST_NVGPRS(r1)
   addi    r1, r1, SWITCH_FRAME_SIZE
   ld    r5, PPC_LR_STKOFF(r1)
   mtlr    r5
   blr
 
EXPORT_SYMBOL_GPL(_kvmppc_restore_tm_pr);
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */