master
c 598 lines 16.4 KB
Raw
1 /*
2 * RISC-V VMState Description
3 *
4 * Copyright (c) 2020 Huawei Technologies Co., Ltd
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "qemu/osdep.h"
20 #include "cpu.h"
21 #include "qemu/error-report.h"
22 #include "system/kvm.h"
23 #include "system/tcg.h"
24 #include "migration/cpu.h"
25 #include "exec/icount.h"
26 #include "target/riscv/tcg/debug.h"
27 #include "hw/riscv/machines-qom.h"
28 #ifdef CONFIG_KVM
29 #include "kvm/kvm_riscv.h"
30 #endif
31
32 static bool pmp_needed(void *opaque)
33 {
34 RISCVCPU *cpu = opaque;
35
36 if (kvm_enabled()) {
37 return false;
38 }
39
40 return tcg_enabled() && cpu->cfg.pmp;
41 }
42
43 static int pmp_post_load(void *opaque, int version_id)
44 {
45 #ifdef CONFIG_TCG
46 RISCVCPU *cpu = opaque;
47 CPURISCVState *env = &cpu->env;
48 uint8_t pmp_regions = riscv_cpu_cfg(env)->pmp_regions;
49
50 for (int i = 0; i < pmp_regions; i++) {
51 pmp_update_rule_addr(env, i);
52 }
53 pmp_update_rule_nums(env);
54 #endif
55 return 0;
56 }
57
58 static const VMStateDescription vmstate_pmp_entry = {
59 .name = "cpu/pmp/entry",
60 .version_id = 2,
61 .minimum_version_id = 2,
62 .fields = (const VMStateField[]) {
63 VMSTATE_UINT64(addr_reg, pmp_entry_t),
64 VMSTATE_UINT8(cfg_reg, pmp_entry_t),
65 VMSTATE_END_OF_LIST()
66 }
67 };
68
69 static const VMStateDescription vmstate_pmp = {
70 .name = "cpu/pmp",
71 .version_id = 2,
72 .minimum_version_id = 2,
73 .needed = pmp_needed,
74 .post_load = pmp_post_load,
75 .fields = (const VMStateField[]) {
76 VMSTATE_STRUCT_ARRAY(env.pmp_state.pmp, RISCVCPU, MAX_RISCV_PMPS,
77 0, vmstate_pmp_entry, pmp_entry_t),
78 VMSTATE_END_OF_LIST()
79 }
80 };
81
82 static bool hyper_needed(void *opaque)
83 {
84 RISCVCPU *cpu = opaque;
85 CPURISCVState *env = &cpu->env;
86
87 return riscv_has_ext(env, RVH);
88 }
89
90 static const VMStateDescription vmstate_hyper = {
91 .name = "cpu/hyper",
92 .version_id = 5,
93 .minimum_version_id = 5,
94 .needed = hyper_needed,
95 .fields = (const VMStateField[]) {
96 VMSTATE_UINT64(env.hstatus, RISCVCPU),
97 VMSTATE_UINT64(env.hedeleg, RISCVCPU),
98 VMSTATE_UINT64(env.hideleg, RISCVCPU),
99 VMSTATE_UINT32(env.hcounteren, RISCVCPU),
100 VMSTATE_UINT64(env.htval, RISCVCPU),
101 VMSTATE_UINT64(env.htinst, RISCVCPU),
102 VMSTATE_UINT64(env.hgatp, RISCVCPU),
103 VMSTATE_UINT64(env.hgeie, RISCVCPU),
104 VMSTATE_UINT64(env.hgeip, RISCVCPU),
105 VMSTATE_UINT64(env.hvien, RISCVCPU),
106 VMSTATE_UINT64(env.hvip, RISCVCPU),
107 VMSTATE_UINT64(env.htimedelta, RISCVCPU),
108 VMSTATE_UINT64(env.vstimecmp, RISCVCPU),
109
110 VMSTATE_UINT32(env.hvictl, RISCVCPU),
111 VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64),
112
113 VMSTATE_UINT64(env.vsstatus, RISCVCPU),
114 VMSTATE_UINT64(env.vstvec, RISCVCPU),
115 VMSTATE_UINT64(env.vsscratch, RISCVCPU),
116 VMSTATE_UINT64(env.vsepc, RISCVCPU),
117 VMSTATE_UINT64(env.vscause, RISCVCPU),
118 VMSTATE_UINT64(env.vstval, RISCVCPU),
119 VMSTATE_UINT64(env.vsatp, RISCVCPU),
120 VMSTATE_UINT16(env.vsiselect, RISCVCPU),
121 VMSTATE_UINT64(env.vsie, RISCVCPU),
122
123 VMSTATE_UINT64(env.mtval2, RISCVCPU),
124 VMSTATE_UINT64(env.mtinst, RISCVCPU),
125
126 VMSTATE_UINT64(env.stvec_hs, RISCVCPU),
127 VMSTATE_UINT64(env.sscratch_hs, RISCVCPU),
128 VMSTATE_UINT64(env.sepc_hs, RISCVCPU),
129 VMSTATE_UINT64(env.scause_hs, RISCVCPU),
130 VMSTATE_UINT64(env.stval_hs, RISCVCPU),
131 VMSTATE_UINT64(env.satp_hs, RISCVCPU),
132 VMSTATE_UINT64(env.mstatus_hs, RISCVCPU),
133
134 VMSTATE_END_OF_LIST()
135 }
136 };
137
138 static bool vector_needed(void *opaque)
139 {
140 RISCVCPU *cpu = opaque;
141 CPURISCVState *env = &cpu->env;
142
143 return kvm_enabled() ? riscv_has_ext(env, RVV) :
144 riscv_cpu_cfg(env)->ext_zve32x;
145 }
146
147 static const VMStateDescription vmstate_vector = {
148 .name = "cpu/vector",
149 .version_id = 3,
150 .minimum_version_id = 3,
151 .needed = vector_needed,
152 .fields = (const VMStateField[]) {
153 VMSTATE_UINT64_ARRAY(env.vreg, RISCVCPU, 32 * RV_VLEN_MAX / 64),
154 VMSTATE_UINT64(env.vtype, RISCVCPU),
155 VMSTATE_UINT32(env.vl, RISCVCPU),
156 VMSTATE_UINT32(env.vstart, RISCVCPU),
157 VMSTATE_UINT8(env.vxrm, RISCVCPU),
158 VMSTATE_UINT8(env.vxsat, RISCVCPU),
159 VMSTATE_BOOL(env.vill, RISCVCPU),
160 VMSTATE_END_OF_LIST()
161 }
162 };
163
164 static bool pointermasking_needed(void *opaque)
165 {
166 return false;
167 }
168
169 static const VMStateDescription vmstate_pointermasking = {
170 .name = "cpu/pointer_masking",
171 .version_id = 2,
172 .minimum_version_id = 2,
173 .needed = pointermasking_needed,
174 .fields = (const VMStateField[]) {
175
176 VMSTATE_END_OF_LIST()
177 }
178 };
179
180 static bool rv128_needed(void *opaque)
181 {
182 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(opaque);
183
184 return mcc->def->misa_mxl_max == MXL_RV128;
185 }
186
187 static const VMStateDescription vmstate_rv128 = {
188 .name = "cpu/rv128",
189 .version_id = 2,
190 .minimum_version_id = 2,
191 .needed = rv128_needed,
192 .fields = (const VMStateField[]) {
193 VMSTATE_UINT64_ARRAY(env.gprh, RISCVCPU, 32),
194 VMSTATE_UINT64(env.mscratchh, RISCVCPU),
195 VMSTATE_UINT64(env.sscratchh, RISCVCPU),
196 VMSTATE_END_OF_LIST()
197 }
198 };
199
200 #ifdef CONFIG_KVM
201 static bool kvmtimer_needed(void *opaque)
202 {
203 return kvm_enabled();
204 }
205
206 static int cpu_kvmtimer_post_load(void *opaque, int version_id)
207 {
208 RISCVCPU *cpu = opaque;
209 CPURISCVState *env = &cpu->env;
210
211 env->kvm_timer_dirty = true;
212 return 0;
213 }
214
215 static const VMStateDescription vmstate_kvmtimer = {
216 .name = "cpu/kvmtimer",
217 .version_id = 1,
218 .minimum_version_id = 1,
219 .needed = kvmtimer_needed,
220 .post_load = cpu_kvmtimer_post_load,
221 .fields = (const VMStateField[]) {
222 VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU),
223 VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU),
224 VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU),
225 VMSTATE_END_OF_LIST()
226 }
227 };
228
229 static int riscv_cpu_kvm_pre_load(void *opaque)
230 {
231 RISCVCPU *cpu = opaque;
232
233 cpu->env.kvm_mp_state_loaded = false;
234 return 0;
235 }
236
237 static bool kvm_mp_state_needed(void *opaque)
238 {
239 return kvm_enabled() && kvm_riscv_has_mp_state();
240 }
241
242 static int kvm_mp_state_post_load(void *opaque, int version_id)
243 {
244 RISCVCPU *cpu = opaque;
245 CPURISCVState *env = &cpu->env;
246
247 if (!kvm_enabled() || !kvm_riscv_has_mp_state()) {
248 return -ENOTSUP;
249 }
250
251 env->kvm_mp_state_loaded = true;
252 return 0;
253 }
254
255 static const VMStateDescription vmstate_kvm_mp_state = {
256 .name = "cpu/kvm-mp-state",
257 .version_id = 1,
258 .minimum_version_id = 1,
259 .needed = kvm_mp_state_needed,
260 .post_load = kvm_mp_state_post_load,
261 .fields = (const VMStateField[]) {
262 VMSTATE_UINT32(env.kvm_mp_state, RISCVCPU),
263 VMSTATE_END_OF_LIST()
264 }
265 };
266 #endif
267
268 static bool debug_needed(void *opaque)
269 {
270 RISCVCPU *cpu = opaque;
271
272 return cpu->cfg.debug;
273 }
274
275 static int debug_post_load(void *opaque, int version_id)
276 {
277 RISCVCPU *cpu = opaque;
278 CPURISCVState *env = &cpu->env;
279
280 if (icount_enabled()) {
281 env->itrigger_enabled = riscv_itrigger_enabled(env);
282 }
283
284 return 0;
285 }
286
287 static const VMStateDescription vmstate_debug = {
288 .name = "cpu/debug",
289 .version_id = 4,
290 .minimum_version_id = 4,
291 .needed = debug_needed,
292 .post_load = debug_post_load,
293 .fields = (const VMStateField[]) {
294 VMSTATE_UINT16(env.mcontext, RISCVCPU),
295 VMSTATE_UINT8(env.trigger_cur, RISCVCPU),
296 VMSTATE_VARRAY_UINT32(env.tdata1, RISCVCPU,
297 env.num_triggers, 0,
298 vmstate_info_uint64, uint64_t),
299 VMSTATE_VARRAY_UINT32(env.tdata2, RISCVCPU,
300 env.num_triggers, 0,
301 vmstate_info_uint64, uint64_t),
302 VMSTATE_VARRAY_UINT32(env.tdata3, RISCVCPU,
303 env.num_triggers, 0,
304 vmstate_info_uint64, uint64_t),
305 VMSTATE_END_OF_LIST()
306 }
307 };
308
309 static int riscv_cpu_post_load(void *opaque, int version_id)
310 {
311 RISCVCPU *cpu = opaque;
312 CPURISCVState *env = &cpu->env;
313
314 env->xl = cpu_recompute_xl(env);
315 return 0;
316 }
317
318 static bool smstateen_needed(void *opaque)
319 {
320 RISCVCPU *cpu = opaque;
321
322 return cpu->cfg.ext_smstateen;
323 }
324
325 static const VMStateDescription vmstate_smstateen = {
326 .name = "cpu/smtateen",
327 .version_id = 1,
328 .minimum_version_id = 1,
329 .needed = smstateen_needed,
330 .fields = (const VMStateField[]) {
331 VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4),
332 VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4),
333 VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4),
334 VMSTATE_END_OF_LIST()
335 }
336 };
337
338 static bool envcfg_needed(void *opaque)
339 {
340 RISCVCPU *cpu = opaque;
341 CPURISCVState *env = &cpu->env;
342
343 return (env->priv_ver >= PRIV_VERSION_1_12_0 ? 1 : 0);
344 }
345
346 static const VMStateDescription vmstate_envcfg = {
347 .name = "cpu/envcfg",
348 .version_id = 2,
349 .minimum_version_id = 2,
350 .needed = envcfg_needed,
351 .fields = (const VMStateField[]) {
352 VMSTATE_UINT64(env.menvcfg, RISCVCPU),
353 VMSTATE_UINT64(env.senvcfg, RISCVCPU),
354 VMSTATE_UINT64(env.henvcfg, RISCVCPU),
355 VMSTATE_END_OF_LIST()
356 }
357 };
358
359 static bool ctr_needed(void *opaque)
360 {
361 RISCVCPU *cpu = opaque;
362
363 return cpu->cfg.ext_smctr || cpu->cfg.ext_ssctr;
364 }
365
366 static const VMStateDescription vmstate_ctr = {
367 .name = "cpu/ctr",
368 .version_id = 1,
369 .minimum_version_id = 1,
370 .needed = ctr_needed,
371 .fields = (const VMStateField[]) {
372 VMSTATE_UINT64(env.mctrctl, RISCVCPU),
373 VMSTATE_UINT32(env.sctrdepth, RISCVCPU),
374 VMSTATE_UINT32(env.sctrstatus, RISCVCPU),
375 VMSTATE_UINT64(env.vsctrctl, RISCVCPU),
376 VMSTATE_UINT64_ARRAY(env.ctr_src, RISCVCPU, 16 << SCTRDEPTH_MAX),
377 VMSTATE_UINT64_ARRAY(env.ctr_dst, RISCVCPU, 16 << SCTRDEPTH_MAX),
378 VMSTATE_UINT64_ARRAY(env.ctr_data, RISCVCPU, 16 << SCTRDEPTH_MAX),
379 VMSTATE_END_OF_LIST()
380 }
381 };
382
383 static bool pmu_needed(void *opaque)
384 {
385 RISCVCPU *cpu = opaque;
386
387 return (cpu->cfg.pmu_mask > 0);
388 }
389
390 static const VMStateDescription vmstate_pmu_ctr_state = {
391 .name = "cpu/pmu",
392 .version_id = 3,
393 .minimum_version_id = 3,
394 .needed = pmu_needed,
395 .fields = (const VMStateField[]) {
396 VMSTATE_UINT64(mhpmcounter_val, PMUCTRState),
397 VMSTATE_UINT64(mhpmcounter_prev, PMUCTRState),
398 VMSTATE_END_OF_LIST()
399 }
400 };
401
402 static bool jvt_needed(void *opaque)
403 {
404 RISCVCPU *cpu = opaque;
405
406 return cpu->cfg.ext_zcmt;
407 }
408
409 static const VMStateDescription vmstate_jvt = {
410 .name = "cpu/jvt",
411 .version_id = 2,
412 .minimum_version_id = 2,
413 .needed = jvt_needed,
414 .fields = (const VMStateField[]) {
415 VMSTATE_UINT64(env.jvt, RISCVCPU),
416 VMSTATE_END_OF_LIST()
417 }
418 };
419
420 static bool elp_needed(void *opaque)
421 {
422 RISCVCPU *cpu = opaque;
423
424 return cpu->cfg.ext_zicfilp;
425 }
426
427 static const VMStateDescription vmstate_elp = {
428 .name = "cpu/elp",
429 .version_id = 1,
430 .minimum_version_id = 1,
431 .needed = elp_needed,
432 .fields = (const VMStateField[]) {
433 VMSTATE_BOOL(env.elp, RISCVCPU),
434 VMSTATE_END_OF_LIST()
435 }
436 };
437
438 static bool ssp_needed(void *opaque)
439 {
440 RISCVCPU *cpu = opaque;
441
442 return cpu->cfg.ext_zicfiss;
443 }
444
445 static const VMStateDescription vmstate_ssp = {
446 .name = "cpu/ssp",
447 .version_id = 2,
448 .minimum_version_id = 2,
449 .needed = ssp_needed,
450 .fields = (const VMStateField[]) {
451 VMSTATE_UINT64(env.ssp, RISCVCPU),
452 VMSTATE_END_OF_LIST()
453 }
454 };
455
456 static bool sstc_timer_needed(void *opaque)
457 {
458 RISCVCPU *cpu = opaque;
459 CPURISCVState *env = &cpu->env;
460
461 if (!cpu->cfg.ext_sstc) {
462 return false;
463 }
464
465 return env->stimer != NULL || env->vstimer != NULL;
466 }
467
468 static const VMStateDescription vmstate_sstc = {
469 .name = "cpu/timer",
470 .version_id = 1,
471 .minimum_version_id = 1,
472 .needed = sstc_timer_needed,
473 .fields = (const VMStateField[]) {
474 VMSTATE_TIMER_PTR(env.stimer, RISCVCPU),
475 VMSTATE_TIMER_PTR(env.vstimer, RISCVCPU),
476 VMSTATE_END_OF_LIST()
477 }
478 };
479
480 static bool mseccfg_needed(void *opaque)
481 {
482 RISCVCPU *cpu = opaque;
483
484 return cpu->cfg.ext_smepmp || cpu->cfg.ext_zkr
485 || cpu->cfg.ext_smmpm || cpu->cfg.ext_zicfilp;
486 }
487
488 static const VMStateDescription vmstate_mseccfg = {
489 .name = "cpu/mseccfg",
490 .version_id = 1,
491 .minimum_version_id = 1,
492 .needed = mseccfg_needed,
493 .fields = (const VMStateField[]) {
494 VMSTATE_UINT64(env.mseccfg, RISCVCPU),
495 VMSTATE_END_OF_LIST()
496 }
497 };
498
499 const VMStateDescription vmstate_riscv_cpu = {
500 .name = "cpu",
501 .version_id = 12,
502 .minimum_version_id = 12,
503 #ifdef CONFIG_KVM
504 .pre_load = riscv_cpu_kvm_pre_load,
505 #endif
506 .post_load = riscv_cpu_post_load,
507 .fields = (const VMStateField[]) {
508 VMSTATE_UINT64_ARRAY(env.gpr, RISCVCPU, 32),
509 VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
510 VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64),
511 VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64),
512 VMSTATE_UINT64(env.pc, RISCVCPU),
513 VMSTATE_UINT64(env.load_res, RISCVCPU),
514 VMSTATE_UINT64(env.load_val, RISCVCPU),
515 VMSTATE_UINT8(env.frm, RISCVCPU),
516 VMSTATE_UINT64(env.badaddr, RISCVCPU),
517 VMSTATE_UINT64(env.guest_phys_fault_addr, RISCVCPU),
518 VMSTATE_UINT32(env.priv_ver, RISCVCPU),
519 VMSTATE_UINT32(env.vext_ver, RISCVCPU),
520 VMSTATE_UINT32(env.misa_mxl, RISCVCPU),
521 VMSTATE_UINT32(env.misa_ext, RISCVCPU),
522 VMSTATE_UNUSED(4),
523 VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU),
524 VMSTATE_UINT8(env.priv, RISCVCPU),
525 VMSTATE_BOOL(env.virt_enabled, RISCVCPU),
526 VMSTATE_UINT64(env.resetvec, RISCVCPU),
527 VMSTATE_UINT64(env.mhartid, RISCVCPU),
528 VMSTATE_UINT64(env.mstatus, RISCVCPU),
529 VMSTATE_UINT64(env.mip, RISCVCPU),
530 VMSTATE_UINT64(env.miclaim, RISCVCPU),
531 VMSTATE_UINT64(env.mie, RISCVCPU),
532 VMSTATE_UINT64(env.mvien, RISCVCPU),
533 VMSTATE_UINT64(env.mvip, RISCVCPU),
534 VMSTATE_UINT64(env.sie, RISCVCPU),
535 VMSTATE_UINT64(env.mideleg, RISCVCPU),
536 VMSTATE_UINT64(env.satp, RISCVCPU),
537 VMSTATE_UINT64(env.stval, RISCVCPU),
538 VMSTATE_UINT64(env.medeleg, RISCVCPU),
539 VMSTATE_UINT64(env.stvec, RISCVCPU),
540 VMSTATE_UINT64(env.sepc, RISCVCPU),
541 VMSTATE_UINT64(env.scause, RISCVCPU),
542 VMSTATE_UINT64(env.mtvec, RISCVCPU),
543 VMSTATE_UINT64(env.mepc, RISCVCPU),
544 VMSTATE_UINT64(env.mcause, RISCVCPU),
545 VMSTATE_UINT64(env.mtval, RISCVCPU),
546 VMSTATE_UINT16(env.miselect, RISCVCPU),
547 VMSTATE_UINT16(env.siselect, RISCVCPU),
548 VMSTATE_UINT32(env.scounteren, RISCVCPU),
549 VMSTATE_UINT32(env.mcounteren, RISCVCPU),
550 VMSTATE_UINT32(env.scountinhibit, RISCVCPU),
551 VMSTATE_UINT32(env.mcountinhibit, RISCVCPU),
552 VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0,
553 vmstate_pmu_ctr_state, PMUCTRState),
554 VMSTATE_UINT64_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS),
555 VMSTATE_UINT64(env.sscratch, RISCVCPU),
556 VMSTATE_UINT64(env.mscratch, RISCVCPU),
557 VMSTATE_UINT64(env.stimecmp, RISCVCPU),
558
559 VMSTATE_END_OF_LIST()
560 },
561 .subsections = (const VMStateDescription * const []) {
562 &vmstate_pmp,
563 &vmstate_hyper,
564 &vmstate_vector,
565 &vmstate_pointermasking,
566 &vmstate_rv128,
567 #ifdef CONFIG_KVM
568 &vmstate_kvmtimer,
569 &vmstate_kvm_mp_state,
570 #endif
571 &vmstate_envcfg,
572 &vmstate_debug,
573 &vmstate_smstateen,
574 &vmstate_jvt,
575 &vmstate_elp,
576 &vmstate_ssp,
577 &vmstate_ctr,
578 &vmstate_sstc,
579 &vmstate_mseccfg,
580 NULL
581 }
582 };
583
584 const InterfaceInfo riscv32_machine_interfaces[] = {
585 { TYPE_TARGET_RISCV32_MACHINE },
586 { }
587 };
588
589 const InterfaceInfo riscv64_machine_interfaces[] = {
590 { TYPE_TARGET_RISCV64_MACHINE },
591 { }
592 };
593
594 const InterfaceInfo riscv32_64_machine_interfaces[] = {
595 { TYPE_TARGET_RISCV32_MACHINE },
596 { TYPE_TARGET_RISCV64_MACHINE },
597 { }
598 };