Example #1
0
File: pnv.c Project: 8tab/qemu
static void powernv_populate_chip(PnvChip *chip, void *fdt)
{
    PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
    char *typename = pnv_core_typename(pcc->cpu_model);
    size_t typesize = object_type_get_instance_size(typename);
    int i;

    pnv_xscom_populate(chip, fdt, 0);

    /* The default LPC bus of a multichip system is on chip 0. It's
     * recognized by the firmware (skiboot) using a "primary"
     * property.
     */
    if (chip->chip_id == 0x0) {
        int lpc_offset = pnv_chip_lpc_offset(chip, fdt);

        _FDT((fdt_setprop(fdt, lpc_offset, "primary", NULL, 0)));
    }

    for (i = 0; i < chip->nr_cores; i++) {
        PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);

        powernv_create_core_node(chip, pnv_core, fdt);

        /* Interrupt Control Presenters (ICP). One per core. */
        powernv_populate_icp(chip, fdt, pnv_core->pir,
                             CPU_CORE(pnv_core)->nr_threads);
    }

    if (chip->ram_size) {
        powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
                                     chip->ram_size);
    }
    g_free(typename);
}
Example #2
0
static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
{
    SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
    CPUCore *cc = CPU_CORE(dev);
    int i;

    for (i = 0; i < cc->nr_threads; i++) {
        spapr_unrealize_vcpu(sc->threads[i], sc);
    }
    g_free(sc->threads);
}
Example #3
0
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
{
    /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
     * tries to add a sPAPR CPU core to a non-pseries machine.
     */
    SpaprMachineState *spapr =
        (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(),
                                                  TYPE_SPAPR_MACHINE);
    SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
    CPUCore *cc = CPU_CORE(OBJECT(dev));
    Error *local_err = NULL;
    int i, j;

    if (!spapr) {
        error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
        return;
    }

    sc->threads = g_new(PowerPCCPU *, cc->nr_threads);
    for (i = 0; i < cc->nr_threads; i++) {
        sc->threads[i] = spapr_create_vcpu(sc, i, &local_err);
        if (local_err) {
            goto err;
        }
    }

    for (j = 0; j < cc->nr_threads; j++) {
        spapr_realize_vcpu(sc->threads[j], spapr, sc, &local_err);
        if (local_err) {
            goto err_unrealize;
        }
    }
    return;

err_unrealize:
    while (--j >= 0) {
        spapr_unrealize_vcpu(sc->threads[j], sc);
    }
err:
    while (--i >= 0) {
        spapr_delete_vcpu(sc->threads[i], sc);
    }
    g_free(sc->threads);
    error_propagate(errp, local_err);
}
Example #4
0
static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
{
    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
    CPUCore *cc = CPU_CORE(dev);
    int i;

    for (i = 0; i < cc->nr_threads; i++) {
        Object *obj = OBJECT(sc->threads[i]);
        DeviceState *dev = DEVICE(obj);
        CPUState *cs = CPU(dev);
        PowerPCCPU *cpu = POWERPC_CPU(cs);

        spapr_cpu_destroy(cpu);
        object_unparent(cpu->intc);
        cpu_remove_sync(cs);
        object_unparent(obj);
    }
    g_free(sc->threads);
}
Example #5
0
static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
{
    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
    sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
    size_t size = object_type_get_instance_size(scc->cpu_type);
    CPUCore *cc = CPU_CORE(dev);
    int i;

    for (i = 0; i < cc->nr_threads; i++) {
        void *obj = sc->threads + i * size;
        DeviceState *dev = DEVICE(obj);
        CPUState *cs = CPU(dev);
        PowerPCCPU *cpu = POWERPC_CPU(cs);

        spapr_cpu_destroy(cpu);
        object_unparent(cpu->intc);
        cpu_remove_sync(cs);
        object_unparent(obj);
    }
    g_free(sc->threads);
}
Example #6
0
static PowerPCCPU *spapr_create_vcpu(SpaprCpuCore *sc, int i, Error **errp)
{
    SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(sc);
    CPUCore *cc = CPU_CORE(sc);
    Object *obj;
    char *id;
    CPUState *cs;
    PowerPCCPU *cpu;
    Error *local_err = NULL;

    obj = object_new(scc->cpu_type);

    cs = CPU(obj);
    cpu = POWERPC_CPU(obj);
    cs->cpu_index = cc->core_id + i;
    spapr_set_vcpu_id(cpu, cs->cpu_index, &local_err);
    if (local_err) {
        goto err;
    }

    cpu->node_id = sc->node_id;

    id = g_strdup_printf("thread[%d]", i);
    object_property_add_child(OBJECT(sc), id, obj, &local_err);
    g_free(id);
    if (local_err) {
        goto err;
    }

    cpu->machine_data = g_new0(SpaprCpuState, 1);

    object_unref(obj);
    return cpu;

err:
    object_unref(obj);
    error_propagate(errp, local_err);
    return NULL;
}
Example #7
0
File: pnv.c Project: 8tab/qemu
/*
 * The PowerNV cores (and threads) need to use real HW ids and not an
 * incremental index like it has been done on other platforms. This HW
 * id is stored in the CPU PIR, it is used to create cpu nodes in the
 * device tree, used in XSCOM to address cores and in interrupt
 * servers.
 */
