static void spapr_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); cpu_reset(cs); /* All CPUs start halted. CPU0 is unhalted from the machine level * reset code and the rest are explicitly started up by the guest * using an RTAS call */ cs->halted = 1; env->spr[SPR_HIOR] = 0; /* Disable Power-saving mode Exit Cause exceptions for the CPU. * This can cause issues when rebooting the guest if a secondary * is awaken */ if (cs != first_cpu) { env->spr[SPR_LPCR] &= ~pcc->lpcr_pm; } /* Set compatibility mode to match the boot CPU, which was either set * by the machine reset code or by CAS. This should never fail. */ if (cs != first_cpu) { ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort); } }
static void do_set_compat(CPUState *cs, run_on_cpu_data arg) { PowerPCCPU *cpu = POWERPC_CPU(cs); SetCompatState *s = arg.host_ptr; ppc_set_compat(cpu, s->compat_pvr, &s->err); }
static void spapr_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); target_ulong lpcr; cpu_reset(cs); /* All CPUs start halted. CPU0 is unhalted from the machine level * reset code and the rest are explicitly started up by the guest * using an RTAS call */ cs->halted = 1; /* Set compatibility mode to match the boot CPU, which was either set * by the machine reset code or by CAS. This should never fail. */ ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort); env->spr[SPR_HIOR] = 0; lpcr = env->spr[SPR_LPCR]; /* Set emulated LPCR to not send interrupts to hypervisor. Note that * under KVM, the actual HW LPCR will be set differently by KVM itself, * the settings below ensure proper operations with TCG in absence of * a real hypervisor. * * Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for * real mode accesses, which thankfully defaults to 0 and isn't * accessible in guest mode. * * Disable Power-saving mode Exit Cause exceptions for the CPU, so * we don't get spurious wakups before an RTAS start-cpu call. */ lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm); lpcr |= LPCR_LPES0 | LPCR_LPES1; /* Set RMLS to the max (ie, 16G) */ lpcr &= ~LPCR_RMLS; lpcr |= 1ull << LPCR_RMLS_SHIFT; ppc_store_lpcr(cpu, lpcr); /* Set a full AMOR so guest can use the AMR as it sees fit */ env->spr[SPR_AMOR] = 0xffffffffffffffffull; spapr_cpu->vpa_addr = 0; spapr_cpu->slb_shadow_addr = 0; spapr_cpu->slb_shadow_size = 0; spapr_cpu->dtl_addr = 0; spapr_cpu->dtl_size = 0; spapr_caps_cpu_apply(SPAPR_MACHINE(qdev_get_machine()), cpu); kvm_check_mmu(cpu, &error_fatal); }
static void spapr_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; cpu_reset(cs); /* All CPUs start halted. CPU0 is unhalted from the machine level * reset code and the rest are explicitly started up by the guest * using an RTAS call */ cs->halted = 1; env->spr[SPR_HIOR] = 0; /* Set compatibility mode to match the boot CPU, which was either set * by the machine reset code or by CAS. This should never fail. */ if (cs != first_cpu) { ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort); } }
static int cpu_post_load(void *opaque, int version_id) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; int i; target_ulong msr; /* * If we're operating in compat mode, we should be ok as long as * the destination supports the same compatiblity mode. * * Otherwise, however, we require that the destination has exactly * the same CPU model as the source. */ #if defined(TARGET_PPC64) if (cpu->compat_pvr) { uint32_t compat_pvr = cpu->compat_pvr; Error *local_err = NULL; cpu->compat_pvr = 0; ppc_set_compat(cpu, compat_pvr, &local_err); if (local_err) { error_report_err(local_err); return -1; } } else #endif { if (!pvr_match(cpu, env->spr[SPR_PVR])) { return -1; } } /* * If we're running with KVM HV, there is a chance that the guest * is running with KVM HV and its kernel does not have the * capability of dealing with a different PVR other than this * exact host PVR in KVM_SET_SREGS. If that happens, the * guest freezes after migration. * * The function kvmppc_pvr_workaround_required does this verification * by first checking if the kernel has the cap, returning true immediately * if that is the case. Otherwise, it checks if we're running in KVM PR. * If the guest kernel does not have the cap and we're not running KVM-PR * (so, it is running KVM-HV), we need to ensure that KVM_SET_SREGS will * receive the PVR it expects as a workaround. * */ #if defined(CONFIG_KVM) if (kvmppc_pvr_workaround_required(cpu)) { env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value; } #endif env->lr = env->spr[SPR_LR]; env->ctr = env->spr[SPR_CTR]; cpu_write_xer(env, env->spr[SPR_XER]); #if defined(TARGET_PPC64) env->cfar = env->spr[SPR_CFAR]; #endif env->spe_fscr = env->spr[SPR_BOOKE_SPEFSCR]; for (i = 0; (i < 4) && (i < env->nb_BATs); i++) { env->DBAT[0][i] = env->spr[SPR_DBAT0U + 2*i]; env->DBAT[1][i] = env->spr[SPR_DBAT0U + 2*i + 1]; env->IBAT[0][i] = env->spr[SPR_IBAT0U + 2*i]; env->IBAT[1][i] = env->spr[SPR_IBAT0U + 2*i + 1]; } for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) { env->DBAT[0][i+4] = env->spr[SPR_DBAT4U + 2*i]; env->DBAT[1][i+4] = env->spr[SPR_DBAT4U + 2*i + 1]; env->IBAT[0][i+4] = env->spr[SPR_IBAT4U + 2*i]; env->IBAT[1][i+4] = env->spr[SPR_IBAT4U + 2*i + 1]; } if (!cpu->vhyp) { ppc_store_sdr1(env, env->spr[SPR_SDR1]); } /* Invalidate all supported msr bits except MSR_TGPR/MSR_HVB before restoring */ msr = env->msr; env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB); ppc_store_msr(env, msr); hreg_compute_mem_idx(env); return 0; }