static void cpu_pre_save(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; int i; env->spr[SPR_LR] = env->lr; env->spr[SPR_CTR] = env->ctr; env->spr[SPR_XER] = cpu_read_xer(env); #if defined(TARGET_PPC64) env->spr[SPR_CFAR] = env->cfar; #endif env->spr[SPR_BOOKE_SPEFSCR] = env->spe_fscr; for (i = 0; (i < 4) && (i < env->nb_BATs); i++) { env->spr[SPR_DBAT0U + 2*i] = env->DBAT[0][i]; env->spr[SPR_DBAT0U + 2*i + 1] = env->DBAT[1][i]; env->spr[SPR_IBAT0U + 2*i] = env->IBAT[0][i]; env->spr[SPR_IBAT0U + 2*i + 1] = env->IBAT[1][i]; } for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) { env->spr[SPR_DBAT4U + 2*i] = env->DBAT[0][i+4]; env->spr[SPR_DBAT4U + 2*i + 1] = env->DBAT[1][i+4]; env->spr[SPR_IBAT4U + 2*i] = env->IBAT[0][i+4]; env->spr[SPR_IBAT4U + 2*i + 1] = env->IBAT[1][i+4]; } }
void cpu_save(QEMUFile *f, void *opaque) { CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; uint32_t fpscr; target_ulong xer; for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gpr[i]); #if !defined(TARGET_PPC64) for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gprh[i]); #endif qemu_put_betls(f, &env->lr); qemu_put_betls(f, &env->ctr); for (i = 0; i < 8; i++) qemu_put_be32s(f, &env->crf[i]); xer = cpu_read_xer(env); qemu_put_betls(f, &xer); qemu_put_betls(f, &env->reserve_addr); qemu_put_betls(f, &env->msr); for (i = 0; i < 4; i++) qemu_put_betls(f, &env->tgpr[i]); for (i = 0; i < 32; i++) { union { float64 d; uint64_t l; } u; u.d = env->fpr[i]; qemu_put_be64(f, u.l); } fpscr = env->fpscr; qemu_put_be32s(f, &fpscr); qemu_put_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_put_betls(f, &env->spr[SPR_ASR]); qemu_put_sbe32s(f, &env->slb_nr); #endif qemu_put_betls(f, &env->spr[SPR_SDR1]); for (i = 0; i < 32; i++) qemu_put_betls(f, &env->sr[i]); for (i = 0; i < 2; i++) for (j = 0; j < 8; j++) qemu_put_betls(f, &env->DBAT[i][j]); for (i = 0; i < 2; i++) for (j = 0; j < 8; j++) qemu_put_betls(f, &env->IBAT[i][j]); qemu_put_sbe32s(f, &env->nb_tlb); qemu_put_sbe32s(f, &env->tlb_per_way); qemu_put_sbe32s(f, &env->nb_ways); qemu_put_sbe32s(f, &env->last_way); qemu_put_sbe32s(f, &env->id_tlbs); qemu_put_sbe32s(f, &env->nb_pids); if (env->tlb.tlb6) { // XXX assumes 6xx for (i = 0; i < env->nb_tlb; i++) { qemu_put_betls(f, &env->tlb.tlb6[i].pte0); qemu_put_betls(f, &env->tlb.tlb6[i].pte1); qemu_put_betls(f, &env->tlb.tlb6[i].EPN); } } for (i = 0; i < 4; i++) qemu_put_betls(f, &env->pb[i]); for (i = 0; i < 1024; i++) qemu_put_betls(f, &env->spr[i]); qemu_put_be32s(f, &env->vscr); qemu_put_be64s(f, &env->spe_acc); qemu_put_be32s(f, &env->spe_fscr); qemu_put_betls(f, &env->msr_mask); qemu_put_be32s(f, &env->flags); qemu_put_sbe32s(f, &env->error_code); qemu_put_be32s(f, &env->pending_interrupts); qemu_put_be32s(f, &env->irq_input_state); for (i = 0; i < POWERPC_EXCP_NB; i++) qemu_put_betls(f, &env->excp_vectors[i]); qemu_put_betls(f, &env->excp_prefix); qemu_put_betls(f, &env->hreset_excp_prefix); qemu_put_betls(f, &env->ivor_mask); qemu_put_betls(f, &env->ivpr_mask); qemu_put_betls(f, &env->hreset_vector); qemu_put_betls(f, &env->nip); qemu_put_betls(f, &env->hflags); qemu_put_betls(f, &env->hflags_nmsr); qemu_put_sbe32s(f, &env->mmu_idx); qemu_put_sbe32(f, 0); }
int kvm_arch_put_registers(CPUState *cs, int level) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; struct kvm_regs regs; int ret; int i; ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); if (ret < 0) { return ret; } regs.ctr = env->ctr; regs.lr = env->lr; regs.xer = cpu_read_xer(env); regs.msr = env->msr; regs.pc = env->nip; regs.srr0 = env->spr[SPR_SRR0]; regs.srr1 = env->spr[SPR_SRR1]; regs.sprg0 = env->spr[SPR_SPRG0]; regs.sprg1 = env->spr[SPR_SPRG1]; regs.sprg2 = env->spr[SPR_SPRG2]; regs.sprg3 = env->spr[SPR_SPRG3]; regs.sprg4 = env->spr[SPR_SPRG4]; regs.sprg5 = env->spr[SPR_SPRG5]; regs.sprg6 = env->spr[SPR_SPRG6]; regs.sprg7 = env->spr[SPR_SPRG7]; regs.pid = env->spr[SPR_BOOKE_PID]; for (i = 0;i < 32; i++) regs.gpr[i] = env->gpr[i]; ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); if (ret < 0) return ret; kvm_put_fp(cs); if (env->tlb_dirty) { kvm_sw_tlb_put(cpu); env->tlb_dirty = false; } if (cap_segstate && (level >= KVM_PUT_RESET_STATE)) { struct kvm_sregs sregs; sregs.pvr = env->spr[SPR_PVR]; sregs.u.s.sdr1 = env->spr[SPR_SDR1]; /* Sync SLB */ #ifdef TARGET_PPC64 for (i = 0; i < 64; i++) { sregs.u.s.ppc64.slb[i].slbe = env->slb[i].esid; sregs.u.s.ppc64.slb[i].slbv = env->slb[i].vsid; } #endif /* Sync SRs */ for (i = 0; i < 16; i++) { sregs.u.s.ppc32.sr[i] = env->sr[i]; } /* Sync BATs */ for (i = 0; i < 8; i++) { /* Beware. We have to swap upper and lower bits here */ sregs.u.s.ppc32.dbat[i] = ((uint64_t)env->DBAT[0][i] << 32) | env->DBAT[1][i]; sregs.u.s.ppc32.ibat[i] = ((uint64_t)env->IBAT[0][i] << 32) | env->IBAT[1][i]; } ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs); if (ret) { return ret; } } if (cap_hior && (level >= KVM_PUT_RESET_STATE)) { kvm_put_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR); } if (cap_one_reg) { int i; /* We deliberately ignore errors here, for kernels which have * the ONE_REG calls, but don't support the specific * registers, there's a reasonable chance things will still * work, at least until we try to migrate. */ for (i = 0; i < 1024; i++) { uint64_t id = env->spr_cb[i].one_reg_id; if (id != 0) { kvm_put_one_spr(cs, id, i); } } } return ret; }
static int cpu_pre_save(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; int i; uint64_t insns_compat_mask = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB | PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_FRSQRTES | PPC_FLOAT_STFIWX | PPC_FLOAT_EXT | PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | PPC_64BX | PPC_ALTIVEC | PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD; uint64_t insns_compat_mask2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_TM; env->spr[SPR_LR] = env->lr; env->spr[SPR_CTR] = env->ctr; env->spr[SPR_XER] = cpu_read_xer(env); #if defined(TARGET_PPC64) env->spr[SPR_CFAR] = env->cfar; #endif env->spr[SPR_BOOKE_SPEFSCR] = env->spe_fscr; for (i = 0; (i < 4) && (i < env->nb_BATs); i++) { env->spr[SPR_DBAT0U + 2*i] = env->DBAT[0][i]; env->spr[SPR_DBAT0U + 2*i + 1] = env->DBAT[1][i]; env->spr[SPR_IBAT0U + 2*i] = env->IBAT[0][i]; env->spr[SPR_IBAT0U + 2*i + 1] = env->IBAT[1][i]; } for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) { env->spr[SPR_DBAT4U + 2*i] = env->DBAT[0][i+4]; env->spr[SPR_DBAT4U + 2*i + 1] = env->DBAT[1][i+4]; env->spr[SPR_IBAT4U + 2*i] = env->IBAT[0][i+4]; env->spr[SPR_IBAT4U + 2*i + 1] = env->IBAT[1][i+4]; } /* Hacks for migration compatibility between 2.6, 2.7 & 2.8 */ if (cpu->pre_2_8_migration) { /* Mask out bits that got added to msr_mask since the versions * which stupidly included it in the migration stream. */ target_ulong metamask = 0 #if defined(TARGET_PPC64) | (1ULL << MSR_TS0) | (1ULL << MSR_TS1) #endif ; cpu->mig_msr_mask = env->msr_mask & ~metamask; cpu->mig_insns_flags = env->insns_flags & insns_compat_mask; /* CPU models supported by old machines all have PPC_MEM_TLBIE, * so we set it unconditionally to allow backward migration from * a POWER9 host to a POWER8 host. */ cpu->mig_insns_flags |= PPC_MEM_TLBIE; cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2; cpu->mig_nb_BATs = env->nb_BATs; } if (cpu->pre_3_0_migration) { if (cpu->hash64_opts) { cpu->mig_slb_nr = cpu->hash64_opts->slb_size; } } return 0; }