static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
{
    CPUState *cs = CPU(DEVICE(pc->threads));
    DeviceClass *dc = DEVICE_GET_CLASS(cs);
    PowerPCCPU *cpu = POWERPC_CPU(cs);
    int smt_threads = CPU_CORE(pc)->nr_threads;
    CPUPPCState *env = &cpu->env;
    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
    uint32_t servers_prop[smt_threads];
    int i;
    uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
                       0xffffffff, 0xffffffff};
    uint32_t tbfreq = PNV_TIMEBASE_FREQ;
    uint32_t cpufreq = 1000000000;
    uint32_t page_sizes_prop[64];
    size_t page_sizes_prop_size;
    const uint8_t pa_features[] = { 24, 0,
                                    0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
                                    0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
                                    0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
    int offset;
    char *nodename;
    int cpus_offset = get_cpus_node(fdt);

    nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
    offset = fdt_add_subnode(fdt, cpus_offset, nodename);
    _FDT(offset);
    g_free(nodename);

    _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));

    _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
    _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
    _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));

    _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
    _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
                            env->dcache_line_size)));
    _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
                            env->dcache_line_size)));
    _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
                            env->icache_line_size)));
    _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
                            env->icache_line_size)));

    if (pcc->l1_dcache_size) {
        _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
                               pcc->l1_dcache_size)));
    } else {
        warn_report("Unknown L1 dcache size for cpu");
    }
    if (pcc->l1_icache_size) {
        _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
                               pcc->l1_icache_size)));
    } else {
        warn_report("Unknown L1 icache size for cpu");
    }

    _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
    _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
    _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr)));
    _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
    _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));

    if (env->spr_cb[SPR_PURR].oea_read) {
        _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
    }

    if (env->mmu_model & POWERPC_MMU_1TSEG) {
        _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
                           segs, sizeof(segs))));
    }

    /* Advertise VMX/VSX (vector extensions) if available
     *   0 / no property == no vector extensions
     *   1               == VMX / Altivec available
     *   2               == VSX available */
    if (env->insns_flags & PPC_ALTIVEC) {
        uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;

        _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
    }

    /* Advertise DFP (Decimal Floating Point) if available
     *   0 / no property == no DFP
     *   1               == DFP available */
    if (env->insns_flags2 & PPC2_DFP) {
        _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
    }

    page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop,
                                                  sizeof(page_sizes_prop));
    if (page_sizes_prop_size) {
        _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
                           page_sizes_prop, page_sizes_prop_size)));
    }

    _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
                       pa_features, sizeof(pa_features))));

    /* Build interrupt servers properties */
    for (i = 0; i < smt_threads; i++) {
        servers_prop[i] = cpu_to_be32(pc->pir + i);
    }
    _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
                       servers_prop, sizeof(servers_prop))));
}
Example #8
0
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
{
    /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
     * tries to add a sPAPR CPU core to a non-pseries machine.
     */
    sPAPRMachineState *spapr =
        (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
                                                  TYPE_SPAPR_MACHINE);
    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
    sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
    CPUCore *cc = CPU_CORE(OBJECT(dev));
    Error *local_err = NULL;
    Object *obj;
    int i, j;

    if (!spapr) {
        error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
        return;
    }

    sc->threads = g_new(PowerPCCPU *, cc->nr_threads);
    for (i = 0; i < cc->nr_threads; i++) {
        char id[32];
        CPUState *cs;
        PowerPCCPU *cpu;

        obj = object_new(scc->cpu_type);

        cs = CPU(obj);
        cpu = sc->threads[i] = POWERPC_CPU(obj);
        cs->cpu_index = cc->core_id + i;
        spapr_set_vcpu_id(cpu, cs->cpu_index, &local_err);
        if (local_err) {
            goto err;
        }


        /* Set NUMA node for the threads belonged to core  */
        cpu->node_id = sc->node_id;

        snprintf(id, sizeof(id), "thread[%d]", i);
        object_property_add_child(OBJECT(sc), id, obj, &local_err);
        if (local_err) {
            goto err;
        }
        object_unref(obj);
    }

    for (j = 0; j < cc->nr_threads; j++) {
        obj = OBJECT(sc->threads[j]);

        spapr_cpu_core_realize_child(obj, spapr, &local_err);
        if (local_err) {
            goto err;
        }
    }
    return;

err:
    while (--i >= 0) {
        obj = OBJECT(sc->threads[i]);
        object_unparent(obj);
    }
    g_free(sc->threads);
    error_propagate(errp, local_err);
}
Example #9
0
static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
{
    /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
     * tries to add a sPAPR CPU core to a non-pseries machine.
     */
    sPAPRMachineState *spapr =
        (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
                                                  TYPE_SPAPR_MACHINE);
    sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
    sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
    CPUCore *cc = CPU_CORE(OBJECT(dev));
    size_t size;
    Error *local_err = NULL;
    void *obj;
    int i, j;

    if (!spapr) {
        error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
        return;
    }

    size = object_type_get_instance_size(scc->cpu_type);
    sc->threads = g_malloc0(size * cc->nr_threads);
    for (i = 0; i < cc->nr_threads; i++) {
        char id[32];
        CPUState *cs;
        PowerPCCPU *cpu;

        obj = sc->threads + i * size;

        object_initialize(obj, size, scc->cpu_type);
        cs = CPU(obj);
        cpu = POWERPC_CPU(cs);
        cs->cpu_index = cc->core_id + i;
        cpu->vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i;
        if (kvm_enabled() && !kvm_vcpu_id_is_valid(cpu->vcpu_id)) {
            error_setg(&local_err, "Can't create CPU with id %d in KVM",
                       cpu->vcpu_id);
            error_append_hint(&local_err, "Adjust the number of cpus to %d "
                              "or try to raise the number of threads per core\n",
                              cpu->vcpu_id * smp_threads / spapr->vsmt);
            goto err;
        }


        /* Set NUMA node for the threads belonged to core  */
        cpu->node_id = sc->node_id;

        snprintf(id, sizeof(id), "thread[%d]", i);
        object_property_add_child(OBJECT(sc), id, obj, &local_err);
        if (local_err) {
            goto err;
        }
        object_unref(obj);
    }

    for (j = 0; j < cc->nr_threads; j++) {
        obj = sc->threads + j * size;

        spapr_cpu_core_realize_child(obj, spapr, &local_err);
        if (local_err) {
            goto err;
        }
    }
    return;

err:
    while (--i >= 0) {
        obj = sc->threads + i * size;
        object_unparent(obj);
    }
    g_free(sc->threads);
    error_propagate(errp, local_err);
}