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 riscv_has_ext(env, RVV); 135 } 136 137 static const VMStateDescription vmstate_vector = { 138 .name = "cpu/vector", 139 .version_id = 2, 140 .minimum_version_id = 2, 141 .needed = vector_needed, 142 .fields = (const VMStateField[]) { 143 VMSTATE_UINT64_ARRAY(env.vreg, RISCVCPU, 32 * RV_VLEN_MAX / 64), 144 VMSTATE_UINTTL(env.vxrm, RISCVCPU), 145 VMSTATE_UINTTL(env.vxsat, RISCVCPU), 146 VMSTATE_UINTTL(env.vl, RISCVCPU), 147 VMSTATE_UINTTL(env.vstart, RISCVCPU), 148 VMSTATE_UINTTL(env.vtype, RISCVCPU), 149 VMSTATE_BOOL(env.vill, RISCVCPU), 150 VMSTATE_END_OF_LIST() 151 } 152 }; 153 154 static bool pointermasking_needed(void *opaque) 155 { 156 return false; 157 } 158 159 static const VMStateDescription vmstate_pointermasking = { 160 .name = "cpu/pointer_masking", 161 .version_id = 2, 162 .minimum_version_id = 2, 163 .needed = pointermasking_needed, 164 .fields = (const VMStateField[]) { 165 166 VMSTATE_END_OF_LIST() 167 } 168 }; 169 170 static bool rv128_needed(void *opaque) 171 { 172 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(opaque); 173 174 return mcc->def->misa_mxl_max == MXL_RV128; 175 } 176 177 static const VMStateDescription vmstate_rv128 = { 178 .name = "cpu/rv128", 179 .version_id = 1, 180 .minimum_version_id = 1, 181 .needed = rv128_needed, 182 .fields = (const VMStateField[]) { 183 VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32), 184 VMSTATE_UINT64(env.mscratchh, RISCVCPU), 185 VMSTATE_UINT64(env.sscratchh, RISCVCPU), 186 VMSTATE_END_OF_LIST() 187 } 188 }; 189 190 #ifdef CONFIG_KVM 191 static bool kvmtimer_needed(void *opaque) 192 { 193 return kvm_enabled(); 194 } 195 196 static int cpu_kvmtimer_post_load(void *opaque, int version_id) 197 { 198 RISCVCPU *cpu = opaque; 199 CPURISCVState *env = &cpu->env; 200 201 env->kvm_timer_dirty = true; 202 return 0; 203 } 204 205 static const VMStateDescription vmstate_kvmtimer = { 206 .name = "cpu/kvmtimer", 207 .version_id = 1, 208 .minimum_version_id = 1, 209 .needed = kvmtimer_needed, 210 .post_load = cpu_kvmtimer_post_load, 211 .fields = (const VMStateField[]) { 212 VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), 213 VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), 214 VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), 215 VMSTATE_END_OF_LIST() 216 } 217 }; 218 #endif 219 220 static bool debug_needed(void *opaque) 221 { 222 RISCVCPU *cpu = opaque; 223 224 return cpu->cfg.debug; 225 } 226 227 static int debug_post_load(void *opaque, int version_id) 228 { 229 RISCVCPU *cpu = opaque; 230 CPURISCVState *env = &cpu->env; 231 232 if (icount_enabled()) { 233 env->itrigger_enabled = riscv_itrigger_enabled(env); 234 } 235 236 return 0; 237 } 238 239 static const VMStateDescription vmstate_debug = { 240 .name = "cpu/debug", 241 .version_id = 2, 242 .minimum_version_id = 2, 243 .needed = debug_needed, 244 .post_load = debug_post_load, 245 .fields = (const VMStateField[]) { 246 VMSTATE_UINTTL(env.trigger_cur, RISCVCPU), 247 VMSTATE_UINTTL_ARRAY(env.tdata1, RISCVCPU, RV_MAX_TRIGGERS), 248 VMSTATE_UINTTL_ARRAY(env.tdata2, RISCVCPU, RV_MAX_TRIGGERS), 249 VMSTATE_UINTTL_ARRAY(env.tdata3, RISCVCPU, RV_MAX_TRIGGERS), 250 VMSTATE_END_OF_LIST() 251 } 252 }; 253 254 static int riscv_cpu_post_load(void *opaque, int version_id) 255 { 256 RISCVCPU *cpu = opaque; 257 CPURISCVState *env = &cpu->env; 258 259 env->xl = cpu_recompute_xl(env); 260 return 0; 261 } 262 263 static bool smstateen_needed(void *opaque) 264 { 265 RISCVCPU *cpu = opaque; 266 267 return cpu->cfg.ext_smstateen; 268 } 269 270 static const VMStateDescription vmstate_smstateen = { 271 .name = "cpu/smtateen", 272 .version_id = 1, 273 .minimum_version_id = 1, 274 .needed = smstateen_needed, 275 .fields = (const VMStateField[]) { 276 VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4), 277 VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4), 278 VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4), 279 VMSTATE_END_OF_LIST() 280 } 281 }; 282 283 static bool envcfg_needed(void *opaque) 284 { 285 RISCVCPU *cpu = opaque; 286 CPURISCVState *env = &cpu->env; 287 288 return (env->priv_ver >= PRIV_VERSION_1_12_0 ? 1 : 0); 289 } 290 291 static const VMStateDescription vmstate_envcfg = { 292 .name = "cpu/envcfg", 293 .version_id = 1, 294 .minimum_version_id = 1, 295 .needed = envcfg_needed, 296 .fields = (const VMStateField[]) { 297 VMSTATE_UINT64(env.menvcfg, RISCVCPU), 298 VMSTATE_UINTTL(env.senvcfg, RISCVCPU), 299 VMSTATE_UINT64(env.henvcfg, RISCVCPU), 300 VMSTATE_END_OF_LIST() 301 } 302 }; 303 304 static bool ctr_needed(void *opaque) 305 { 306 RISCVCPU *cpu = opaque; 307 308 return cpu->cfg.ext_smctr || cpu->cfg.ext_ssctr; 309 } 310 311 static const VMStateDescription vmstate_ctr = { 312 .name = "cpu/ctr", 313 .version_id = 1, 314 .minimum_version_id = 1, 315 .needed = ctr_needed, 316 .fields = (const VMStateField[]) { 317 VMSTATE_UINT64(env.mctrctl, RISCVCPU), 318 VMSTATE_UINT32(env.sctrdepth, RISCVCPU), 319 VMSTATE_UINT32(env.sctrstatus, RISCVCPU), 320 VMSTATE_UINT64(env.vsctrctl, RISCVCPU), 321 VMSTATE_UINT64_ARRAY(env.ctr_src, RISCVCPU, 16 << SCTRDEPTH_MAX), 322 VMSTATE_UINT64_ARRAY(env.ctr_dst, RISCVCPU, 16 << SCTRDEPTH_MAX), 323 VMSTATE_UINT64_ARRAY(env.ctr_data, RISCVCPU, 16 << SCTRDEPTH_MAX), 324 VMSTATE_END_OF_LIST() 325 } 326 }; 327 328 static bool pmu_needed(void *opaque) 329 { 330 RISCVCPU *cpu = opaque; 331 332 return (cpu->cfg.pmu_mask > 0); 333 } 334 335 static const VMStateDescription vmstate_pmu_ctr_state = { 336 .name = "cpu/pmu", 337 .version_id = 2, 338 .minimum_version_id = 2, 339 .needed = pmu_needed, 340 .fields = (const VMStateField[]) { 341 VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState), 342 VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState), 343 VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState), 344 VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState), 345 VMSTATE_END_OF_LIST() 346 } 347 }; 348 349 static bool jvt_needed(void *opaque) 350 { 351 RISCVCPU *cpu = opaque; 352 353 return cpu->cfg.ext_zcmt; 354 } 355 356 static const VMStateDescription vmstate_jvt = { 357 .name = "cpu/jvt", 358 .version_id = 1, 359 .minimum_version_id = 1, 360 .needed = jvt_needed, 361 .fields = (const VMStateField[]) { 362 VMSTATE_UINTTL(env.jvt, RISCVCPU), 363 VMSTATE_END_OF_LIST() 364 } 365 }; 366 367 static bool elp_needed(void *opaque) 368 { 369 RISCVCPU *cpu = opaque; 370 371 return cpu->cfg.ext_zicfilp; 372 } 373 374 static const VMStateDescription vmstate_elp = { 375 .name = "cpu/elp", 376 .version_id = 1, 377 .minimum_version_id = 1, 378 .needed = elp_needed, 379 .fields = (const VMStateField[]) { 380 VMSTATE_BOOL(env.elp, RISCVCPU), 381 VMSTATE_END_OF_LIST() 382 } 383 }; 384 385 static bool ssp_needed(void *opaque) 386 { 387 RISCVCPU *cpu = opaque; 388 389 return cpu->cfg.ext_zicfiss; 390 } 391 392 static const VMStateDescription vmstate_ssp = { 393 .name = "cpu/ssp", 394 .version_id = 1, 395 .minimum_version_id = 1, 396 .needed = ssp_needed, 397 .fields = (const VMStateField[]) { 398 VMSTATE_UINTTL(env.ssp, RISCVCPU), 399 VMSTATE_END_OF_LIST() 400 } 401 }; 402 403 const VMStateDescription vmstate_riscv_cpu = { 404 .name = "cpu", 405 .version_id = 10, 406 .minimum_version_id = 10, 407 .post_load = riscv_cpu_post_load, 408 .fields = (const VMStateField[]) { 409 VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), 410 VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), 411 VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64), 412 VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64), 413 VMSTATE_UINTTL(env.pc, RISCVCPU), 414 VMSTATE_UINTTL(env.load_res, RISCVCPU), 415 VMSTATE_UINTTL(env.load_val, RISCVCPU), 416 VMSTATE_UINTTL(env.frm, RISCVCPU), 417 VMSTATE_UINTTL(env.badaddr, RISCVCPU), 418 VMSTATE_UINTTL(env.guest_phys_fault_addr, RISCVCPU), 419 VMSTATE_UINTTL(env.priv_ver, RISCVCPU), 420 VMSTATE_UINTTL(env.vext_ver, RISCVCPU), 421 VMSTATE_UINT32(env.misa_mxl, RISCVCPU), 422 VMSTATE_UINT32(env.misa_ext, RISCVCPU), 423 VMSTATE_UNUSED(4), 424 VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU), 425 VMSTATE_UINTTL(env.priv, RISCVCPU), 426 VMSTATE_BOOL(env.virt_enabled, RISCVCPU), 427 VMSTATE_UINT64(env.resetvec, RISCVCPU), 428 VMSTATE_UINTTL(env.mhartid, RISCVCPU), 429 VMSTATE_UINT64(env.mstatus, RISCVCPU), 430 VMSTATE_UINT64(env.mip, RISCVCPU), 431 VMSTATE_UINT64(env.miclaim, RISCVCPU), 432 VMSTATE_UINT64(env.mie, RISCVCPU), 433 VMSTATE_UINT64(env.mvien, RISCVCPU), 434 VMSTATE_UINT64(env.mvip, RISCVCPU), 435 VMSTATE_UINT64(env.sie, RISCVCPU), 436 VMSTATE_UINT64(env.mideleg, RISCVCPU), 437 VMSTATE_UINTTL(env.satp, RISCVCPU), 438 VMSTATE_UINTTL(env.stval, RISCVCPU), 439 VMSTATE_UINTTL(env.medeleg, RISCVCPU), 440 VMSTATE_UINTTL(env.stvec, RISCVCPU), 441 VMSTATE_UINTTL(env.sepc, RISCVCPU), 442 VMSTATE_UINTTL(env.scause, RISCVCPU), 443 VMSTATE_UINTTL(env.mtvec, RISCVCPU), 444 VMSTATE_UINTTL(env.mepc, RISCVCPU), 445 VMSTATE_UINTTL(env.mcause, RISCVCPU), 446 VMSTATE_UINTTL(env.mtval, RISCVCPU), 447 VMSTATE_UINTTL(env.miselect, RISCVCPU), 448 VMSTATE_UINTTL(env.siselect, RISCVCPU), 449 VMSTATE_UINT32(env.scounteren, RISCVCPU), 450 VMSTATE_UINT32(env.mcounteren, RISCVCPU), 451 VMSTATE_UINT32(env.scountinhibit, RISCVCPU), 452 VMSTATE_UINT32(env.mcountinhibit, RISCVCPU), 453 VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0, 454 vmstate_pmu_ctr_state, PMUCTRState), 455 VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS), 456 VMSTATE_UINTTL_ARRAY(env.mhpmeventh_val, RISCVCPU, RV_MAX_MHPMEVENTS), 457 VMSTATE_UINTTL(env.sscratch, RISCVCPU), 458 VMSTATE_UINTTL(env.mscratch, RISCVCPU), 459 VMSTATE_UINT64(env.stimecmp, RISCVCPU), 460 461 VMSTATE_END_OF_LIST() 462 }, 463 .subsections = (const VMStateDescription * const []) { 464 &vmstate_pmp, 465 &vmstate_hyper, 466 &vmstate_vector, 467 &vmstate_pointermasking, 468 &vmstate_rv128, 469 #ifdef CONFIG_KVM 470 &vmstate_kvmtimer, 471 #endif 472 &vmstate_envcfg, 473 &vmstate_debug, 474 &vmstate_smstateen, 475 &vmstate_jvt, 476 &vmstate_elp, 477 &vmstate_ssp, 478 &vmstate_ctr, 479 NULL 480 } 481 }; 482