Beispiel #1
0
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);
    }
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
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;
}