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 "migration/cpu.h" 24 #include "exec/icount.h" 25 #include "debug.h" 26 27 static bool pmp_needed(void *opaque) 28 { 29 RISCVCPU *cpu = opaque; 30 31 return cpu->cfg.pmp; 32 } 33 34 static int pmp_post_load(void *opaque, int version_id) 35 { 36 RISCVCPU *cpu = opaque; 37 CPURISCVState *env = &cpu->env; 38 int i; 39 uint8_t pmp_regions = riscv_cpu_cfg(env)->pmp_regions; 40 41 for (i = 0; i < pmp_regions; i++) { 42 pmp_update_rule_addr(env, i); 43 } 44 pmp_update_rule_nums(env); 45 46 return 0; 47 } 48 49 static const VMStateDescription vmstate_pmp_entry = { 50 .name = "cpu/pmp/entry", 51 .version_id = 1, 52 .minimum_version_id = 1, 53 .fields = (const VMStateField[]) { 54 VMSTATE_UINTTL(addr_reg, pmp_entry_t), 55 VMSTATE_UINT8(cfg_reg, pmp_entry_t), 56 VMSTATE_END_OF_LIST() 57 } 58 }; 59 60 static const VMStateDescription vmstate_pmp = { 61 .name = "cpu/pmp", 62 .version_id = 1, 63 .minimum_version_id = 1, 64 .needed = pmp_needed, 65 .post_load = pmp_post_load, 66 .fields = (const VMStateField[]) { 67 VMSTATE_STRUCT_ARRAY(env.pmp_state.pmp, RISCVCPU, MAX_RISCV_PMPS, 68 0, vmstate_pmp_entry, pmp_entry_t), 69 VMSTATE_END_OF_LIST() 70 } 71 }; 72 73 static bool hyper_needed(void *opaque) 74 { 75 RISCVCPU *cpu = opaque; 76 CPURISCVState *env = &cpu->env; 77 78 return riscv_has_ext(env, RVH); 79 } 80 81 static const VMStateDescription vmstate_hyper = { 82 .name = "cpu/hyper", 83 .version_id = 4, 84 .minimum_version_id = 4, 85 .needed = hyper_needed, 86 .fields = (const VMStateField[]) { 87 VMSTATE_UINTTL(env.hstatus, RISCVCPU), 88 VMSTATE_UINTTL(env.hedeleg, RISCVCPU), 89 VMSTATE_UINT64(env.hideleg, RISCVCPU), 90 VMSTATE_UINT32(env.hcounteren, RISCVCPU), 91 VMSTATE_UINTTL(env.htval, RISCVCPU), 92 VMSTATE_UINTTL(env.htinst, RISCVCPU), 93 VMSTATE_UINTTL(env.hgatp, RISCVCPU), 94 VMSTATE_UINTTL(env.hgeie, RISCVCPU), 95 VMSTATE_UINTTL(env.hgeip, RISCVCPU), 96 VMSTATE_UINT64(env.hvien, RISCVCPU), 97 VMSTATE_UINT64(env.hvip, RISCVCPU), 98 VMSTATE_UINT64(env.htimedelta, RISCVCPU), 99 VMSTATE_UINT64(env.vstimecmp, RISCVCPU), 100 101 VMSTATE_UINTTL(env.hvictl, RISCVCPU), 102 VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64), 103 104 VMSTATE_UINT64(env.vsstatus, RISCVCPU), 105 VMSTATE_UINTTL(env.vstvec, RISCVCPU), 106 VMSTATE_UINTTL(env.vsscratch, RISCVCPU), 107 VMSTATE_UINTTL(env.vsepc, RISCVCPU), 108 VMSTATE_UINTTL(env.vscause, RISCVCPU), 109 VMSTATE_UINTTL(env.vstval, RISCVCPU), 110 VMSTATE_UINTTL(env.vsatp, RISCVCPU), 111 VMSTATE_UINTTL(env.vsiselect, RISCVCPU), 112 VMSTATE_UINT64(env.vsie, RISCVCPU), 113 114 VMSTATE_UINTTL(env.mtval2, RISCVCPU), 115 VMSTATE_UINTTL(env.mtinst, RISCVCPU), 116 117 VMSTATE_UINTTL(env.stvec_hs, RISCVCPU), 118 VMSTATE_UINTTL(env.sscratch_hs, RISCVCPU), 119 VMSTATE_UINTTL(env.sepc_hs, RISCVCPU), 120 VMSTATE_UINTTL(env.scause_hs, RISCVCPU), 121 VMSTATE_UINTTL(env.stval_hs, RISCVCPU), 122 VMSTATE_UINTTL(env.satp_hs, RISCVCPU), 123 VMSTATE_UINT64(env.mstatus_hs, RISCVCPU), 124 125 VMSTATE_END_OF_LIST() 126 } 127 }; 128 129 static bool vector_needed(void *opaque) 130 { 131 RISCVCPU *cpu = opaque; 132 CPURISCVState *env = &cpu->env; 133 134 return kvm_enabled() ? riscv_has_ext(env, RVV) : 135 riscv_cpu_cfg(env)->ext_zve32x; 136 } 137 138 static const VMStateDescription vmstate_vector = { 139 .name = "cpu/vector", 140 .version_id = 2, 141 .minimum_version_id = 2, 142 .needed = vector_needed, 143 .fields = (const VMStateField[]) { 144 VMSTATE_UINT64_ARRAY(env.vreg, RISCVCPU, 32 * RV_VLEN_MAX / 64), 145 VMSTATE_UINTTL(env.vxrm, RISCVCPU), 146 VMSTATE_UINTTL(env.vxsat, RISCVCPU), 147 VMSTATE_UINTTL(env.vl, RISCVCPU), 148 VMSTATE_UINTTL(env.vstart, RISCVCPU), 149 VMSTATE_UINTTL(env.vtype, RISCVCPU), 150 VMSTATE_BOOL(env.vill, RISCVCPU), 151 VMSTATE_END_OF_LIST() 152 } 153 }; 154 155 static bool pointermasking_needed(void *opaque) 156 { 157 return false; 158 } 159 160 static const VMStateDescription vmstate_pointermasking = { 161 .name = "cpu/pointer_masking", 162 .version_id = 2, 163 .minimum_version_id = 2, 164 .needed = pointermasking_needed, 165 .fields = (const VMStateField[]) { 166 167 VMSTATE_END_OF_LIST() 168 } 169 }; 170 171 static bool rv128_needed(void *opaque) 172 { 173 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(opaque); 174 175 return mcc->def->misa_mxl_max == MXL_RV128; 176 } 177 178 static const VMStateDescription vmstate_rv128 = { 179 .name = "cpu/rv128", 180 .version_id = 1, 181 .minimum_version_id = 1, 182 .needed = rv128_needed, 183 .fields = (const VMStateField[]) { 184 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32), 185 VMSTATE_UINT64(env.mscratchh, RISCVCPU), 186 VMSTATE_UINT64(env.sscratchh, RISCVCPU), 187 VMSTATE_END_OF_LIST() 188 } 189 }; 190 191 #ifdef CONFIG_KVM 192 static bool kvmtimer_needed(void *opaque) 193 { 194 return kvm_enabled(); 195 } 196 197 static int cpu_kvmtimer_post_load(void *opaque, int version_id) 198 { 199 RISCVCPU *cpu = opaque; 200 CPURISCVState *env = &cpu->env; 201 202 env->kvm_timer_dirty = true; 203 return 0; 204 } 205 206 static const VMStateDescription vmstate_kvmtimer = { 207 .name = "cpu/kvmtimer", 208 .version_id = 1, 209 .minimum_version_id = 1, 210 .needed = kvmtimer_needed, 211 .post_load = cpu_kvmtimer_post_load, 212 .fields = (const VMStateField[]) { 213 VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), 214 VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), 215 VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), 216 VMSTATE_END_OF_LIST() 217 } 218 }; 219 #endif 220 221 static bool debug_needed(void *opaque) 222 { 223 RISCVCPU *cpu = opaque; 224 225 return cpu->cfg.debug; 226 } 227 228 static int debug_post_load(void *opaque, int version_id) 229 { 230 RISCVCPU *cpu = opaque; 231 CPURISCVState *env = &cpu->env; 232 233 if (icount_enabled()) { 234 env->itrigger_enabled = riscv_itrigger_enabled(env); 235 } 236 237 return 0; 238 } 239 240 static const VMStateDescription vmstate_debug = { 241 .name = "cpu/debug", 242 .version_id = 2, 243 .minimum_version_id = 2, 244 .needed = debug_needed, 245 .post_load = debug_post_load, 246 .fields = (const VMStateField[]) { 247 VMSTATE_UINTTL(env.trigger_cur, RISCVCPU), 248 VMSTATE_UINTTL_ARRAY(env.tdata1, RISCVCPU, RV_MAX_TRIGGERS), 249 VMSTATE_UINTTL_ARRAY(env.tdata2, RISCVCPU, RV_MAX_TRIGGERS), 250 VMSTATE_UINTTL_ARRAY(env.tdata3, RISCVCPU, RV_MAX_TRIGGERS), 251 VMSTATE_END_OF_LIST() 252 } 253 }; 254 255 static int riscv_cpu_post_load(void *opaque, int version_id) 256 { 257 RISCVCPU *cpu = opaque; 258 CPURISCVState *env = &cpu->env; 259 260 env->xl = cpu_recompute_xl(env); 261 return 0; 262 } 263 264 static bool smstateen_needed(void *opaque) 265 { 266 RISCVCPU *cpu = opaque; 267 268 return cpu->cfg.ext_smstateen; 269 } 270 271 static const VMStateDescription vmstate_smstateen = { 272 .name = "cpu/smtateen", 273 .version_id = 1, 274 .minimum_version_id = 1, 275 .needed = smstateen_needed, 276 .fields = (const VMStateField[]) { 277 VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4), 278 VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4), 279 VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4), 280 VMSTATE_END_OF_LIST() 281 } 282 }; 283 284 static bool envcfg_needed(void *opaque) 285 { 286 RISCVCPU *cpu = opaque; 287 CPURISCVState *env = &cpu->env; 288 289 return (env->priv_ver >= PRIV_VERSION_1_12_0 ? 1 : 0); 290 } 291 292 static const VMStateDescription vmstate_envcfg = { 293 .name = "cpu/envcfg", 294 .version_id = 1, 295 .minimum_version_id = 1, 296 .needed = envcfg_needed, 297 .fields = (const VMStateField[]) { 298 VMSTATE_UINT64(env.menvcfg, RISCVCPU), 299 VMSTATE_UINTTL(env.senvcfg, RISCVCPU), 300 VMSTATE_UINT64(env.henvcfg, RISCVCPU), 301 VMSTATE_END_OF_LIST() 302 } 303 }; 304 305 static bool ctr_needed(void *opaque) 306 { 307 RISCVCPU *cpu = opaque; 308 309 return cpu->cfg.ext_smctr || cpu->cfg.ext_ssctr; 310 } 311 312 static const VMStateDescription vmstate_ctr = { 313 .name = "cpu/ctr", 314 .version_id = 1, 315 .minimum_version_id = 1, 316 .needed = ctr_needed, 317 .fields = (const VMStateField[]) { 318 VMSTATE_UINT64(env.mctrctl, RISCVCPU), 319 VMSTATE_UINT32(env.sctrdepth, RISCVCPU), 320 VMSTATE_UINT32(env.sctrstatus, RISCVCPU), 321 VMSTATE_UINT64(env.vsctrctl, RISCVCPU), 322 VMSTATE_UINT64_ARRAY(env.ctr_src, RISCVCPU, 16 << SCTRDEPTH_MAX), 323 VMSTATE_UINT64_ARRAY(env.ctr_dst, RISCVCPU, 16 << SCTRDEPTH_MAX), 324 VMSTATE_UINT64_ARRAY(env.ctr_data, RISCVCPU, 16 << SCTRDEPTH_MAX), 325 VMSTATE_END_OF_LIST() 326 } 327 }; 328 329 static bool pmu_needed(void *opaque) 330 { 331 RISCVCPU *cpu = opaque; 332 333 return (cpu->cfg.pmu_mask > 0); 334 } 335 336 static const VMStateDescription vmstate_pmu_ctr_state = { 337 .name = "cpu/pmu", 338 .version_id = 2, 339 .minimum_version_id = 2, 340 .needed = pmu_needed, 341 .fields = (const VMStateField[]) { 342 VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState), 343 VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState), 344 VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState), 345 VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState), 346 VMSTATE_END_OF_LIST() 347 } 348 }; 349 350 static bool jvt_needed(void *opaque) 351 { 352 RISCVCPU *cpu = opaque; 353 354 return cpu->cfg.ext_zcmt; 355 } 356 357 static const VMStateDescription vmstate_jvt = { 358 .name = "cpu/jvt", 359 .version_id = 1, 360 .minimum_version_id = 1, 361 .needed = jvt_needed, 362 .fields = (const VMStateField[]) { 363 VMSTATE_UINTTL(env.jvt, RISCVCPU), 364 VMSTATE_END_OF_LIST() 365 } 366 }; 367 368 static bool elp_needed(void *opaque) 369 { 370 RISCVCPU *cpu = opaque; 371 372 return cpu->cfg.ext_zicfilp; 373 } 374 375 static const VMStateDescription vmstate_elp = { 376 .name = "cpu/elp", 377 .version_id = 1, 378 .minimum_version_id = 1, 379 .needed = elp_needed, 380 .fields = (const VMStateField[]) { 381 VMSTATE_BOOL(env.elp, RISCVCPU), 382 VMSTATE_END_OF_LIST() 383 } 384 }; 385 386 static bool ssp_needed(void *opaque) 387 { 388 RISCVCPU *cpu = opaque; 389 390 return cpu->cfg.ext_zicfiss; 391 } 392 393 static const VMStateDescription vmstate_ssp = { 394 .name = "cpu/ssp", 395 .version_id = 1, 396 .minimum_version_id = 1, 397 .needed = ssp_needed, 398 .fields = (const VMStateField[]) { 399 VMSTATE_UINTTL(env.ssp, RISCVCPU), 400 VMSTATE_END_OF_LIST() 401 } 402 }; 403 404 const VMStateDescription vmstate_riscv_cpu = { 405 .name = "cpu", 406 .version_id = 10, 407 .minimum_version_id = 10, 408 .post_load = riscv_cpu_post_load, 409 .fields = (const VMStateField[]) { 410 VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), 411 VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), 412 VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64), 413 VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64), 414 VMSTATE_UINTTL(env.pc, RISCVCPU), 415 VMSTATE_UINTTL(env.load_res, RISCVCPU), 416 VMSTATE_UINTTL(env.load_val, RISCVCPU), 417 VMSTATE_UINTTL(env.frm, RISCVCPU), 418 VMSTATE_UINTTL(env.badaddr, RISCVCPU), 419 VMSTATE_UINTTL(env.guest_phys_fault_addr, RISCVCPU), 420 VMSTATE_UINTTL(env.priv_ver, RISCVCPU), 421 VMSTATE_UINTTL(env.vext_ver, RISCVCPU), 422 VMSTATE_UINT32(env.misa_mxl, RISCVCPU), 423 VMSTATE_UINT32(env.misa_ext, RISCVCPU), 424 VMSTATE_UNUSED(4), 425 VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU), 426 VMSTATE_UINTTL(env.priv, RISCVCPU), 427 VMSTATE_BOOL(env.virt_enabled, RISCVCPU), 428 VMSTATE_UINT64(env.resetvec, RISCVCPU), 429 VMSTATE_UINTTL(env.mhartid, RISCVCPU), 430 VMSTATE_UINT64(env.mstatus, RISCVCPU), 431 VMSTATE_UINT64(env.mip, RISCVCPU), 432 VMSTATE_UINT64(env.miclaim, RISCVCPU), 433 VMSTATE_UINT64(env.mie, RISCVCPU), 434 VMSTATE_UINT64(env.mvien, RISCVCPU), 435 VMSTATE_UINT64(env.mvip, RISCVCPU), 436 VMSTATE_UINT64(env.sie, RISCVCPU), 437 VMSTATE_UINT64(env.mideleg, RISCVCPU), 438 VMSTATE_UINTTL(env.satp, RISCVCPU), 439 VMSTATE_UINTTL(env.stval, RISCVCPU), 440 VMSTATE_UINTTL(env.medeleg, RISCVCPU), 441 VMSTATE_UINTTL(env.stvec, RISCVCPU), 442 VMSTATE_UINTTL(env.sepc, RISCVCPU), 443 VMSTATE_UINTTL(env.scause, RISCVCPU), 444 VMSTATE_UINTTL(env.mtvec, RISCVCPU), 445 VMSTATE_UINTTL(env.mepc, RISCVCPU), 446 VMSTATE_UINTTL(env.mcause, RISCVCPU), 447 VMSTATE_UINTTL(env.mtval, RISCVCPU), 448 VMSTATE_UINTTL(env.miselect, RISCVCPU), 449 VMSTATE_UINTTL(env.siselect, RISCVCPU), 450 VMSTATE_UINT32(env.scounteren, RISCVCPU), 451 VMSTATE_UINT32(env.mcounteren, RISCVCPU), 452 VMSTATE_UINT32(env.scountinhibit, RISCVCPU), 453 VMSTATE_UINT32(env.mcountinhibit, RISCVCPU), 454 VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0, 455 vmstate_pmu_ctr_state, PMUCTRState), 456 VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS), 457 VMSTATE_UINTTL_ARRAY(env.mhpmeventh_val, RISCVCPU, RV_MAX_MHPMEVENTS), 458 VMSTATE_UINTTL(env.sscratch, RISCVCPU), 459 VMSTATE_UINTTL(env.mscratch, RISCVCPU), 460 VMSTATE_UINT64(env.stimecmp, RISCVCPU), 461 462 VMSTATE_END_OF_LIST() 463 }, 464 .subsections = (const VMStateDescription * const []) { 465 &vmstate_pmp, 466 &vmstate_hyper, 467 &vmstate_vector, 468 &vmstate_pointermasking, 469 &vmstate_rv128, 470 #ifdef CONFIG_KVM 471 &vmstate_kvmtimer, 472 #endif 473 &vmstate_envcfg, 474 &vmstate_debug, 475 &vmstate_smstateen, 476 &vmstate_jvt, 477 &vmstate_elp, 478 &vmstate_ssp, 479 &vmstate_ctr, 480 NULL 481 } 482 }; 483