From nobody Thu Oct 2 03:24:58 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1584441027; cv=none; d=zohomail.com; s=zohoarc; b=HzkeZz8q9vUYmF/v+TiNfXwv+h1dUuDH3CcJOd5ABF1jTD7kT5hbGmf8D1h8e8rWvYSHN9+a/fknZVEqUml/Ca4vkIefeYjcyb6eWrbrTFi14aDhsWAys/xllx5gaHVqX3tghSZcTqzNB4briIsdo77N6/9sQnQSMTL25x7wXBA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1584441027; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=m2bui6kzh4CLuC7zywQZJ0giBrHzPEOCZPl6Fr3S8yI=; b=j7vqQHChCZygTvFfwv+ejWpBYlYKNSRlDbM8zb3yKYX8zyvunBmDcW5i9cj6slWRVnti/UKB3slcMX6tyDG3Qo4JTePP11wXrO1PHNm0Ee2pmLwKBecq0ZxVaCYIjyDpUJJbDaRsy2uVFY4Ojr0yH0QymVcjGdaFkicLSql62cM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1584441027250428.84406883947383; Tue, 17 Mar 2020 03:30:27 -0700 (PDT) Received: from localhost ([::1]:56084 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jE9UP-0004d2-Ek for importer@patchew.org; Tue, 17 Mar 2020 06:30:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46665) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jE96Y-0002SD-27 for qemu-devel@nongnu.org; Tue, 17 Mar 2020 06:05:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jE96U-0008QH-4T for qemu-devel@nongnu.org; Tue, 17 Mar 2020 06:05:45 -0400 Received: from bilbo.ozlabs.org ([2401:3900:2:1::2]:42435 helo=ozlabs.org) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1jE96T-0005nt-GC; Tue, 17 Mar 2020 06:05:42 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 48hTL119HHz9sTT; Tue, 17 Mar 2020 21:04:40 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1584439481; bh=FhepqqVZ6pumuQdjmbFwm45Zhnxo3XugrtWy+4DrEk8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=alYwWJ4qADrfZPoi/IidrztK0XqesGkN/9Jkzs7YPaqrHlFlPtxL+INWdDXM+YbFh 925tG6TsYUebjSGCQMaEvzoOvjuFrYmimvCnSIic2Yb6gvT/VwMTaktVWphpsPaF2d hQpAfoQWbWezw1KpNPQoR9Z8VRzyg/ssvigsUytE= From: David Gibson To: peter.maydell@linaro.org Subject: [PULL 34/45] spapr: Move creation of ibm, dynamic-reconfiguration-memory dt node Date: Tue, 17 Mar 2020 21:04:12 +1100 Message-Id: <20200317100423.622643-35-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317100423.622643-1-david@gibson.dropbear.id.au> References: <20200317100423.622643-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2401:3900:2:1::2 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: lvivier@redhat.com, aik@ozlabs.ru, mdroth@linux.vnet.ibm.com, qemu-devel@nongnu.org, groug@kaod.org, qemu-ppc@nongnu.org, clg@kaod.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Currently this node with information about hotpluggable memory is created from spapr_dt_cas_updates(). But that's just a hangover from when we created it only as a diff to the device tree at CAS time. Now that we fully rebuild the DT as CAS time, it makes more sense to create this along with the rest of the memory information in the device tree. So, move it to spapr_populate_memory(). The patch is huge, but it's nearly all just code motion. Signed-off-by: David Gibson Reviewed-by: Greg Kurz --- hw/ppc/spapr.c | 512 +++++++++++++++++++++++++------------------------ 1 file changed, 257 insertions(+), 255 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 2f9a65b414..5e938833f3 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -341,257 +341,6 @@ static int spapr_populate_memory_node(void *fdt, int = nodeid, hwaddr start, return off; } =20 -static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt) -{ - MachineState *machine =3D MACHINE(spapr); - hwaddr mem_start, node_size; - int i, nb_nodes =3D machine->numa_state->num_nodes; - NodeInfo *nodes =3D machine->numa_state->nodes; - - for (i =3D 0, mem_start =3D 0; i < nb_nodes; ++i) { - if (!nodes[i].node_mem) { - continue; - } - if (mem_start >=3D machine->ram_size) { - node_size =3D 0; - } else { - node_size =3D nodes[i].node_mem; - if (node_size > machine->ram_size - mem_start) { - node_size =3D machine->ram_size - mem_start; - } - } - if (!mem_start) { - /* spapr_machine_init() checks for rma_size <=3D node0_size - * already */ - spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); - mem_start +=3D spapr->rma_size; - node_size -=3D spapr->rma_size; - } - for ( ; node_size; ) { - hwaddr sizetmp =3D pow2floor(node_size); - - /* mem_start !=3D 0 here */ - if (ctzl(mem_start) < ctzl(sizetmp)) { - sizetmp =3D 1ULL << ctzl(mem_start); - } - - spapr_populate_memory_node(fdt, i, mem_start, sizetmp); - node_size -=3D sizetmp; - mem_start +=3D sizetmp; - } - } - - return 0; -} - -static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, - SpaprMachineState *spapr) -{ - MachineState *ms =3D MACHINE(spapr); - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - CPUPPCState *env =3D &cpu->env; - PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cs); - int index =3D spapr_get_vcpu_id(cpu); - uint32_t segs[] =3D {cpu_to_be32(28), cpu_to_be32(40), - 0xffffffff, 0xffffffff}; - uint32_t tbfreq =3D kvm_enabled() ? kvmppc_get_tbfreq() - : SPAPR_TIMEBASE_FREQ; - uint32_t cpufreq =3D kvm_enabled() ? kvmppc_get_clockfreq() : 10000000= 00; - uint32_t page_sizes_prop[64]; - size_t page_sizes_prop_size; - unsigned int smp_threads =3D ms->smp.threads; - uint32_t vcpus_per_socket =3D smp_threads * ms->smp.cores; - uint32_t pft_size_prop[] =3D {0, cpu_to_be32(spapr->htab_shift)}; - int compat_smt =3D MIN(smp_threads, ppc_compat_max_vthreads(cpu)); - SpaprDrc *drc; - int drc_index; - uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; - int i; - - drc =3D spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); - if (drc) { - drc_index =3D spapr_drc_index(drc); - _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)= )); - } - - _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); - _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, "slb-size", cpu->hash64_opts->slb_= size))); - _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->= slb_size))); - _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_cell(fdt, offset, "ibm,purr", 1))); - } - if (env->spr_cb[SPR_SPURR].oea_read) { - _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); - } - - if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { - _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", - segs, sizeof(segs)))); - } - - /* Advertise VSX (vector extensions) if available - * 1 =3D=3D VMX / Altivec available - * 2 =3D=3D VSX available - * - * Only CPUs for which we create core types in spapr_cpu_core.c - * are possible, and all of those have VMX */ - if (spapr_get_cap(spapr, SPAPR_CAP_VSX) !=3D 0) { - _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); - } else { - _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); - } - - /* Advertise DFP (Decimal Floating Point) if available - * 0 / no property =3D=3D no DFP - * 1 =3D=3D DFP available */ - if (spapr_get_cap(spapr, SPAPR_CAP_DFP) !=3D 0) { - _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); - } - - page_sizes_prop_size =3D ppc_create_page_sizes_prop(cpu, page_sizes_pr= op, - sizeof(page_sizes_pr= op)); - if (page_sizes_prop_size) { - _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", - page_sizes_prop, page_sizes_prop_size))); - } - - spapr_populate_pa_features(spapr, cpu, fdt, offset); - - _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", - cs->cpu_index / vcpus_per_socket))); - - _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", - pft_size_prop, sizeof(pft_size_prop)))); - - if (ms->numa_state->num_nodes > 1) { - _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); - } - - _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); - - if (pcc->radix_page_info) { - for (i =3D 0; i < pcc->radix_page_info->count; i++) { - radix_AP_encodings[i] =3D - cpu_to_be32(pcc->radix_page_info->entries[i]); - } - _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", - radix_AP_encodings, - pcc->radix_page_info->count * - sizeof(radix_AP_encodings[0])))); - } - - /* - * We set this property to let the guest know that it can use the large - * decrementer and its width in bits. - */ - if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) !=3D SPAPR_CAP_O= FF) - _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", - pcc->lrg_decr_bits))); -} - -static void spapr_populate_cpus_dt_node(void *fdt, SpaprMachineState *spap= r) -{ - CPUState **rev; - CPUState *cs; - int n_cpus; - int cpus_offset; - char *nodename; - int i; - - cpus_offset =3D fdt_add_subnode(fdt, 0, "cpus"); - _FDT(cpus_offset); - _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); - _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); - - /* - * We walk the CPUs in reverse order to ensure that CPU DT nodes - * created by fdt_add_subnode() end up in the right order in FDT - * for the guest kernel the enumerate the CPUs correctly. - * - * The CPU list cannot be traversed in reverse order, so we need - * to do extra work. - */ - n_cpus =3D 0; - rev =3D NULL; - CPU_FOREACH(cs) { - rev =3D g_renew(CPUState *, rev, n_cpus + 1); - rev[n_cpus++] =3D cs; - } - - for (i =3D n_cpus - 1; i >=3D 0; i--) { - CPUState *cs =3D rev[i]; - PowerPCCPU *cpu =3D POWERPC_CPU(cs); - int index =3D spapr_get_vcpu_id(cpu); - DeviceClass *dc =3D DEVICE_GET_CLASS(cs); - int offset; - - if (!spapr_is_thread0_in_vcore(spapr, cpu)) { - continue; - } - - nodename =3D g_strdup_printf("%s@%x", dc->fw_name, index); - offset =3D fdt_add_subnode(fdt, cpus_offset, nodename); - g_free(nodename); - _FDT(offset); - spapr_populate_cpu_dt(cs, fdt, offset, spapr); - } - - g_free(rev); -} - -static int spapr_rng_populate_dt(void *fdt) -{ - int node; - int ret; - - node =3D qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); - if (node <=3D 0) { - return -1; - } - ret =3D fdt_setprop_string(fdt, node, "device_type", - "ibm,platform-facilities"); - ret |=3D fdt_setprop_cell(fdt, node, "#address-cells", 0x1); - ret |=3D fdt_setprop_cell(fdt, node, "#size-cells", 0x0); - - node =3D fdt_add_subnode(fdt, node, "ibm,random-v1"); - if (node <=3D 0) { - return -1; - } - ret |=3D fdt_setprop_string(fdt, node, "compatible", "ibm,random"); - - return ret ? -1 : 0; -} - static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t = addr) { MemoryDeviceInfoList *info; @@ -877,14 +626,51 @@ static int spapr_populate_drconf_memory(SpaprMachineS= tate *spapr, void *fdt) return ret; } =20 -static int spapr_dt_cas_updates(SpaprMachineState *spapr, void *fdt, - SpaprOptionVector *ov5_updates) +static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt) { + MachineState *machine =3D MACHINE(spapr); SpaprMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(spapr); - int ret =3D 0, offset; + hwaddr mem_start, node_size; + int i, nb_nodes =3D machine->numa_state->num_nodes; + NodeInfo *nodes =3D machine->numa_state->nodes; + + for (i =3D 0, mem_start =3D 0; i < nb_nodes; ++i) { + if (!nodes[i].node_mem) { + continue; + } + if (mem_start >=3D machine->ram_size) { + node_size =3D 0; + } else { + node_size =3D nodes[i].node_mem; + if (node_size > machine->ram_size - mem_start) { + node_size =3D machine->ram_size - mem_start; + } + } + if (!mem_start) { + /* spapr_machine_init() checks for rma_size <=3D node0_size + * already */ + spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); + mem_start +=3D spapr->rma_size; + node_size -=3D spapr->rma_size; + } + for ( ; node_size; ) { + hwaddr sizetmp =3D pow2floor(node_size); + + /* mem_start !=3D 0 here */ + if (ctzl(mem_start) < ctzl(sizetmp)) { + sizetmp =3D 1ULL << ctzl(mem_start); + } + + spapr_populate_memory_node(fdt, i, mem_start, sizetmp); + node_size -=3D sizetmp; + mem_start +=3D sizetmp; + } + } =20 /* Generate ibm,dynamic-reconfiguration-memory node if required */ - if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) { + if (spapr_ovec_test(spapr->ov5_cas, OV5_DRCONF_MEMORY)) { + int ret; + g_assert(smc->dr_lmb_enabled); ret =3D spapr_populate_drconf_memory(spapr, fdt); if (ret) { @@ -892,6 +678,222 @@ static int spapr_dt_cas_updates(SpaprMachineState *sp= apr, void *fdt, } } =20 + return 0; +} + +static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, + SpaprMachineState *spapr) +{ + MachineState *ms =3D MACHINE(spapr); + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + CPUPPCState *env =3D &cpu->env; + PowerPCCPUClass *pcc =3D POWERPC_CPU_GET_CLASS(cs); + int index =3D spapr_get_vcpu_id(cpu); + uint32_t segs[] =3D {cpu_to_be32(28), cpu_to_be32(40), + 0xffffffff, 0xffffffff}; + uint32_t tbfreq =3D kvm_enabled() ? kvmppc_get_tbfreq() + : SPAPR_TIMEBASE_FREQ; + uint32_t cpufreq =3D kvm_enabled() ? kvmppc_get_clockfreq() : 10000000= 00; + uint32_t page_sizes_prop[64]; + size_t page_sizes_prop_size; + unsigned int smp_threads =3D ms->smp.threads; + uint32_t vcpus_per_socket =3D smp_threads * ms->smp.cores; + uint32_t pft_size_prop[] =3D {0, cpu_to_be32(spapr->htab_shift)}; + int compat_smt =3D MIN(smp_threads, ppc_compat_max_vthreads(cpu)); + SpaprDrc *drc; + int drc_index; + uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; + int i; + + drc =3D spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); + if (drc) { + drc_index =3D spapr_drc_index(drc); + _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)= )); + } + + _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); + _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, "slb-size", cpu->hash64_opts->slb_= size))); + _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->= slb_size))); + _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_cell(fdt, offset, "ibm,purr", 1))); + } + if (env->spr_cb[SPR_SPURR].oea_read) { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,spurr", 1))); + } + + if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { + _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", + segs, sizeof(segs)))); + } + + /* Advertise VSX (vector extensions) if available + * 1 =3D=3D VMX / Altivec available + * 2 =3D=3D VSX available + * + * Only CPUs for which we create core types in spapr_cpu_core.c + * are possible, and all of those have VMX */ + if (spapr_get_cap(spapr, SPAPR_CAP_VSX) !=3D 0) { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); + } else { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); + } + + /* Advertise DFP (Decimal Floating Point) if available + * 0 / no property =3D=3D no DFP + * 1 =3D=3D DFP available */ + if (spapr_get_cap(spapr, SPAPR_CAP_DFP) !=3D 0) { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); + } + + page_sizes_prop_size =3D ppc_create_page_sizes_prop(cpu, page_sizes_pr= op, + sizeof(page_sizes_pr= op)); + if (page_sizes_prop_size) { + _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", + page_sizes_prop, page_sizes_prop_size))); + } + + spapr_populate_pa_features(spapr, cpu, fdt, offset); + + _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", + cs->cpu_index / vcpus_per_socket))); + + _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", + pft_size_prop, sizeof(pft_size_prop)))); + + if (ms->numa_state->num_nodes > 1) { + _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); + } + + _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); + + if (pcc->radix_page_info) { + for (i =3D 0; i < pcc->radix_page_info->count; i++) { + radix_AP_encodings[i] =3D + cpu_to_be32(pcc->radix_page_info->entries[i]); + } + _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", + radix_AP_encodings, + pcc->radix_page_info->count * + sizeof(radix_AP_encodings[0])))); + } + + /* + * We set this property to let the guest know that it can use the large + * decrementer and its width in bits. + */ + if (spapr_get_cap(spapr, SPAPR_CAP_LARGE_DECREMENTER) !=3D SPAPR_CAP_O= FF) + _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits", + pcc->lrg_decr_bits))); +} + +static void spapr_populate_cpus_dt_node(void *fdt, SpaprMachineState *spap= r) +{ + CPUState **rev; + CPUState *cs; + int n_cpus; + int cpus_offset; + char *nodename; + int i; + + cpus_offset =3D fdt_add_subnode(fdt, 0, "cpus"); + _FDT(cpus_offset); + _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); + _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); + + /* + * We walk the CPUs in reverse order to ensure that CPU DT nodes + * created by fdt_add_subnode() end up in the right order in FDT + * for the guest kernel the enumerate the CPUs correctly. + * + * The CPU list cannot be traversed in reverse order, so we need + * to do extra work. + */ + n_cpus =3D 0; + rev =3D NULL; + CPU_FOREACH(cs) { + rev =3D g_renew(CPUState *, rev, n_cpus + 1); + rev[n_cpus++] =3D cs; + } + + for (i =3D n_cpus - 1; i >=3D 0; i--) { + CPUState *cs =3D rev[i]; + PowerPCCPU *cpu =3D POWERPC_CPU(cs); + int index =3D spapr_get_vcpu_id(cpu); + DeviceClass *dc =3D DEVICE_GET_CLASS(cs); + int offset; + + if (!spapr_is_thread0_in_vcore(spapr, cpu)) { + continue; + } + + nodename =3D g_strdup_printf("%s@%x", dc->fw_name, index); + offset =3D fdt_add_subnode(fdt, cpus_offset, nodename); + g_free(nodename); + _FDT(offset); + spapr_populate_cpu_dt(cs, fdt, offset, spapr); + } + + g_free(rev); +} + +static int spapr_rng_populate_dt(void *fdt) +{ + int node; + int ret; + + node =3D qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); + if (node <=3D 0) { + return -1; + } + ret =3D fdt_setprop_string(fdt, node, "device_type", + "ibm,platform-facilities"); + ret |=3D fdt_setprop_cell(fdt, node, "#address-cells", 0x1); + ret |=3D fdt_setprop_cell(fdt, node, "#size-cells", 0x0); + + node =3D fdt_add_subnode(fdt, node, "ibm,random-v1"); + if (node <=3D 0) { + return -1; + } + ret |=3D fdt_setprop_string(fdt, node, "compatible", "ibm,random"); + + return ret ? -1 : 0; +} + +static int spapr_dt_cas_updates(SpaprMachineState *spapr, void *fdt, + SpaprOptionVector *ov5_updates) +{ + int offset; + offset =3D fdt_path_offset(fdt, "/chosen"); if (offset < 0) { offset =3D fdt_add_subnode(fdt, 0, "chosen"); --=20 2.24.1