10d75590dSPeter Maydell #include "qemu/osdep.h" 233c11879SPaolo Bonzini #include "cpu.h" 363c91552SPaolo Bonzini #include "exec/exec-all.h" 49c17d615SPaolo Bonzini #include "sysemu/kvm.h" 5a90db158SAlexey Kardashevskiy #include "helper_regs.h" 6cd6a9bb6SDavid Gibson #include "mmu-hash64.h" 71e00b8d5SPaolo Bonzini #include "migration/cpu.h" 8d5fc133eSDavid Gibson #include "qapi/error.h" 9db725815SMarkus Armbruster #include "qemu/main-loop.h" 10c363a37aSDaniel Henrique Barboza #include "kvm_ppc.h" 11596fff20SRichard Henderson #include "exec/helper-proto.h" 128dd3dca3Saurel32 13*edece45dSRichard Henderson static void post_load_update_msr(CPUPPCState *env) 14*edece45dSRichard Henderson { 15*edece45dSRichard Henderson target_ulong msr = env->msr; 16*edece45dSRichard Henderson 17*edece45dSRichard Henderson /* 18*edece45dSRichard Henderson * Invalidate all supported msr bits except MSR_TGPR/MSR_HVB 19*edece45dSRichard Henderson * before restoring. Note that this recomputes hflags and mem_idx. 20*edece45dSRichard Henderson */ 21*edece45dSRichard Henderson env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB); 22*edece45dSRichard Henderson ppc_store_msr(env, msr); 23*edece45dSRichard Henderson } 24*edece45dSRichard Henderson 25a90db158SAlexey Kardashevskiy static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) 268dd3dca3Saurel32 { 27a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 28a90db158SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 29a456d59cSblueswir1 unsigned int i, j; 30bb593904SDavid Gibson target_ulong sdr1; 31596fff20SRichard Henderson uint32_t fpscr, vscr; 3267d7d66fSDavid Gibson #if defined(TARGET_PPC64) 3367d7d66fSDavid Gibson int32_t slb_nr; 3467d7d66fSDavid Gibson #endif 35da91a00fSRichard Henderson target_ulong xer; 36a456d59cSblueswir1 376f7a6993SDavid Gibson for (i = 0; i < 32; i++) { 38a456d59cSblueswir1 qemu_get_betls(f, &env->gpr[i]); 396f7a6993SDavid Gibson } 40a456d59cSblueswir1 #if !defined(TARGET_PPC64) 416f7a6993SDavid Gibson for (i = 0; i < 32; i++) { 42a456d59cSblueswir1 qemu_get_betls(f, &env->gprh[i]); 436f7a6993SDavid Gibson } 44a456d59cSblueswir1 #endif 45a456d59cSblueswir1 qemu_get_betls(f, &env->lr); 46a456d59cSblueswir1 qemu_get_betls(f, &env->ctr); 476f7a6993SDavid Gibson for (i = 0; i < 8; i++) { 48a456d59cSblueswir1 qemu_get_be32s(f, &env->crf[i]); 496f7a6993SDavid Gibson } 50da91a00fSRichard Henderson qemu_get_betls(f, &xer); 51da91a00fSRichard Henderson cpu_write_xer(env, xer); 5218b21a2fSNathan Froyd qemu_get_betls(f, &env->reserve_addr); 53a456d59cSblueswir1 qemu_get_betls(f, &env->msr); 546f7a6993SDavid Gibson for (i = 0; i < 4; i++) { 55a456d59cSblueswir1 qemu_get_betls(f, &env->tgpr[i]); 566f7a6993SDavid Gibson } 57a456d59cSblueswir1 for (i = 0; i < 32; i++) { 58a456d59cSblueswir1 union { 59a456d59cSblueswir1 float64 d; 60a456d59cSblueswir1 uint64_t l; 61a456d59cSblueswir1 } u; 62a456d59cSblueswir1 u.l = qemu_get_be64(f); 63ef96e3aeSMark Cave-Ayland *cpu_fpr_ptr(env, i) = u.d; 64a456d59cSblueswir1 } 6530304420SDavid Gibson qemu_get_be32s(f, &fpscr); 6630304420SDavid Gibson env->fpscr = fpscr; 67a456d59cSblueswir1 qemu_get_sbe32s(f, &env->access_type); 68a456d59cSblueswir1 #if defined(TARGET_PPC64) 699baea4a3SDavid Gibson qemu_get_betls(f, &env->spr[SPR_ASR]); 7067d7d66fSDavid Gibson qemu_get_sbe32s(f, &slb_nr); 71a456d59cSblueswir1 #endif 72bb593904SDavid Gibson qemu_get_betls(f, &sdr1); 736f7a6993SDavid Gibson for (i = 0; i < 32; i++) { 74a456d59cSblueswir1 qemu_get_betls(f, &env->sr[i]); 756f7a6993SDavid Gibson } 766f7a6993SDavid Gibson for (i = 0; i < 2; i++) { 776f7a6993SDavid Gibson for (j = 0; j < 8; j++) { 78a456d59cSblueswir1 qemu_get_betls(f, &env->DBAT[i][j]); 796f7a6993SDavid Gibson } 806f7a6993SDavid Gibson } 816f7a6993SDavid Gibson for (i = 0; i < 2; i++) { 826f7a6993SDavid Gibson for (j = 0; j < 8; j++) { 83a456d59cSblueswir1 qemu_get_betls(f, &env->IBAT[i][j]); 846f7a6993SDavid Gibson } 856f7a6993SDavid Gibson } 86a456d59cSblueswir1 qemu_get_sbe32s(f, &env->nb_tlb); 87a456d59cSblueswir1 qemu_get_sbe32s(f, &env->tlb_per_way); 88a456d59cSblueswir1 qemu_get_sbe32s(f, &env->nb_ways); 89a456d59cSblueswir1 qemu_get_sbe32s(f, &env->last_way); 90a456d59cSblueswir1 qemu_get_sbe32s(f, &env->id_tlbs); 91a456d59cSblueswir1 qemu_get_sbe32s(f, &env->nb_pids); 921c53acccSAlexander Graf if (env->tlb.tlb6) { 936f7a6993SDavid Gibson /* XXX assumes 6xx */ 94a456d59cSblueswir1 for (i = 0; i < env->nb_tlb; i++) { 951c53acccSAlexander Graf qemu_get_betls(f, &env->tlb.tlb6[i].pte0); 961c53acccSAlexander Graf qemu_get_betls(f, &env->tlb.tlb6[i].pte1); 971c53acccSAlexander Graf qemu_get_betls(f, &env->tlb.tlb6[i].EPN); 98a456d59cSblueswir1 } 99a456d59cSblueswir1 } 1006f7a6993SDavid Gibson for (i = 0; i < 4; i++) { 101a456d59cSblueswir1 qemu_get_betls(f, &env->pb[i]); 1026f7a6993SDavid Gibson } 1036f7a6993SDavid Gibson for (i = 0; i < 1024; i++) { 104a456d59cSblueswir1 qemu_get_betls(f, &env->spr[i]); 1056f7a6993SDavid Gibson } 106e57ca75cSDavid Gibson if (!cpu->vhyp) { 107bb593904SDavid Gibson ppc_store_sdr1(env, sdr1); 108f3c75d42SAneesh Kumar K.V } 109596fff20SRichard Henderson qemu_get_be32s(f, &vscr); 110596fff20SRichard Henderson helper_mtvscr(env, vscr); 111a456d59cSblueswir1 qemu_get_be64s(f, &env->spe_acc); 112a456d59cSblueswir1 qemu_get_be32s(f, &env->spe_fscr); 113a456d59cSblueswir1 qemu_get_betls(f, &env->msr_mask); 114a456d59cSblueswir1 qemu_get_be32s(f, &env->flags); 115a456d59cSblueswir1 qemu_get_sbe32s(f, &env->error_code); 116a456d59cSblueswir1 qemu_get_be32s(f, &env->pending_interrupts); 117a456d59cSblueswir1 qemu_get_be32s(f, &env->irq_input_state); 1186f7a6993SDavid Gibson for (i = 0; i < POWERPC_EXCP_NB; i++) { 119a456d59cSblueswir1 qemu_get_betls(f, &env->excp_vectors[i]); 1206f7a6993SDavid Gibson } 121a456d59cSblueswir1 qemu_get_betls(f, &env->excp_prefix); 122a456d59cSblueswir1 qemu_get_betls(f, &env->ivor_mask); 123a456d59cSblueswir1 qemu_get_betls(f, &env->ivpr_mask); 124a456d59cSblueswir1 qemu_get_betls(f, &env->hreset_vector); 125a456d59cSblueswir1 qemu_get_betls(f, &env->nip); 126dafe299cSRichard Henderson qemu_get_sbetl(f); /* Discard unused hflags */ 127dafe299cSRichard Henderson qemu_get_sbetl(f); /* Discard unused hflags_nmsr */ 1289fb04491SBenjamin Herrenschmidt qemu_get_sbe32(f); /* Discard unused mmu_idx */ 129011aba24SDavid Gibson qemu_get_sbe32(f); /* Discard unused power_mode */ 130a456d59cSblueswir1 131*edece45dSRichard Henderson post_load_update_msr(env); 132dafe299cSRichard Henderson 1338dd3dca3Saurel32 return 0; 1348dd3dca3Saurel32 } 135a90db158SAlexey Kardashevskiy 13603fee66fSMarc-André Lureau static int get_avr(QEMUFile *f, void *pv, size_t size, 13703fee66fSMarc-André Lureau const VMStateField *field) 138a90db158SAlexey Kardashevskiy { 139a90db158SAlexey Kardashevskiy ppc_avr_t *v = pv; 140a90db158SAlexey Kardashevskiy 141a90db158SAlexey Kardashevskiy v->u64[0] = qemu_get_be64(f); 142a90db158SAlexey Kardashevskiy v->u64[1] = qemu_get_be64(f); 143a90db158SAlexey Kardashevskiy 144a90db158SAlexey Kardashevskiy return 0; 145a90db158SAlexey Kardashevskiy } 146a90db158SAlexey Kardashevskiy 14703fee66fSMarc-André Lureau static int put_avr(QEMUFile *f, void *pv, size_t size, 1483ddba9a9SMarkus Armbruster const VMStateField *field, JSONWriter *vmdesc) 149a90db158SAlexey Kardashevskiy { 150a90db158SAlexey Kardashevskiy ppc_avr_t *v = pv; 151a90db158SAlexey Kardashevskiy 152a90db158SAlexey Kardashevskiy qemu_put_be64(f, v->u64[0]); 153a90db158SAlexey Kardashevskiy qemu_put_be64(f, v->u64[1]); 1542c21ee76SJianjun Duan return 0; 155a90db158SAlexey Kardashevskiy } 156a90db158SAlexey Kardashevskiy 157cfd54a04SStefan Weil static const VMStateInfo vmstate_info_avr = { 158a90db158SAlexey Kardashevskiy .name = "avr", 159a90db158SAlexey Kardashevskiy .get = get_avr, 160a90db158SAlexey Kardashevskiy .put = put_avr, 161a90db158SAlexey Kardashevskiy }; 162a90db158SAlexey Kardashevskiy 163a90db158SAlexey Kardashevskiy #define VMSTATE_AVR_ARRAY_V(_f, _s, _n, _v) \ 164ef96e3aeSMark Cave-Ayland VMSTATE_SUB_ARRAY(_f, _s, 32, _n, _v, vmstate_info_avr, ppc_avr_t) 165a90db158SAlexey Kardashevskiy 166a90db158SAlexey Kardashevskiy #define VMSTATE_AVR_ARRAY(_f, _s, _n) \ 167a90db158SAlexey Kardashevskiy VMSTATE_AVR_ARRAY_V(_f, _s, _n, 0) 168a90db158SAlexey Kardashevskiy 169ef96e3aeSMark Cave-Ayland static int get_fpr(QEMUFile *f, void *pv, size_t size, 170ef96e3aeSMark Cave-Ayland const VMStateField *field) 171ef96e3aeSMark Cave-Ayland { 172ef96e3aeSMark Cave-Ayland ppc_vsr_t *v = pv; 173ef96e3aeSMark Cave-Ayland 1748a14d31bSMark Cave-Ayland v->VsrD(0) = qemu_get_be64(f); 175ef96e3aeSMark Cave-Ayland 176ef96e3aeSMark Cave-Ayland return 0; 177ef96e3aeSMark Cave-Ayland } 178ef96e3aeSMark Cave-Ayland 179ef96e3aeSMark Cave-Ayland static int put_fpr(QEMUFile *f, void *pv, size_t size, 1803ddba9a9SMarkus Armbruster const VMStateField *field, JSONWriter *vmdesc) 181ef96e3aeSMark Cave-Ayland { 182ef96e3aeSMark Cave-Ayland ppc_vsr_t *v = pv; 183ef96e3aeSMark Cave-Ayland 1848a14d31bSMark Cave-Ayland qemu_put_be64(f, v->VsrD(0)); 185ef96e3aeSMark Cave-Ayland return 0; 186ef96e3aeSMark Cave-Ayland } 187ef96e3aeSMark Cave-Ayland 188ef96e3aeSMark Cave-Ayland static const VMStateInfo vmstate_info_fpr = { 189ef96e3aeSMark Cave-Ayland .name = "fpr", 190ef96e3aeSMark Cave-Ayland .get = get_fpr, 191ef96e3aeSMark Cave-Ayland .put = put_fpr, 192ef96e3aeSMark Cave-Ayland }; 193ef96e3aeSMark Cave-Ayland 194ef96e3aeSMark Cave-Ayland #define VMSTATE_FPR_ARRAY_V(_f, _s, _n, _v) \ 195ef96e3aeSMark Cave-Ayland VMSTATE_SUB_ARRAY(_f, _s, 0, _n, _v, vmstate_info_fpr, ppc_vsr_t) 196ef96e3aeSMark Cave-Ayland 197ef96e3aeSMark Cave-Ayland #define VMSTATE_FPR_ARRAY(_f, _s, _n) \ 198ef96e3aeSMark Cave-Ayland VMSTATE_FPR_ARRAY_V(_f, _s, _n, 0) 199ef96e3aeSMark Cave-Ayland 200ef96e3aeSMark Cave-Ayland static int get_vsr(QEMUFile *f, void *pv, size_t size, 201ef96e3aeSMark Cave-Ayland const VMStateField *field) 202ef96e3aeSMark Cave-Ayland { 203ef96e3aeSMark Cave-Ayland ppc_vsr_t *v = pv; 204ef96e3aeSMark Cave-Ayland 2058a14d31bSMark Cave-Ayland v->VsrD(1) = qemu_get_be64(f); 206ef96e3aeSMark Cave-Ayland 207ef96e3aeSMark Cave-Ayland return 0; 208ef96e3aeSMark Cave-Ayland } 209ef96e3aeSMark Cave-Ayland 210ef96e3aeSMark Cave-Ayland static int put_vsr(QEMUFile *f, void *pv, size_t size, 2113ddba9a9SMarkus Armbruster const VMStateField *field, JSONWriter *vmdesc) 212ef96e3aeSMark Cave-Ayland { 213ef96e3aeSMark Cave-Ayland ppc_vsr_t *v = pv; 214ef96e3aeSMark Cave-Ayland 2158a14d31bSMark Cave-Ayland qemu_put_be64(f, v->VsrD(1)); 216ef96e3aeSMark Cave-Ayland return 0; 217ef96e3aeSMark Cave-Ayland } 218ef96e3aeSMark Cave-Ayland 219ef96e3aeSMark Cave-Ayland static const VMStateInfo vmstate_info_vsr = { 220ef96e3aeSMark Cave-Ayland .name = "vsr", 221ef96e3aeSMark Cave-Ayland .get = get_vsr, 222ef96e3aeSMark Cave-Ayland .put = put_vsr, 223ef96e3aeSMark Cave-Ayland }; 224ef96e3aeSMark Cave-Ayland 225ef96e3aeSMark Cave-Ayland #define VMSTATE_VSR_ARRAY_V(_f, _s, _n, _v) \ 226ef96e3aeSMark Cave-Ayland VMSTATE_SUB_ARRAY(_f, _s, 0, _n, _v, vmstate_info_vsr, ppc_vsr_t) 227ef96e3aeSMark Cave-Ayland 228ef96e3aeSMark Cave-Ayland #define VMSTATE_VSR_ARRAY(_f, _s, _n) \ 229ef96e3aeSMark Cave-Ayland VMSTATE_VSR_ARRAY_V(_f, _s, _n, 0) 230ef96e3aeSMark Cave-Ayland 231146c11f1SDavid Gibson static bool cpu_pre_2_8_migration(void *opaque, int version_id) 232146c11f1SDavid Gibson { 233146c11f1SDavid Gibson PowerPCCPU *cpu = opaque; 234146c11f1SDavid Gibson 235146c11f1SDavid Gibson return cpu->pre_2_8_migration; 236146c11f1SDavid Gibson } 237146c11f1SDavid Gibson 23867d7d66fSDavid Gibson #if defined(TARGET_PPC64) 239d8c0c7afSPeter Maydell static bool cpu_pre_3_0_migration(void *opaque, int version_id) 24067d7d66fSDavid Gibson { 24167d7d66fSDavid Gibson PowerPCCPU *cpu = opaque; 24267d7d66fSDavid Gibson 243d8c0c7afSPeter Maydell return cpu->pre_3_0_migration; 24467d7d66fSDavid Gibson } 24567d7d66fSDavid Gibson #endif 24667d7d66fSDavid Gibson 24744b1ff31SDr. David Alan Gilbert static int cpu_pre_save(void *opaque) 248a90db158SAlexey Kardashevskiy { 249a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 250a90db158SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 251a90db158SAlexey Kardashevskiy int i; 25216a2497bSDavid Gibson uint64_t insns_compat_mask = 25316a2497bSDavid Gibson PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB 25416a2497bSDavid Gibson | PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES 25516a2497bSDavid Gibson | PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES 25616a2497bSDavid Gibson | PPC_FLOAT_STFIWX | PPC_FLOAT_EXT 25716a2497bSDavid Gibson | PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ 25816a2497bSDavid Gibson | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC 25916a2497bSDavid Gibson | PPC_64B | PPC_64BX | PPC_ALTIVEC 26016a2497bSDavid Gibson | PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD; 26116a2497bSDavid Gibson uint64_t insns_compat_mask2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX 26216a2497bSDavid Gibson | PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 26316a2497bSDavid Gibson | PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 26416a2497bSDavid Gibson | PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 26516a2497bSDavid Gibson | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 26616a2497bSDavid Gibson | PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_TM; 267a90db158SAlexey Kardashevskiy 268a90db158SAlexey Kardashevskiy env->spr[SPR_LR] = env->lr; 269a90db158SAlexey Kardashevskiy env->spr[SPR_CTR] = env->ctr; 270aa378598SThomas Huth env->spr[SPR_XER] = cpu_read_xer(env); 271a90db158SAlexey Kardashevskiy #if defined(TARGET_PPC64) 272a90db158SAlexey Kardashevskiy env->spr[SPR_CFAR] = env->cfar; 273a90db158SAlexey Kardashevskiy #endif 274a90db158SAlexey Kardashevskiy env->spr[SPR_BOOKE_SPEFSCR] = env->spe_fscr; 275a90db158SAlexey Kardashevskiy 276a90db158SAlexey Kardashevskiy for (i = 0; (i < 4) && (i < env->nb_BATs); i++) { 277a90db158SAlexey Kardashevskiy env->spr[SPR_DBAT0U + 2 * i] = env->DBAT[0][i]; 278a90db158SAlexey Kardashevskiy env->spr[SPR_DBAT0U + 2 * i + 1] = env->DBAT[1][i]; 279a90db158SAlexey Kardashevskiy env->spr[SPR_IBAT0U + 2 * i] = env->IBAT[0][i]; 280a90db158SAlexey Kardashevskiy env->spr[SPR_IBAT0U + 2 * i + 1] = env->IBAT[1][i]; 281a90db158SAlexey Kardashevskiy } 282a90db158SAlexey Kardashevskiy for (i = 0; (i < 4) && ((i + 4) < env->nb_BATs); i++) { 283a90db158SAlexey Kardashevskiy env->spr[SPR_DBAT4U + 2 * i] = env->DBAT[0][i + 4]; 284a90db158SAlexey Kardashevskiy env->spr[SPR_DBAT4U + 2 * i + 1] = env->DBAT[1][i + 4]; 285a90db158SAlexey Kardashevskiy env->spr[SPR_IBAT4U + 2 * i] = env->IBAT[0][i + 4]; 286a90db158SAlexey Kardashevskiy env->spr[SPR_IBAT4U + 2 * i + 1] = env->IBAT[1][i + 4]; 287a90db158SAlexey Kardashevskiy } 28816a2497bSDavid Gibson 28916a2497bSDavid Gibson /* Hacks for migration compatibility between 2.6, 2.7 & 2.8 */ 290146c11f1SDavid Gibson if (cpu->pre_2_8_migration) { 2916f7a6993SDavid Gibson /* 2926f7a6993SDavid Gibson * Mask out bits that got added to msr_mask since the versions 2936f7a6993SDavid Gibson * which stupidly included it in the migration stream. 2946f7a6993SDavid Gibson */ 295efb7db25SDavid Gibson target_ulong metamask = 0 296efb7db25SDavid Gibson #if defined(TARGET_PPC64) 297efb7db25SDavid Gibson | (1ULL << MSR_TS0) 298efb7db25SDavid Gibson | (1ULL << MSR_TS1) 299efb7db25SDavid Gibson #endif 300efb7db25SDavid Gibson ; 301efb7db25SDavid Gibson cpu->mig_msr_mask = env->msr_mask & ~metamask; 30216a2497bSDavid Gibson cpu->mig_insns_flags = env->insns_flags & insns_compat_mask; 3036f7a6993SDavid Gibson /* 3046f7a6993SDavid Gibson * CPU models supported by old machines all have 3056f7a6993SDavid Gibson * PPC_MEM_TLBIE, so we set it unconditionally to allow 3066f7a6993SDavid Gibson * backward migration from a POWER9 host to a POWER8 host. 307bce00964SGreg Kurz */ 308bce00964SGreg Kurz cpu->mig_insns_flags |= PPC_MEM_TLBIE; 30916a2497bSDavid Gibson cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2; 31016a2497bSDavid Gibson cpu->mig_nb_BATs = env->nb_BATs; 311a90db158SAlexey Kardashevskiy } 312d8c0c7afSPeter Maydell if (cpu->pre_3_0_migration) { 31367d7d66fSDavid Gibson if (cpu->hash64_opts) { 31467d7d66fSDavid Gibson cpu->mig_slb_nr = cpu->hash64_opts->slb_size; 31567d7d66fSDavid Gibson } 31667d7d66fSDavid Gibson } 31744b1ff31SDr. David Alan Gilbert 318f7a7b652SRichard Henderson /* Retain migration compatibility for pre 6.0 for 601 machines. */ 319f7a7b652SRichard Henderson env->hflags_compat_nmsr = (env->flags & POWERPC_FLAG_HID0_LE 320f7a7b652SRichard Henderson ? env->hflags & MSR_LE : 0); 321f7a7b652SRichard Henderson 32244b1ff31SDr. David Alan Gilbert return 0; 323146c11f1SDavid Gibson } 324a90db158SAlexey Kardashevskiy 325d5fc133eSDavid Gibson /* 326d5fc133eSDavid Gibson * Determine if a given PVR is a "close enough" match to the CPU 327d5fc133eSDavid Gibson * object. For TCG and KVM PR it would probably be sufficient to 328d5fc133eSDavid Gibson * require an exact PVR match. However for KVM HV the user is 329d5fc133eSDavid Gibson * restricted to a PVR exactly matching the host CPU. The correct way 330d5fc133eSDavid Gibson * to handle this is to put the guest into an architected 331d5fc133eSDavid Gibson * compatibility mode. However, to allow a more forgiving transition 332d5fc133eSDavid Gibson * and migration from before this was widely done, we allow migration 333d5fc133eSDavid Gibson * between sufficiently similar PVRs, as determined by the CPU class's 334d5fc133eSDavid Gibson * pvr_match() hook. 335d5fc133eSDavid Gibson */ 336d5fc133eSDavid Gibson static bool pvr_match(PowerPCCPU *cpu, uint32_t pvr) 337d5fc133eSDavid Gibson { 338d5fc133eSDavid Gibson PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); 339d5fc133eSDavid Gibson 340d5fc133eSDavid Gibson if (pvr == pcc->pvr) { 341d5fc133eSDavid Gibson return true; 342d5fc133eSDavid Gibson } 343d5fc133eSDavid Gibson return pcc->pvr_match(pcc, pvr); 344d5fc133eSDavid Gibson } 345d5fc133eSDavid Gibson 346a90db158SAlexey Kardashevskiy static int cpu_post_load(void *opaque, int version_id) 347a90db158SAlexey Kardashevskiy { 348a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 349a90db158SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 350a90db158SAlexey Kardashevskiy int i; 351a90db158SAlexey Kardashevskiy 352569be9f0SAlexey Kardashevskiy /* 353d5fc133eSDavid Gibson * If we're operating in compat mode, we should be ok as long as 354136fbf65Szhaolichang * the destination supports the same compatibility mode. 355d5fc133eSDavid Gibson * 356d5fc133eSDavid Gibson * Otherwise, however, we require that the destination has exactly 357d5fc133eSDavid Gibson * the same CPU model as the source. 358569be9f0SAlexey Kardashevskiy */ 359d5fc133eSDavid Gibson 360d5fc133eSDavid Gibson #if defined(TARGET_PPC64) 361d5fc133eSDavid Gibson if (cpu->compat_pvr) { 362e07cc192SSuraj Jitindar Singh uint32_t compat_pvr = cpu->compat_pvr; 363d5fc133eSDavid Gibson Error *local_err = NULL; 364899134ebSGreg Kurz int ret; 365d5fc133eSDavid Gibson 366e07cc192SSuraj Jitindar Singh cpu->compat_pvr = 0; 367899134ebSGreg Kurz ret = ppc_set_compat(cpu, compat_pvr, &local_err); 368899134ebSGreg Kurz if (ret < 0) { 369d5fc133eSDavid Gibson error_report_err(local_err); 370899134ebSGreg Kurz return ret; 371d5fc133eSDavid Gibson } 372d5fc133eSDavid Gibson } else 373d5fc133eSDavid Gibson #endif 374d5fc133eSDavid Gibson { 375d5fc133eSDavid Gibson if (!pvr_match(cpu, env->spr[SPR_PVR])) { 376899134ebSGreg Kurz return -EINVAL; 377d5fc133eSDavid Gibson } 378d5fc133eSDavid Gibson } 379d5fc133eSDavid Gibson 380c363a37aSDaniel Henrique Barboza /* 381c363a37aSDaniel Henrique Barboza * If we're running with KVM HV, there is a chance that the guest 382c363a37aSDaniel Henrique Barboza * is running with KVM HV and its kernel does not have the 383c363a37aSDaniel Henrique Barboza * capability of dealing with a different PVR other than this 384c363a37aSDaniel Henrique Barboza * exact host PVR in KVM_SET_SREGS. If that happens, the 385c363a37aSDaniel Henrique Barboza * guest freezes after migration. 386c363a37aSDaniel Henrique Barboza * 387c363a37aSDaniel Henrique Barboza * The function kvmppc_pvr_workaround_required does this verification 388c363a37aSDaniel Henrique Barboza * by first checking if the kernel has the cap, returning true immediately 389c363a37aSDaniel Henrique Barboza * if that is the case. Otherwise, it checks if we're running in KVM PR. 390c363a37aSDaniel Henrique Barboza * If the guest kernel does not have the cap and we're not running KVM-PR 391c363a37aSDaniel Henrique Barboza * (so, it is running KVM-HV), we need to ensure that KVM_SET_SREGS will 392c363a37aSDaniel Henrique Barboza * receive the PVR it expects as a workaround. 393c363a37aSDaniel Henrique Barboza * 394c363a37aSDaniel Henrique Barboza */ 395c363a37aSDaniel Henrique Barboza if (kvmppc_pvr_workaround_required(cpu)) { 396c363a37aSDaniel Henrique Barboza env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value; 397c363a37aSDaniel Henrique Barboza } 398c363a37aSDaniel Henrique Barboza 399a90db158SAlexey Kardashevskiy env->lr = env->spr[SPR_LR]; 400a90db158SAlexey Kardashevskiy env->ctr = env->spr[SPR_CTR]; 4016a9620e6SMark Cave-Ayland cpu_write_xer(env, env->spr[SPR_XER]); 402a90db158SAlexey Kardashevskiy #if defined(TARGET_PPC64) 403a90db158SAlexey Kardashevskiy env->cfar = env->spr[SPR_CFAR]; 404a90db158SAlexey Kardashevskiy #endif 405a90db158SAlexey Kardashevskiy env->spe_fscr = env->spr[SPR_BOOKE_SPEFSCR]; 406a90db158SAlexey Kardashevskiy 407a90db158SAlexey Kardashevskiy for (i = 0; (i < 4) && (i < env->nb_BATs); i++) { 408a90db158SAlexey Kardashevskiy env->DBAT[0][i] = env->spr[SPR_DBAT0U + 2 * i]; 409a90db158SAlexey Kardashevskiy env->DBAT[1][i] = env->spr[SPR_DBAT0U + 2 * i + 1]; 410a90db158SAlexey Kardashevskiy env->IBAT[0][i] = env->spr[SPR_IBAT0U + 2 * i]; 411a90db158SAlexey Kardashevskiy env->IBAT[1][i] = env->spr[SPR_IBAT0U + 2 * i + 1]; 412a90db158SAlexey Kardashevskiy } 413a90db158SAlexey Kardashevskiy for (i = 0; (i < 4) && ((i + 4) < env->nb_BATs); i++) { 414a90db158SAlexey Kardashevskiy env->DBAT[0][i + 4] = env->spr[SPR_DBAT4U + 2 * i]; 415a90db158SAlexey Kardashevskiy env->DBAT[1][i + 4] = env->spr[SPR_DBAT4U + 2 * i + 1]; 416a90db158SAlexey Kardashevskiy env->IBAT[0][i + 4] = env->spr[SPR_IBAT4U + 2 * i]; 417a90db158SAlexey Kardashevskiy env->IBAT[1][i + 4] = env->spr[SPR_IBAT4U + 2 * i + 1]; 418a90db158SAlexey Kardashevskiy } 419a90db158SAlexey Kardashevskiy 420e57ca75cSDavid Gibson if (!cpu->vhyp) { 421a90db158SAlexey Kardashevskiy ppc_store_sdr1(env, env->spr[SPR_SDR1]); 422f3c75d42SAneesh Kumar K.V } 4232360b6e8SMark Cave-Ayland 424*edece45dSRichard Henderson post_load_update_msr(env); 4252360b6e8SMark Cave-Ayland 426a90db158SAlexey Kardashevskiy return 0; 427a90db158SAlexey Kardashevskiy } 428a90db158SAlexey Kardashevskiy 429a90db158SAlexey Kardashevskiy static bool fpu_needed(void *opaque) 430a90db158SAlexey Kardashevskiy { 431a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 432a90db158SAlexey Kardashevskiy 4336f7a6993SDavid Gibson return cpu->env.insns_flags & PPC_FLOAT; 434a90db158SAlexey Kardashevskiy } 435a90db158SAlexey Kardashevskiy 436a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_fpu = { 437a90db158SAlexey Kardashevskiy .name = "cpu/fpu", 438a90db158SAlexey Kardashevskiy .version_id = 1, 439a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 4405cd8cadaSJuan Quintela .needed = fpu_needed, 441a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 442ef96e3aeSMark Cave-Ayland VMSTATE_FPR_ARRAY(env.vsr, PowerPCCPU, 32), 443a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(env.fpscr, PowerPCCPU), 444a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 445a90db158SAlexey Kardashevskiy }, 446a90db158SAlexey Kardashevskiy }; 447a90db158SAlexey Kardashevskiy 448a90db158SAlexey Kardashevskiy static bool altivec_needed(void *opaque) 449a90db158SAlexey Kardashevskiy { 450a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 451a90db158SAlexey Kardashevskiy 4526f7a6993SDavid Gibson return cpu->env.insns_flags & PPC_ALTIVEC; 453a90db158SAlexey Kardashevskiy } 454a90db158SAlexey Kardashevskiy 455596fff20SRichard Henderson static int get_vscr(QEMUFile *f, void *opaque, size_t size, 456596fff20SRichard Henderson const VMStateField *field) 457596fff20SRichard Henderson { 458596fff20SRichard Henderson PowerPCCPU *cpu = opaque; 459596fff20SRichard Henderson helper_mtvscr(&cpu->env, qemu_get_be32(f)); 460596fff20SRichard Henderson return 0; 461596fff20SRichard Henderson } 462596fff20SRichard Henderson 463596fff20SRichard Henderson static int put_vscr(QEMUFile *f, void *opaque, size_t size, 4643ddba9a9SMarkus Armbruster const VMStateField *field, JSONWriter *vmdesc) 465596fff20SRichard Henderson { 466596fff20SRichard Henderson PowerPCCPU *cpu = opaque; 467596fff20SRichard Henderson qemu_put_be32(f, helper_mfvscr(&cpu->env)); 468596fff20SRichard Henderson return 0; 469596fff20SRichard Henderson } 470596fff20SRichard Henderson 471596fff20SRichard Henderson static const VMStateInfo vmstate_vscr = { 472596fff20SRichard Henderson .name = "cpu/altivec/vscr", 473596fff20SRichard Henderson .get = get_vscr, 474596fff20SRichard Henderson .put = put_vscr, 475596fff20SRichard Henderson }; 476596fff20SRichard Henderson 477a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_altivec = { 478a90db158SAlexey Kardashevskiy .name = "cpu/altivec", 479a90db158SAlexey Kardashevskiy .version_id = 1, 480a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 4815cd8cadaSJuan Quintela .needed = altivec_needed, 482a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 483ef96e3aeSMark Cave-Ayland VMSTATE_AVR_ARRAY(env.vsr, PowerPCCPU, 32), 484596fff20SRichard Henderson /* 485596fff20SRichard Henderson * Save the architecture value of the vscr, not the internally 486596fff20SRichard Henderson * expanded version. Since this architecture value does not 487596fff20SRichard Henderson * exist in memory to be stored, this requires a but of hoop 488596fff20SRichard Henderson * jumping. We want OFFSET=0 so that we effectively pass CPU 489596fff20SRichard Henderson * to the helper functions. 490596fff20SRichard Henderson */ 491596fff20SRichard Henderson { 492596fff20SRichard Henderson .name = "vscr", 493596fff20SRichard Henderson .version_id = 0, 494596fff20SRichard Henderson .size = sizeof(uint32_t), 495596fff20SRichard Henderson .info = &vmstate_vscr, 496596fff20SRichard Henderson .flags = VMS_SINGLE, 497596fff20SRichard Henderson .offset = 0 498596fff20SRichard Henderson }, 499a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 500a90db158SAlexey Kardashevskiy }, 501a90db158SAlexey Kardashevskiy }; 502a90db158SAlexey Kardashevskiy 503a90db158SAlexey Kardashevskiy static bool vsx_needed(void *opaque) 504a90db158SAlexey Kardashevskiy { 505a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 506a90db158SAlexey Kardashevskiy 5076f7a6993SDavid Gibson return cpu->env.insns_flags2 & PPC2_VSX; 508a90db158SAlexey Kardashevskiy } 509a90db158SAlexey Kardashevskiy 510a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_vsx = { 511a90db158SAlexey Kardashevskiy .name = "cpu/vsx", 512a90db158SAlexey Kardashevskiy .version_id = 1, 513a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 5145cd8cadaSJuan Quintela .needed = vsx_needed, 515a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 516ef96e3aeSMark Cave-Ayland VMSTATE_VSR_ARRAY(env.vsr, PowerPCCPU, 32), 517a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 518a90db158SAlexey Kardashevskiy }, 519a90db158SAlexey Kardashevskiy }; 520a90db158SAlexey Kardashevskiy 52180b3f79bSAlexey Kardashevskiy #ifdef TARGET_PPC64 52280b3f79bSAlexey Kardashevskiy /* Transactional memory state */ 52380b3f79bSAlexey Kardashevskiy static bool tm_needed(void *opaque) 52480b3f79bSAlexey Kardashevskiy { 52580b3f79bSAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 52680b3f79bSAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 52780b3f79bSAlexey Kardashevskiy return msr_ts; 52880b3f79bSAlexey Kardashevskiy } 52980b3f79bSAlexey Kardashevskiy 53080b3f79bSAlexey Kardashevskiy static const VMStateDescription vmstate_tm = { 53180b3f79bSAlexey Kardashevskiy .name = "cpu/tm", 53280b3f79bSAlexey Kardashevskiy .version_id = 1, 53380b3f79bSAlexey Kardashevskiy .minimum_version_id = 1, 53480b3f79bSAlexey Kardashevskiy .minimum_version_id_old = 1, 5355cd8cadaSJuan Quintela .needed = tm_needed, 53680b3f79bSAlexey Kardashevskiy .fields = (VMStateField []) { 53780b3f79bSAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.tm_gpr, PowerPCCPU, 32), 53880b3f79bSAlexey Kardashevskiy VMSTATE_AVR_ARRAY(env.tm_vsr, PowerPCCPU, 64), 53980b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_cr, PowerPCCPU), 54080b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_lr, PowerPCCPU), 54180b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_ctr, PowerPCCPU), 54280b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_fpscr, PowerPCCPU), 54380b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_amr, PowerPCCPU), 54480b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_ppr, PowerPCCPU), 54580b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_vrsave, PowerPCCPU), 54680b3f79bSAlexey Kardashevskiy VMSTATE_UINT32(env.tm_vscr, PowerPCCPU), 54780b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_dscr, PowerPCCPU), 54880b3f79bSAlexey Kardashevskiy VMSTATE_UINT64(env.tm_tar, PowerPCCPU), 54980b3f79bSAlexey Kardashevskiy VMSTATE_END_OF_LIST() 55080b3f79bSAlexey Kardashevskiy }, 55180b3f79bSAlexey Kardashevskiy }; 55280b3f79bSAlexey Kardashevskiy #endif 55380b3f79bSAlexey Kardashevskiy 554a90db158SAlexey Kardashevskiy static bool sr_needed(void *opaque) 555a90db158SAlexey Kardashevskiy { 556a90db158SAlexey Kardashevskiy #ifdef TARGET_PPC64 557a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 558a90db158SAlexey Kardashevskiy 559d57d72a8SGreg Kurz return !mmu_is_64bit(cpu->env.mmu_model); 560a90db158SAlexey Kardashevskiy #else 561a90db158SAlexey Kardashevskiy return true; 562a90db158SAlexey Kardashevskiy #endif 563a90db158SAlexey Kardashevskiy } 564a90db158SAlexey Kardashevskiy 565a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_sr = { 566a90db158SAlexey Kardashevskiy .name = "cpu/sr", 567a90db158SAlexey Kardashevskiy .version_id = 1, 568a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 5695cd8cadaSJuan Quintela .needed = sr_needed, 570a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 571a90db158SAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.sr, PowerPCCPU, 32), 572a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 573a90db158SAlexey Kardashevskiy }, 574a90db158SAlexey Kardashevskiy }; 575a90db158SAlexey Kardashevskiy 576a90db158SAlexey Kardashevskiy #ifdef TARGET_PPC64 57703fee66fSMarc-André Lureau static int get_slbe(QEMUFile *f, void *pv, size_t size, 57803fee66fSMarc-André Lureau const VMStateField *field) 579a90db158SAlexey Kardashevskiy { 580a90db158SAlexey Kardashevskiy ppc_slb_t *v = pv; 581a90db158SAlexey Kardashevskiy 582a90db158SAlexey Kardashevskiy v->esid = qemu_get_be64(f); 583a90db158SAlexey Kardashevskiy v->vsid = qemu_get_be64(f); 584a90db158SAlexey Kardashevskiy 585a90db158SAlexey Kardashevskiy return 0; 586a90db158SAlexey Kardashevskiy } 587a90db158SAlexey Kardashevskiy 58803fee66fSMarc-André Lureau static int put_slbe(QEMUFile *f, void *pv, size_t size, 5893ddba9a9SMarkus Armbruster const VMStateField *field, JSONWriter *vmdesc) 590a90db158SAlexey Kardashevskiy { 591a90db158SAlexey Kardashevskiy ppc_slb_t *v = pv; 592a90db158SAlexey Kardashevskiy 593a90db158SAlexey Kardashevskiy qemu_put_be64(f, v->esid); 594a90db158SAlexey Kardashevskiy qemu_put_be64(f, v->vsid); 5952c21ee76SJianjun Duan return 0; 596a90db158SAlexey Kardashevskiy } 597a90db158SAlexey Kardashevskiy 598cfd54a04SStefan Weil static const VMStateInfo vmstate_info_slbe = { 599a90db158SAlexey Kardashevskiy .name = "slbe", 600a90db158SAlexey Kardashevskiy .get = get_slbe, 601a90db158SAlexey Kardashevskiy .put = put_slbe, 602a90db158SAlexey Kardashevskiy }; 603a90db158SAlexey Kardashevskiy 604a90db158SAlexey Kardashevskiy #define VMSTATE_SLB_ARRAY_V(_f, _s, _n, _v) \ 605a90db158SAlexey Kardashevskiy VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_slbe, ppc_slb_t) 606a90db158SAlexey Kardashevskiy 607a90db158SAlexey Kardashevskiy #define VMSTATE_SLB_ARRAY(_f, _s, _n) \ 608a90db158SAlexey Kardashevskiy VMSTATE_SLB_ARRAY_V(_f, _s, _n, 0) 609a90db158SAlexey Kardashevskiy 610a90db158SAlexey Kardashevskiy static bool slb_needed(void *opaque) 611a90db158SAlexey Kardashevskiy { 612a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 613a90db158SAlexey Kardashevskiy 614a90db158SAlexey Kardashevskiy /* We don't support any of the old segment table based 64-bit CPUs */ 615d57d72a8SGreg Kurz return mmu_is_64bit(cpu->env.mmu_model); 616a90db158SAlexey Kardashevskiy } 617a90db158SAlexey Kardashevskiy 618cd6a9bb6SDavid Gibson static int slb_post_load(void *opaque, int version_id) 619cd6a9bb6SDavid Gibson { 620cd6a9bb6SDavid Gibson PowerPCCPU *cpu = opaque; 621cd6a9bb6SDavid Gibson CPUPPCState *env = &cpu->env; 622cd6a9bb6SDavid Gibson int i; 623cd6a9bb6SDavid Gibson 6246f7a6993SDavid Gibson /* 6256f7a6993SDavid Gibson * We've pulled in the raw esid and vsid values from the migration 6266f7a6993SDavid Gibson * stream, but we need to recompute the page size pointers 6276f7a6993SDavid Gibson */ 62867d7d66fSDavid Gibson for (i = 0; i < cpu->hash64_opts->slb_size; i++) { 629cd6a9bb6SDavid Gibson if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) { 630cd6a9bb6SDavid Gibson /* Migration source had bad values in its SLB */ 631cd6a9bb6SDavid Gibson return -1; 632cd6a9bb6SDavid Gibson } 633cd6a9bb6SDavid Gibson } 634cd6a9bb6SDavid Gibson 635cd6a9bb6SDavid Gibson return 0; 636cd6a9bb6SDavid Gibson } 637cd6a9bb6SDavid Gibson 638a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_slb = { 639a90db158SAlexey Kardashevskiy .name = "cpu/slb", 640a90db158SAlexey Kardashevskiy .version_id = 1, 641a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 6425cd8cadaSJuan Quintela .needed = slb_needed, 643cd6a9bb6SDavid Gibson .post_load = slb_post_load, 644a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 645d8c0c7afSPeter Maydell VMSTATE_INT32_TEST(mig_slb_nr, PowerPCCPU, cpu_pre_3_0_migration), 646d83af167SAneesh Kumar K.V VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES), 647a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 648a90db158SAlexey Kardashevskiy } 649a90db158SAlexey Kardashevskiy }; 650a90db158SAlexey Kardashevskiy #endif /* TARGET_PPC64 */ 651a90db158SAlexey Kardashevskiy 652a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_tlb6xx_entry = { 653a90db158SAlexey Kardashevskiy .name = "cpu/tlb6xx_entry", 654a90db158SAlexey Kardashevskiy .version_id = 1, 655a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 656a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 657a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(pte0, ppc6xx_tlb_t), 658a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(pte1, ppc6xx_tlb_t), 659a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(EPN, ppc6xx_tlb_t), 660a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 661a90db158SAlexey Kardashevskiy }, 662a90db158SAlexey Kardashevskiy }; 663a90db158SAlexey Kardashevskiy 664a90db158SAlexey Kardashevskiy static bool tlb6xx_needed(void *opaque) 665a90db158SAlexey Kardashevskiy { 666a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 667a90db158SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 668a90db158SAlexey Kardashevskiy 669a90db158SAlexey Kardashevskiy return env->nb_tlb && (env->tlb_type == TLB_6XX); 670a90db158SAlexey Kardashevskiy } 671a90db158SAlexey Kardashevskiy 672a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_tlb6xx = { 673a90db158SAlexey Kardashevskiy .name = "cpu/tlb6xx", 674a90db158SAlexey Kardashevskiy .version_id = 1, 675a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 6765cd8cadaSJuan Quintela .needed = tlb6xx_needed, 677a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 678d2164ad3SHalil Pasic VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU, NULL), 679a90db158SAlexey Kardashevskiy VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlb6, PowerPCCPU, 680a90db158SAlexey Kardashevskiy env.nb_tlb, 681a90db158SAlexey Kardashevskiy vmstate_tlb6xx_entry, 682a90db158SAlexey Kardashevskiy ppc6xx_tlb_t), 683a90db158SAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.tgpr, PowerPCCPU, 4), 684a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 685a90db158SAlexey Kardashevskiy } 686a90db158SAlexey Kardashevskiy }; 687a90db158SAlexey Kardashevskiy 688a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_tlbemb_entry = { 689a90db158SAlexey Kardashevskiy .name = "cpu/tlbemb_entry", 690a90db158SAlexey Kardashevskiy .version_id = 1, 691a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 692a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 693a90db158SAlexey Kardashevskiy VMSTATE_UINT64(RPN, ppcemb_tlb_t), 694a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(EPN, ppcemb_tlb_t), 695a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(PID, ppcemb_tlb_t), 696a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(size, ppcemb_tlb_t), 697a90db158SAlexey Kardashevskiy VMSTATE_UINT32(prot, ppcemb_tlb_t), 698a90db158SAlexey Kardashevskiy VMSTATE_UINT32(attr, ppcemb_tlb_t), 699a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 700a90db158SAlexey Kardashevskiy }, 701a90db158SAlexey Kardashevskiy }; 702a90db158SAlexey Kardashevskiy 703a90db158SAlexey Kardashevskiy static bool tlbemb_needed(void *opaque) 704a90db158SAlexey Kardashevskiy { 705a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 706a90db158SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 707a90db158SAlexey Kardashevskiy 708a90db158SAlexey Kardashevskiy return env->nb_tlb && (env->tlb_type == TLB_EMB); 709a90db158SAlexey Kardashevskiy } 710a90db158SAlexey Kardashevskiy 711a90db158SAlexey Kardashevskiy static bool pbr403_needed(void *opaque) 712a90db158SAlexey Kardashevskiy { 713a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 714a90db158SAlexey Kardashevskiy uint32_t pvr = cpu->env.spr[SPR_PVR]; 715a90db158SAlexey Kardashevskiy 716a90db158SAlexey Kardashevskiy return (pvr & 0xffff0000) == 0x00200000; 717a90db158SAlexey Kardashevskiy } 718a90db158SAlexey Kardashevskiy 719a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_pbr403 = { 720a90db158SAlexey Kardashevskiy .name = "cpu/pbr403", 721a90db158SAlexey Kardashevskiy .version_id = 1, 722a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 7235cd8cadaSJuan Quintela .needed = pbr403_needed, 724a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 725a90db158SAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.pb, PowerPCCPU, 4), 726a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 727a90db158SAlexey Kardashevskiy }, 728a90db158SAlexey Kardashevskiy }; 729a90db158SAlexey Kardashevskiy 730a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_tlbemb = { 731a90db158SAlexey Kardashevskiy .name = "cpu/tlb6xx", 732a90db158SAlexey Kardashevskiy .version_id = 1, 733a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 7345cd8cadaSJuan Quintela .needed = tlbemb_needed, 735a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 736d2164ad3SHalil Pasic VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU, NULL), 737a90db158SAlexey Kardashevskiy VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbe, PowerPCCPU, 738a90db158SAlexey Kardashevskiy env.nb_tlb, 739a90db158SAlexey Kardashevskiy vmstate_tlbemb_entry, 740a90db158SAlexey Kardashevskiy ppcemb_tlb_t), 741a90db158SAlexey Kardashevskiy /* 403 protection registers */ 742a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 743a90db158SAlexey Kardashevskiy }, 7445cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 7455cd8cadaSJuan Quintela &vmstate_pbr403, 7465cd8cadaSJuan Quintela NULL 747a90db158SAlexey Kardashevskiy } 748a90db158SAlexey Kardashevskiy }; 749a90db158SAlexey Kardashevskiy 750a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_tlbmas_entry = { 751a90db158SAlexey Kardashevskiy .name = "cpu/tlbmas_entry", 752a90db158SAlexey Kardashevskiy .version_id = 1, 753a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 754a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 755a90db158SAlexey Kardashevskiy VMSTATE_UINT32(mas8, ppcmas_tlb_t), 756a90db158SAlexey Kardashevskiy VMSTATE_UINT32(mas1, ppcmas_tlb_t), 757a90db158SAlexey Kardashevskiy VMSTATE_UINT64(mas2, ppcmas_tlb_t), 758a90db158SAlexey Kardashevskiy VMSTATE_UINT64(mas7_3, ppcmas_tlb_t), 759a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 760a90db158SAlexey Kardashevskiy }, 761a90db158SAlexey Kardashevskiy }; 762a90db158SAlexey Kardashevskiy 763a90db158SAlexey Kardashevskiy static bool tlbmas_needed(void *opaque) 764a90db158SAlexey Kardashevskiy { 765a90db158SAlexey Kardashevskiy PowerPCCPU *cpu = opaque; 766a90db158SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 767a90db158SAlexey Kardashevskiy 768a90db158SAlexey Kardashevskiy return env->nb_tlb && (env->tlb_type == TLB_MAS); 769a90db158SAlexey Kardashevskiy } 770a90db158SAlexey Kardashevskiy 771a90db158SAlexey Kardashevskiy static const VMStateDescription vmstate_tlbmas = { 772a90db158SAlexey Kardashevskiy .name = "cpu/tlbmas", 773a90db158SAlexey Kardashevskiy .version_id = 1, 774a90db158SAlexey Kardashevskiy .minimum_version_id = 1, 7755cd8cadaSJuan Quintela .needed = tlbmas_needed, 776a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 777d2164ad3SHalil Pasic VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU, NULL), 778a90db158SAlexey Kardashevskiy VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbm, PowerPCCPU, 779a90db158SAlexey Kardashevskiy env.nb_tlb, 780a90db158SAlexey Kardashevskiy vmstate_tlbmas_entry, 781a90db158SAlexey Kardashevskiy ppcmas_tlb_t), 782a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 783a90db158SAlexey Kardashevskiy } 784a90db158SAlexey Kardashevskiy }; 785a90db158SAlexey Kardashevskiy 786d5fc133eSDavid Gibson static bool compat_needed(void *opaque) 787d5fc133eSDavid Gibson { 788d5fc133eSDavid Gibson PowerPCCPU *cpu = opaque; 789d5fc133eSDavid Gibson 790d5fc133eSDavid Gibson assert(!(cpu->compat_pvr && !cpu->vhyp)); 791d5fc133eSDavid Gibson return !cpu->pre_2_10_migration && cpu->compat_pvr != 0; 792d5fc133eSDavid Gibson } 793d5fc133eSDavid Gibson 794d5fc133eSDavid Gibson static const VMStateDescription vmstate_compat = { 795d5fc133eSDavid Gibson .name = "cpu/compat", 796d5fc133eSDavid Gibson .version_id = 1, 797d5fc133eSDavid Gibson .minimum_version_id = 1, 798d5fc133eSDavid Gibson .needed = compat_needed, 799d5fc133eSDavid Gibson .fields = (VMStateField[]) { 800d5fc133eSDavid Gibson VMSTATE_UINT32(compat_pvr, PowerPCCPU), 801d5fc133eSDavid Gibson VMSTATE_END_OF_LIST() 802d5fc133eSDavid Gibson } 803d5fc133eSDavid Gibson }; 804d5fc133eSDavid Gibson 805a90db158SAlexey Kardashevskiy const VMStateDescription vmstate_ppc_cpu = { 806a90db158SAlexey Kardashevskiy .name = "cpu", 807a90db158SAlexey Kardashevskiy .version_id = 5, 808a90db158SAlexey Kardashevskiy .minimum_version_id = 5, 809a90db158SAlexey Kardashevskiy .minimum_version_id_old = 4, 810a90db158SAlexey Kardashevskiy .load_state_old = cpu_load_old, 811a90db158SAlexey Kardashevskiy .pre_save = cpu_pre_save, 812a90db158SAlexey Kardashevskiy .post_load = cpu_post_load, 813a90db158SAlexey Kardashevskiy .fields = (VMStateField[]) { 814569be9f0SAlexey Kardashevskiy VMSTATE_UNUSED(sizeof(target_ulong)), /* was _EQUAL(env.spr[SPR_PVR]) */ 815a90db158SAlexey Kardashevskiy 816a90db158SAlexey Kardashevskiy /* User mode architected state */ 817a90db158SAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.gpr, PowerPCCPU, 32), 818a90db158SAlexey Kardashevskiy #if !defined(TARGET_PPC64) 819a90db158SAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.gprh, PowerPCCPU, 32), 820a90db158SAlexey Kardashevskiy #endif 821a90db158SAlexey Kardashevskiy VMSTATE_UINT32_ARRAY(env.crf, PowerPCCPU, 8), 822a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(env.nip, PowerPCCPU), 823a90db158SAlexey Kardashevskiy 824a90db158SAlexey Kardashevskiy /* SPRs */ 825a90db158SAlexey Kardashevskiy VMSTATE_UINTTL_ARRAY(env.spr, PowerPCCPU, 1024), 826a90db158SAlexey Kardashevskiy VMSTATE_UINT64(env.spe_acc, PowerPCCPU), 827a90db158SAlexey Kardashevskiy 828a90db158SAlexey Kardashevskiy /* Reservation */ 829a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(env.reserve_addr, PowerPCCPU), 830a90db158SAlexey Kardashevskiy 831a90db158SAlexey Kardashevskiy /* Supervisor mode architected state */ 832a90db158SAlexey Kardashevskiy VMSTATE_UINTTL(env.msr, PowerPCCPU), 833a90db158SAlexey Kardashevskiy 834f7a7b652SRichard Henderson /* Backward compatible internal state */ 835f7a7b652SRichard Henderson VMSTATE_UINTTL(env.hflags_compat_nmsr, PowerPCCPU), 836a90db158SAlexey Kardashevskiy 837a90db158SAlexey Kardashevskiy /* Sanity checking */ 838146c11f1SDavid Gibson VMSTATE_UINTTL_TEST(mig_msr_mask, PowerPCCPU, cpu_pre_2_8_migration), 839146c11f1SDavid Gibson VMSTATE_UINT64_TEST(mig_insns_flags, PowerPCCPU, cpu_pre_2_8_migration), 840146c11f1SDavid Gibson VMSTATE_UINT64_TEST(mig_insns_flags2, PowerPCCPU, 841146c11f1SDavid Gibson cpu_pre_2_8_migration), 842146c11f1SDavid Gibson VMSTATE_UINT32_TEST(mig_nb_BATs, PowerPCCPU, cpu_pre_2_8_migration), 843a90db158SAlexey Kardashevskiy VMSTATE_END_OF_LIST() 844a90db158SAlexey Kardashevskiy }, 8455cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 8465cd8cadaSJuan Quintela &vmstate_fpu, 8475cd8cadaSJuan Quintela &vmstate_altivec, 8485cd8cadaSJuan Quintela &vmstate_vsx, 8495cd8cadaSJuan Quintela &vmstate_sr, 850a90db158SAlexey Kardashevskiy #ifdef TARGET_PPC64 8515cd8cadaSJuan Quintela &vmstate_tm, 8525cd8cadaSJuan Quintela &vmstate_slb, 853a90db158SAlexey Kardashevskiy #endif /* TARGET_PPC64 */ 8545cd8cadaSJuan Quintela &vmstate_tlb6xx, 8555cd8cadaSJuan Quintela &vmstate_tlbemb, 8565cd8cadaSJuan Quintela &vmstate_tlbmas, 857d5fc133eSDavid Gibson &vmstate_compat, 8585cd8cadaSJuan Quintela NULL 859a90db158SAlexey Kardashevskiy } 860a90db158SAlexey Kardashevskiy }; 861