]> Git Repo - qemu.git/blobdiff - hw/ppc/spapr.c
Include hw/qdev-properties.h less
[qemu.git] / hw / ppc / spapr.c
index b6a571b6f184fdfd24ede7fdcddc0e75dbc6585e..fb669c413bebf846eb18a9e2ec60edaa72c70477 100644 (file)
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
- *
  */
+
 #include "qemu/osdep.h"
+#include "qemu-common.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/numa.h"
-#include "hw/hw.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
 #include "qemu/log.h"
 #include "hw/fw-path-provider.h"
 #include "elf.h"
@@ -39,6 +41,7 @@
 #include "sysemu/hw_accel.h"
 #include "kvm_ppc.h"
 #include "migration/misc.h"
+#include "migration/qemu-file-types.h"
 #include "migration/global_state.h"
 #include "migration/register.h"
 #include "mmu-hash64.h"
@@ -53,6 +56,7 @@
 #include "hw/ppc/fdt.h"
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
+#include "hw/qdev-properties.h"
 #include "hw/pci-host/spapr.h"
 #include "hw/pci/msi.h"
 
  * all and one to identify thread 0 of a VCORE. Any change to the first one
  * is likely to have an impact on the second one, so let's keep them close.
  */
-static int spapr_vcpu_id(sPAPRMachineState *spapr, int cpu_index)
+static int spapr_vcpu_id(SpaprMachineState *spapr, int cpu_index)
 {
+    MachineState *ms = MACHINE(spapr);
+    unsigned int smp_threads = ms->smp.threads;
+
     assert(spapr->vsmt);
     return
         (cpu_index / smp_threads) * spapr->vsmt + cpu_index % smp_threads;
 }
-static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr,
+static bool spapr_is_thread0_in_vcore(SpaprMachineState *spapr,
                                       PowerPCCPU *cpu)
 {
     assert(spapr->vsmt);
@@ -149,10 +156,12 @@ static void pre_2_10_vmstate_unregister_dummy_icp(int i)
                        (void *)(uintptr_t) i);
 }
 
-int spapr_max_server_number(sPAPRMachineState *spapr)
+int spapr_max_server_number(SpaprMachineState *spapr)
 {
+    MachineState *ms = MACHINE(spapr);
+
     assert(spapr->vsmt);
-    return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads);
+    return DIV_ROUND_UP(ms->smp.max_cpus * spapr->vsmt, ms->smp.threads);
 }
 
 static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
@@ -204,7 +213,7 @@ static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu)
 }
 
 /* Populate the "ibm,pa-features" property */
-static void spapr_populate_pa_features(sPAPRMachineState *spapr,
+static void spapr_populate_pa_features(SpaprMachineState *spapr,
                                        PowerPCCPU *cpu,
                                        void *fdt, int offset,
                                        bool legacy_guest)
@@ -283,8 +292,9 @@ static void spapr_populate_pa_features(sPAPRMachineState *spapr,
     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
 }
 
-static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
+static int spapr_fixup_cpu_dt(void *fdt, SpaprMachineState *spapr)
 {
+    MachineState *ms = MACHINE(spapr);
     int ret = 0, offset, cpus_offset;
     CPUState *cs;
     char cpu_model[32];
@@ -294,7 +304,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
         PowerPCCPU *cpu = POWERPC_CPU(cs);
         DeviceClass *dc = DEVICE_GET_CLASS(cs);
         int index = spapr_get_vcpu_id(cpu);
-        int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
+        int compat_smt = MIN(ms->smp.threads, ppc_compat_max_vthreads(cpu));
 
         if (!spapr_is_thread0_in_vcore(spapr, cpu)) {
             continue;
@@ -386,7 +396,7 @@ static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
     return off;
 }
 
-static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
+static int spapr_populate_memory(SpaprMachineState *spapr, void *fdt)
 {
     MachineState *machine = MACHINE(spapr);
     hwaddr mem_start, node_size;
@@ -438,8 +448,9 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
 }
 
 static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
-                                  sPAPRMachineState *spapr)
+                                  SpaprMachineState *spapr)
 {
+    MachineState *ms = MACHINE(spapr);
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = &cpu->env;
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
@@ -451,10 +462,11 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
     uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
     uint32_t page_sizes_prop[64];
     size_t page_sizes_prop_size;
-    uint32_t vcpus_per_socket = smp_threads * smp_cores;
+    unsigned int smp_threads = ms->smp.threads;
+    uint32_t vcpus_per_socket = smp_threads * ms->smp.cores;
     uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
     int compat_smt = MIN(smp_threads, ppc_compat_max_vthreads(cpu));
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     int drc_index;
     uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ];
     int i;
@@ -499,7 +511,10 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
     _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)));
+        _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)) {
@@ -557,9 +572,17 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
                           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) != SPAPR_CAP_OFF)
+        _FDT((fdt_setprop_u32(fdt, offset, "ibm,dec-bits",
+                              pcc->lrg_decr_bits)));
 }
 
-static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
+static void spapr_populate_cpus_dt_node(void *fdt, SpaprMachineState *spapr)
 {
     CPUState **rev;
     CPUState *cs;
@@ -683,7 +706,7 @@ spapr_get_drconf_cell(uint32_t seq_lmbs, uint64_t base_addr,
 }
 
 /* ibm,dynamic-memory-v2 */
-static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt,
+static int spapr_populate_drmem_v2(SpaprMachineState *spapr, void *fdt,
                                    int offset, MemoryDeviceInfoList *dimms)
 {
     MachineState *machine = MACHINE(spapr);
@@ -695,7 +718,7 @@ static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt,
     uint64_t mem_end = machine->device_memory->base +
                        memory_region_size(&machine->device_memory->mr);
     uint32_t node, buf_len, nr_entries = 0;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     DrconfCellQueue *elem, *next;
     MemoryDeviceInfoList *info;
     QSIMPLEQ_HEAD(, DrconfCellQueue) drconf_queue
@@ -768,7 +791,7 @@ static int spapr_populate_drmem_v2(sPAPRMachineState *spapr, void *fdt,
 }
 
 /* ibm,dynamic-memory */
-static int spapr_populate_drmem_v1(sPAPRMachineState *spapr, void *fdt,
+static int spapr_populate_drmem_v1(SpaprMachineState *spapr, void *fdt,
                                    int offset, MemoryDeviceInfoList *dimms)
 {
     MachineState *machine = MACHINE(spapr);
@@ -792,7 +815,7 @@ static int spapr_populate_drmem_v1(sPAPRMachineState *spapr, void *fdt,
         uint32_t *dynamic_memory = cur_index;
 
         if (i >= device_lmb_start) {
-            sPAPRDRConnector *drc;
+            SpaprDrc *drc;
 
             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
             g_assert(drc);
@@ -837,7 +860,7 @@ static int spapr_populate_drmem_v1(sPAPRMachineState *spapr, void *fdt,
  * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
  * of this device tree node.
  */
-static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
+static int spapr_populate_drconf_memory(SpaprMachineState *spapr, void *fdt)
 {
     MachineState *machine = MACHINE(spapr);
     int ret, i, offset;
@@ -908,10 +931,10 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
     return ret;
 }
 
-static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt,
-                                sPAPROptionVector *ov5_updates)
+static int spapr_dt_cas_updates(SpaprMachineState *spapr, void *fdt,
+                                SpaprOptionVector *ov5_updates)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     int ret = 0, offset;
 
     /* Generate ibm,dynamic-reconfiguration-memory node if required */
@@ -957,12 +980,12 @@ static bool spapr_hotplugged_dev_before_cas(void)
     return false;
 }
 
-int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
+int spapr_h_cas_compose_response(SpaprMachineState *spapr,
                                  target_ulong addr, target_ulong size,
-                                 sPAPROptionVector *ov5_updates)
+                                 SpaprOptionVector *ov5_updates)
 {
     void *fdt, *fdt_skel;
-    sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
+    SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 };
 
     if (spapr_hotplugged_dev_before_cas()) {
         return 1;
@@ -1011,8 +1034,9 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
     return 0;
 }
 
-static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
+static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
 {
+    MachineState *ms = MACHINE(spapr);
     int rtas;
     GString *hypertas = g_string_sized_new(256);
     GString *qemu_hypertas = g_string_sized_new(256);
@@ -1023,14 +1047,15 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
         cpu_to_be32(max_device_addr >> 32),
         cpu_to_be32(max_device_addr & 0xffffffff),
         0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
-        cpu_to_be32(max_cpus / smp_threads),
+        cpu_to_be32(ms->smp.max_cpus / ms->smp.threads),
     };
+    uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0);
     uint32_t maxdomains[] = {
         cpu_to_be32(4),
-        cpu_to_be32(0),
-        cpu_to_be32(0),
-        cpu_to_be32(0),
-        cpu_to_be32(nb_numa_nodes ? nb_numa_nodes : 1),
+        maxdomain,
+        maxdomain,
+        maxdomain,
+        cpu_to_be32(spapr->gpu_numa_id),
     };
 
     _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
@@ -1100,7 +1125,7 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
  * and the XIVE features that the guest may request and thus the valid
  * values for bytes 23..26 of option vector 5:
  */
-static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void *fdt,
+static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
                                           int chosen)
 {
     PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
@@ -1136,7 +1161,7 @@ static void spapr_dt_ov5_platform_support(sPAPRMachineState *spapr, void *fdt,
                      val, sizeof(val)));
 }
 
-static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
+static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
 {
     MachineState *machine = MACHINE(spapr);
     int chosen;
@@ -1202,7 +1227,7 @@ static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
     g_free(bootlist);
 }
 
-static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt)
+static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
 {
     /* The /hypervisor node isn't in PAPR - this is a hack to allow PR
      * KVM to work under pHyp with some guest co-operation */
@@ -1225,14 +1250,14 @@ static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt)
     }
 }
 
-static void *spapr_build_fdt(sPAPRMachineState *spapr)
+static void *spapr_build_fdt(SpaprMachineState *spapr)
 {
     MachineState *machine = MACHINE(spapr);
     MachineClass *mc = MACHINE_GET_CLASS(machine);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
     int ret;
     void *fdt;
-    sPAPRPHBState *phb;
+    SpaprPhbState *phb;
     char *buf;
 
     fdt = g_malloc0(FDT_MAX_SIZE);
@@ -1243,38 +1268,8 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
     _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)"));
     _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries"));
 
-    /*
-     * Add info to guest to indentify which host is it being run on
-     * and what is the uuid of the guest
-     */
-    if (spapr->host_model && !g_str_equal(spapr->host_model, "none")) {
-        if (g_str_equal(spapr->host_model, "passthrough")) {
-            /* -M host-model=passthrough */
-            if (kvmppc_get_host_model(&buf)) {
-                _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
-                g_free(buf);
-            }
-        } else {
-            /* -M host-model=<user-string> */
-            _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
-        }
-    }
-
-    if (spapr->host_serial && !g_str_equal(spapr->host_serial, "none")) {
-        if (g_str_equal(spapr->host_serial, "passthrough")) {
-            /* -M host-serial=passthrough */
-            if (kvmppc_get_host_serial(&buf)) {
-                _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
-                g_free(buf);
-            }
-        } else {
-            /* -M host-serial=<user-string> */
-            _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
-        }
-    }
-
+    /* Guest UUID & Name*/
     buf = qemu_uuid_unparse_strdup(&qemu_uuid);
-
     _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf));
     if (qemu_uuid_set) {
         _FDT(fdt_setprop_string(fdt, 0, "system-id", buf));
@@ -1286,6 +1281,21 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
                                 qemu_get_vm_name()));
     }
 
+    /* Host Model & Serial Number */
+    if (spapr->host_model) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-model", spapr->host_model));
+    } else if (smc->broken_host_serial_model && kvmppc_get_host_model(&buf)) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
+        g_free(buf);
+    }
+
+    if (spapr->host_serial) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-serial", spapr->host_serial));
+    } else if (smc->broken_host_serial_model && kvmppc_get_host_serial(&buf)) {
+        _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
+        g_free(buf);
+    }
+
     _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2));
     _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
 
@@ -1311,8 +1321,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
     }
 
     QLIST_FOREACH(phb, &spapr->phbs, list) {
-        ret = spapr_populate_pci_dt(phb, PHANDLE_INTC, fdt,
-                                    spapr->irq->nr_msis, NULL);
+        ret = spapr_dt_phb(phb, PHANDLE_INTC, fdt, spapr->irq->nr_msis, NULL);
         if (ret < 0) {
             error_report("couldn't setup PCI devices in fdt");
             exit(1);
@@ -1323,13 +1332,12 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
     spapr_populate_cpus_dt_node(fdt, spapr);
 
     if (smc->dr_lmb_enabled) {
-        _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
+        _FDT(spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
     }
 
     if (mc->has_hotpluggable_cpus) {
         int offset = fdt_path_offset(fdt, "/cpus");
-        ret = spapr_drc_populate_dt(fdt, offset, NULL,
-                                    SPAPR_DR_CONNECTOR_TYPE_CPU);
+        ret = spapr_dt_drc(fdt, offset, NULL, SPAPR_DR_CONNECTOR_TYPE_CPU);
         if (ret < 0) {
             error_report("Couldn't set up CPU DR device tree properties");
             exit(1);
@@ -1366,7 +1374,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr)
     }
 
     if (smc->dr_phb_enabled) {
-        ret = spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB);
+        ret = spapr_dt_drc(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_PHB);
         if (ret < 0) {
             error_report("Couldn't set up PHB DR device tree properties");
             exit(1);
@@ -1430,7 +1438,7 @@ void spapr_set_all_lpcrs(target_ulong value, target_ulong mask)
 
 static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     /* Copy PATE1:GR into PATE0:HR */
     entry->dw0 = spapr->patb_entry & PATE0_HR;
@@ -1446,7 +1454,7 @@ static void spapr_get_pate(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry)
 /*
  * Get the fd to access the kernel htab, re-opening it if necessary
  */
-static int get_htab_fd(sPAPRMachineState *spapr)
+static int get_htab_fd(SpaprMachineState *spapr)
 {
     Error *local_err = NULL;
 
@@ -1462,7 +1470,7 @@ static int get_htab_fd(sPAPRMachineState *spapr)
     return spapr->htab_fd;
 }
 
-void close_htab_fd(sPAPRMachineState *spapr)
+void close_htab_fd(SpaprMachineState *spapr)
 {
     if (spapr->htab_fd >= 0) {
         close(spapr->htab_fd);
@@ -1472,14 +1480,14 @@ void close_htab_fd(sPAPRMachineState *spapr)
 
 static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1;
 }
 
 static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     assert(kvm_enabled());
 
@@ -1493,7 +1501,7 @@ static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp)
 static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp,
                                                 hwaddr ptex, int n)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
     hwaddr pte_offset = ptex * HASH_PTE_SIZE_64;
 
     if (!spapr->htab) {
@@ -1516,7 +1524,7 @@ static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp,
                               const ppc_hash_pte64_t *hptes,
                               hwaddr ptex, int n)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
 
     if (!spapr->htab) {
         g_free((void *)hptes);
@@ -1525,10 +1533,10 @@ static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp,
     /* Nothing to do for qemu managed HPT */
 }
 
-static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex,
-                             uint64_t pte0, uint64_t pte1)
+void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
+                      uint64_t pte0, uint64_t pte1)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);
+    SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp);
     hwaddr offset = ptex * HASH_PTE_SIZE_64;
 
     if (!spapr->htab) {
@@ -1556,6 +1564,38 @@ static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex,
     }
 }
 
+static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
+                             uint64_t pte1)
+{
+    hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15;
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
+
+    if (!spapr->htab) {
+        /* There should always be a hash table when this is called */
+        error_report("spapr_hpte_set_c called with no hash table !");
+        return;
+    }
+
+    /* The HW performs a non-atomic byte update */
+    stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80);
+}
+
+static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex,
+                             uint64_t pte1)
+{
+    hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14;
+    SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
+
+    if (!spapr->htab) {
+        /* There should always be a hash table when this is called */
+        error_report("spapr_hpte_set_r called with no hash table !");
+        return;
+    }
+
+    /* The HW performs a non-atomic byte update */
+    stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01);
+}
+
 int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
 {
     int shift;
@@ -1569,7 +1609,7 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
     return shift;
 }
 
-void spapr_free_hpt(sPAPRMachineState *spapr)
+void spapr_free_hpt(SpaprMachineState *spapr)
 {
     g_free(spapr->htab);
     spapr->htab = NULL;
@@ -1577,7 +1617,7 @@ void spapr_free_hpt(sPAPRMachineState *spapr)
     close_htab_fd(spapr);
 }
 
-void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
+void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift,
                           Error **errp)
 {
     long rc;
@@ -1623,10 +1663,11 @@ void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
         }
     }
     /* We're setting up a hash table, so that means we're not radix */
+    spapr->patb_entry = 0;
     spapr_set_all_lpcrs(0, LPCR_HR | LPCR_UPRT);
 }
 
-void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
+void spapr_setup_hpt_and_vrma(SpaprMachineState *spapr)
 {
     int hpt_shift;
 
@@ -1650,8 +1691,8 @@ void spapr_setup_hpt_and_vrma(sPAPRMachineState *spapr)
 
 static int spapr_reset_drcs(Object *child, void *opaque)
 {
-    sPAPRDRConnector *drc =
-        (sPAPRDRConnector *) object_dynamic_cast(child,
+    SpaprDrc *drc =
+        (SpaprDrc *) object_dynamic_cast(child,
                                                  TYPE_SPAPR_DR_CONNECTOR);
 
     if (drc) {
@@ -1661,10 +1702,9 @@ static int spapr_reset_drcs(Object *child, void *opaque)
     return 0;
 }
 
-static void spapr_machine_reset(void)
+static void spapr_machine_reset(MachineState *machine)
 {
-    MachineState *machine = MACHINE(qdev_get_machine());
-    sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
+    SpaprMachineState *spapr = SPAPR_MACHINE(machine);
     PowerPCCPU *first_ppc_cpu;
     uint32_t rtas_limit;
     hwaddr rtas_addr, fdt_addr;
@@ -1688,6 +1728,18 @@ static void spapr_machine_reset(void)
         spapr_setup_hpt_and_vrma(spapr);
     }
 
+    /*
+     * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node.
+     * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is
+     * called from vPHB reset handler so we initialize the counter here.
+     * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM
+     * must be equally distant from any other node.
+     * The final value of spapr->gpu_numa_id is going to be written to
+     * max-associativity-domains in spapr_build_fdt().
+     */
+    spapr->gpu_numa_id = MAX(1, nb_numa_nodes);
+    qemu_devices_reset();
+
     /*
      * If this reset wasn't generated by CAS, we should reset our
      * negotiated options and start from scratch
@@ -1703,14 +1755,22 @@ static void spapr_machine_reset(void)
         spapr_irq_msi_reset(spapr);
     }
 
-    qemu_devices_reset();
-
     /*
      * This is fixing some of the default configuration of the XIVE
      * devices. To be called after the reset of the machine devices.
      */
     spapr_irq_reset(spapr, &error_fatal);
 
+    /*
+     * There is no CAS under qtest. Simulate one to please the code that
+     * depends on spapr->ov5_cas. This is especially needed to test device
+     * unplug, so we do that before resetting the DRCs.
+     */
+    if (qtest_enabled()) {
+        spapr_ovec_cleanup(spapr->ov5_cas);
+        spapr->ov5_cas = spapr_ovec_clone(spapr->ov5);
+    }
+
     /* DRC reset may cause a device to be unplugged. This will cause troubles
      * if this device is used by another device (eg, a running vhost backend
      * will crash QEMU if the DIMM holding the vring goes away). To avoid such
@@ -1759,7 +1819,7 @@ static void spapr_machine_reset(void)
     spapr->cas_reboot = false;
 }
 
-static void spapr_create_nvram(sPAPRMachineState *spapr)
+static void spapr_create_nvram(SpaprMachineState *spapr)
 {
     DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
@@ -1771,10 +1831,10 @@ static void spapr_create_nvram(sPAPRMachineState *spapr)
 
     qdev_init_nofail(dev);
 
-    spapr->nvram = (struct sPAPRNVRAM *)dev;
+    spapr->nvram = (struct SpaprNvram *)dev;
 }
 
-static void spapr_rtc_create(sPAPRMachineState *spapr)
+static void spapr_rtc_create(SpaprMachineState *spapr)
 {
     object_initialize_child(OBJECT(spapr), "rtc",
                             &spapr->rtc, sizeof(spapr->rtc), TYPE_SPAPR_RTC,
@@ -1818,7 +1878,7 @@ static int spapr_pre_load(void *opaque)
 
 static int spapr_post_load(void *opaque, int version_id)
 {
-    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    SpaprMachineState *spapr = (SpaprMachineState *)opaque;
     int err = 0;
 
     err = spapr_caps_post_migration(spapr);
@@ -1885,7 +1945,7 @@ static bool version_before_3(void *opaque, int version_id)
 
 static bool spapr_pending_events_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    SpaprMachineState *spapr = (SpaprMachineState *)opaque;
     return !QTAILQ_EMPTY(&spapr->pending_events);
 }
 
@@ -1894,9 +1954,9 @@ static const VMStateDescription vmstate_spapr_event_entry = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(summary, sPAPREventLogEntry),
-        VMSTATE_UINT32(extended_length, sPAPREventLogEntry),
-        VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, sPAPREventLogEntry, 0,
+        VMSTATE_UINT32(summary, SpaprEventLogEntry),
+        VMSTATE_UINT32(extended_length, SpaprEventLogEntry),
+        VMSTATE_VBUFFER_ALLOC_UINT32(extended_log, SpaprEventLogEntry, 0,
                                      NULL, extended_length),
         VMSTATE_END_OF_LIST()
     },
@@ -1908,21 +1968,21 @@ static const VMStateDescription vmstate_spapr_pending_events = {
     .minimum_version_id = 1,
     .needed = spapr_pending_events_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1,
-                         vmstate_spapr_event_entry, sPAPREventLogEntry, next),
+        VMSTATE_QTAILQ_V(pending_events, SpaprMachineState, 1,
+                         vmstate_spapr_event_entry, SpaprEventLogEntry, next),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_ov5_cas_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
-    sPAPROptionVector *ov5_mask = spapr_ovec_new();
-    sPAPROptionVector *ov5_legacy = spapr_ovec_new();
-    sPAPROptionVector *ov5_removed = spapr_ovec_new();
+    SpaprMachineState *spapr = opaque;
+    SpaprOptionVector *ov5_mask = spapr_ovec_new();
+    SpaprOptionVector *ov5_legacy = spapr_ovec_new();
+    SpaprOptionVector *ov5_removed = spapr_ovec_new();
     bool cas_needed;
 
-    /* Prior to the introduction of sPAPROptionVector, we had two option
+    /* Prior to the introduction of SpaprOptionVector, we had two option
      * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY.
      * Both of these options encode machine topology into the device-tree
      * in such a way that the now-booted OS should still be able to interact
@@ -1972,15 +2032,15 @@ static const VMStateDescription vmstate_spapr_ov5_cas = {
     .minimum_version_id = 1,
     .needed = spapr_ov5_cas_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1,
-                                 vmstate_spapr_ovec, sPAPROptionVector),
+        VMSTATE_STRUCT_POINTER_V(ov5_cas, SpaprMachineState, 1,
+                                 vmstate_spapr_ovec, SpaprOptionVector),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_patb_entry_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     return !!spapr->patb_entry;
 }
@@ -1991,14 +2051,14 @@ static const VMStateDescription vmstate_spapr_patb_entry = {
     .minimum_version_id = 1,
     .needed = spapr_patb_entry_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT64(patb_entry, sPAPRMachineState),
+        VMSTATE_UINT64(patb_entry, SpaprMachineState),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_irq_map_needed(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr);
 }
@@ -2009,21 +2069,21 @@ static const VMStateDescription vmstate_spapr_irq_map = {
     .minimum_version_id = 1,
     .needed = spapr_irq_map_needed,
     .fields = (VMStateField[]) {
-        VMSTATE_BITMAP(irq_map, sPAPRMachineState, 0, irq_map_nr),
+        VMSTATE_BITMAP(irq_map, SpaprMachineState, 0, irq_map_nr),
         VMSTATE_END_OF_LIST()
     },
 };
 
 static bool spapr_dtb_needed(void *opaque)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(opaque);
 
     return smc->update_dt_enabled;
 }
 
 static int spapr_dtb_pre_load(void *opaque)
 {
-    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    SpaprMachineState *spapr = (SpaprMachineState *)opaque;
 
     g_free(spapr->fdt_blob);
     spapr->fdt_blob = NULL;
@@ -2039,9 +2099,9 @@ static const VMStateDescription vmstate_spapr_dtb = {
     .needed = spapr_dtb_needed,
     .pre_load = spapr_dtb_pre_load,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(fdt_initial_size, sPAPRMachineState),
-        VMSTATE_UINT32(fdt_size, sPAPRMachineState),
-        VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, sPAPRMachineState, 0, NULL,
+        VMSTATE_UINT32(fdt_initial_size, SpaprMachineState),
+        VMSTATE_UINT32(fdt_size, SpaprMachineState),
+        VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL,
                                      fdt_size),
         VMSTATE_END_OF_LIST()
     },
@@ -2059,9 +2119,9 @@ static const VMStateDescription vmstate_spapr = {
         VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
 
         /* RTC offset */
-        VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3),
+        VMSTATE_UINT64_TEST(rtc_offset, SpaprMachineState, version_before_3),
 
-        VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
+        VMSTATE_PPC_TIMEBASE_V(tb, SpaprMachineState, 2),
         VMSTATE_END_OF_LIST()
     },
     .subsections = (const VMStateDescription*[]) {
@@ -2074,16 +2134,19 @@ static const VMStateDescription vmstate_spapr = {
         &vmstate_spapr_cap_cfpc,
         &vmstate_spapr_cap_sbbc,
         &vmstate_spapr_cap_ibs,
+        &vmstate_spapr_cap_hpt_maxpagesize,
         &vmstate_spapr_irq_map,
         &vmstate_spapr_cap_nested_kvm_hv,
         &vmstate_spapr_dtb,
+        &vmstate_spapr_cap_large_decr,
+        &vmstate_spapr_cap_ccf_assist,
         NULL
     }
 };
 
 static int htab_save_setup(QEMUFile *f, void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     /* "Iteration" header */
     if (!spapr->htab_shift) {
@@ -2105,7 +2168,7 @@ static int htab_save_setup(QEMUFile *f, void *opaque)
     return 0;
 }
 
-static void htab_save_chunk(QEMUFile *f, sPAPRMachineState *spapr,
+static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr,
                             int chunkstart, int n_valid, int n_invalid)
 {
     qemu_put_be32(f, chunkstart);
@@ -2122,7 +2185,7 @@ static void htab_save_end_marker(QEMUFile *f)
     qemu_put_be16(f, 0);
 }
 
-static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
+static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr,
                                  int64_t max_ns)
 {
     bool has_timeout = max_ns != -1;
@@ -2170,7 +2233,7 @@ static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
     spapr->htab_save_index = index;
 }
 
-static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr,
+static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr,
                                 int64_t max_ns)
 {
     bool final = max_ns < 0;
@@ -2248,7 +2311,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr,
 
 static int htab_save_iterate(QEMUFile *f, void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
     int fd;
     int rc = 0;
 
@@ -2285,7 +2348,7 @@ static int htab_save_iterate(QEMUFile *f, void *opaque)
 
 static int htab_save_complete(QEMUFile *f, void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
     int fd;
 
     /* Iteration header */
@@ -2325,7 +2388,7 @@ static int htab_save_complete(QEMUFile *f, void *opaque)
 
 static int htab_load(QEMUFile *f, void *opaque, int version_id)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
     uint32_t section_hdr;
     int fd = -1;
     Error *local_err = NULL;
@@ -2415,7 +2478,7 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
 
 static void htab_save_cleanup(void *opaque)
 {
-    sPAPRMachineState *spapr = opaque;
+    SpaprMachineState *spapr = opaque;
 
     close_htab_fd(spapr);
 }
@@ -2435,7 +2498,7 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
     machine->boot_order = g_strdup(boot_device);
 }
 
-static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr)
+static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr)
 {
     MachineState *machine = MACHINE(spapr);
     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
@@ -2491,7 +2554,7 @@ static void spapr_validate_node_memory(MachineState *machine, Error **errp)
 /* find cpu slot in machine->possible_cpus by core_id */
 static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
 {
-    int index = id / smp_threads;
+    int index = id / ms->smp.threads;
 
     if (index >= ms->possible_cpus->len) {
         return NULL;
@@ -2502,12 +2565,14 @@ static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx)
     return &ms->possible_cpus->cpus[index];
 }
 
-static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp)
+static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp)
 {
+    MachineState *ms = MACHINE(spapr);
     Error *local_err = NULL;
     bool vsmt_user = !!spapr->vsmt;
     int kvm_smt = kvmppc_smt_threads();
     int ret;
+    unsigned int smp_threads = ms->smp.threads;
 
     if (!kvm_enabled() && (smp_threads > 1)) {
         error_setg(&local_err, "TCG cannot support more than 1 thread/core "
@@ -2574,13 +2639,16 @@ out:
     error_propagate(errp, local_err);
 }
 
-static void spapr_init_cpus(sPAPRMachineState *spapr)
+static void spapr_init_cpus(SpaprMachineState *spapr)
 {
     MachineState *machine = MACHINE(spapr);
     MachineClass *mc = MACHINE_GET_CLASS(machine);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
     const char *type = spapr_get_cpu_core_type(machine->cpu_type);
     const CPUArchIdList *possible_cpus;
+    unsigned int smp_cpus = machine->smp.cpus;
+    unsigned int smp_threads = machine->smp.threads;
+    unsigned int max_cpus = machine->smp.max_cpus;
     int boot_cores_nr = smp_cpus / smp_threads;
     int i;
 
@@ -2657,8 +2725,8 @@ static PCIHostState *spapr_create_default_phb(void)
 /* pSeries LPAR / sPAPR hardware init */
 static void spapr_machine_init(MachineState *machine)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
+    SpaprMachineState *spapr = SPAPR_MACHINE(machine);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
     const char *kernel_filename = machine->kernel_filename;
     const char *initrd_filename = machine->initrd_filename;
     PCIHostState *phb;
@@ -2773,13 +2841,7 @@ static void spapr_machine_init(MachineState *machine)
 
     /* advertise XIVE on POWER9 machines */
     if (spapr->irq->ov5 & (SPAPR_OV5_XIVE_EXPLOIT | SPAPR_OV5_XIVE_BOTH)) {
-        if (ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00,
-                                  0, spapr->max_compat_pvr)) {
-            spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
-        } else if (spapr->irq->ov5 & SPAPR_OV5_XIVE_EXPLOIT) {
-            error_report("XIVE-only machines require a POWER9 CPU");
-            exit(1);
-        }
+        spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT);
     }
 
     /* init CPUs */
@@ -2800,6 +2862,9 @@ static void spapr_machine_init(MachineState *machine)
 
         /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
         kvmppc_enable_clear_ref_mod_hcalls();
+
+        /* Enable H_PAGE_INIT */
+        kvmppc_enable_h_page_init();
     }
 
     /* allocate RAM */
@@ -3023,7 +3088,7 @@ static void spapr_machine_init(MachineState *machine)
     }
 }
 
-static int spapr_kvm_type(const char *vm_type)
+static int spapr_kvm_type(MachineState *machine, const char *vm_type)
 {
     if (!vm_type) {
         return 0;
@@ -3051,7 +3116,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
 #define CAST(type, obj, name) \
     ((type *)object_dynamic_cast(OBJECT(obj), (name)))
     SCSIDevice *d = CAST(SCSIDevice,  dev, TYPE_SCSI_DEVICE);
-    sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
+    SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
     VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);
 
     if (d) {
@@ -3131,14 +3196,14 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
 
 static char *spapr_get_kvm_type(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return g_strdup(spapr->kvm_type);
 }
 
 static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->kvm_type);
     spapr->kvm_type = g_strdup(value);
@@ -3146,7 +3211,7 @@ static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
 
 static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return spapr->use_hotplug_event_source;
 }
@@ -3154,7 +3219,7 @@ static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp)
 static void spapr_set_modern_hotplug_events(Object *obj, bool value,
                                             Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     spapr->use_hotplug_event_source = value;
 }
@@ -3166,7 +3231,7 @@ static bool spapr_get_msix_emulation(Object *obj, Error **errp)
 
 static char *spapr_get_resize_hpt(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     switch (spapr->resize_hpt) {
     case SPAPR_RESIZE_HPT_DEFAULT:
@@ -3183,7 +3248,7 @@ static char *spapr_get_resize_hpt(Object *obj, Error **errp)
 
 static void spapr_set_resize_hpt(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     if (strcmp(value, "default") == 0) {
         spapr->resize_hpt = SPAPR_RESIZE_HPT_DEFAULT;
@@ -3212,7 +3277,7 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
 
 static char *spapr_get_ic_mode(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     if (spapr->irq == &spapr_irq_xics_legacy) {
         return g_strdup("legacy");
@@ -3228,7 +3293,7 @@ static char *spapr_get_ic_mode(Object *obj, Error **errp)
 
 static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
         error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
@@ -3249,14 +3314,14 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
 
 static char *spapr_get_host_model(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return g_strdup(spapr->host_model);
 }
 
 static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->host_model);
     spapr->host_model = g_strdup(value);
@@ -3264,14 +3329,14 @@ static void spapr_set_host_model(Object *obj, const char *value, Error **errp)
 
 static char *spapr_get_host_serial(Object *obj, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     return g_strdup(spapr->host_serial);
 }
 
 static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->host_serial);
     spapr->host_serial = g_strdup(value);
@@ -3279,8 +3344,8 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
 
 static void spapr_instance_init(Object *obj)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 
     spapr->htab_fd = -1;
     spapr->use_hotplug_event_source = true;
@@ -3327,17 +3392,17 @@ static void spapr_instance_init(Object *obj)
         spapr_get_host_model, spapr_set_host_model,
         &error_abort);
     object_property_set_description(obj, "host-model",
-        "Set host's model-id to use - none|passthrough|string", &error_abort);
+        "Host model to advertise in guest device tree", &error_abort);
     object_property_add_str(obj, "host-serial",
         spapr_get_host_serial, spapr_set_host_serial,
         &error_abort);
     object_property_set_description(obj, "host-serial",
-        "Set host's system-id to use - none|passthrough|string", &error_abort);
+        "Host serial number to advertise in guest device tree", &error_abort);
 }
 
 static void spapr_machine_finalizefn(Object *obj)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     g_free(spapr->kvm_type);
 }
@@ -3357,7 +3422,7 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
     }
 }
 
-int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp)
 {
     uint64_t addr;
@@ -3374,7 +3439,7 @@ int spapr_lmb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
 static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
                            bool dedicated_hp_event_source, Error **errp)
 {
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
     int i;
     uint64_t addr = addr_start;
@@ -3423,7 +3488,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                               Error **errp)
 {
     Error *local_err = NULL;
-    sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
+    SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev);
     PCDIMMDevice *dimm = PC_DIMM(dev);
     uint64_t size, addr;
 
@@ -3457,8 +3522,8 @@ out:
 static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                   Error **errp)
 {
-    const sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
+    const SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
     PCDIMMDevice *dimm = PC_DIMM(dev);
     Error *local_err = NULL;
     uint64_t size;
@@ -3494,16 +3559,16 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp);
 }
 
-struct sPAPRDIMMState {
+struct SpaprDimmState {
     PCDIMMDevice *dimm;
     uint32_t nr_lmbs;
-    QTAILQ_ENTRY(sPAPRDIMMState) next;
+    QTAILQ_ENTRY(SpaprDimmState) next;
 };
 
-static sPAPRDIMMState *spapr_pending_dimm_unplugs_find(sPAPRMachineState *s,
+static SpaprDimmState *spapr_pending_dimm_unplugs_find(SpaprMachineState *s,
                                                        PCDIMMDevice *dimm)
 {
-    sPAPRDIMMState *dimm_state = NULL;
+    SpaprDimmState *dimm_state = NULL;
 
     QTAILQ_FOREACH(dimm_state, &s->pending_dimm_unplugs, next) {
         if (dimm_state->dimm == dimm) {
@@ -3513,11 +3578,11 @@ static sPAPRDIMMState *spapr_pending_dimm_unplugs_find(sPAPRMachineState *s,
     return dimm_state;
 }
 
-static sPAPRDIMMState *spapr_pending_dimm_unplugs_add(sPAPRMachineState *spapr,
+static SpaprDimmState *spapr_pending_dimm_unplugs_add(SpaprMachineState *spapr,
                                                       uint32_t nr_lmbs,
                                                       PCDIMMDevice *dimm)
 {
-    sPAPRDIMMState *ds = NULL;
+    SpaprDimmState *ds = NULL;
 
     /*
      * If this request is for a DIMM whose removal had failed earlier
@@ -3527,7 +3592,7 @@ static sPAPRDIMMState *spapr_pending_dimm_unplugs_add(sPAPRMachineState *spapr,
      */
     ds = spapr_pending_dimm_unplugs_find(spapr, dimm);
     if (!ds) {
-        ds = g_malloc0(sizeof(sPAPRDIMMState));
+        ds = g_malloc0(sizeof(SpaprDimmState));
         ds->nr_lmbs = nr_lmbs;
         ds->dimm = dimm;
         QTAILQ_INSERT_HEAD(&spapr->pending_dimm_unplugs, ds, next);
@@ -3535,17 +3600,17 @@ static sPAPRDIMMState *spapr_pending_dimm_unplugs_add(sPAPRMachineState *spapr,
     return ds;
 }
 
-static void spapr_pending_dimm_unplugs_remove(sPAPRMachineState *spapr,
-                                              sPAPRDIMMState *dimm_state)
+static void spapr_pending_dimm_unplugs_remove(SpaprMachineState *spapr,
+                                              SpaprDimmState *dimm_state)
 {
     QTAILQ_REMOVE(&spapr->pending_dimm_unplugs, dimm_state, next);
     g_free(dimm_state);
 }
 
-static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
+static SpaprDimmState *spapr_recover_pending_dimm_state(SpaprMachineState *ms,
                                                         PCDIMMDevice *dimm)
 {
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     uint64_t size = memory_device_get_region_size(MEMORY_DEVICE(dimm),
                                                   &error_abort);
     uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
@@ -3574,8 +3639,8 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
 void spapr_lmb_release(DeviceState *dev)
 {
     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
-    sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_ctrl);
+    SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
 
     /* This information will get lost if a migration occurs
      * during the unplug process. In this case recover it. */
@@ -3595,28 +3660,29 @@ void spapr_lmb_release(DeviceState *dev)
      * unplug handler chain. This can never fail.
      */
     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+    object_unparent(OBJECT(dev));
 }
 
 static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
-    sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
+    SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
 
     pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev));
-    object_unparent(OBJECT(dev));
+    object_property_set_bool(OBJECT(dev), false, "realized", NULL);
     spapr_pending_dimm_unplugs_remove(spapr, ds);
 }
 
 static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
                                         DeviceState *dev, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
     Error *local_err = NULL;
     PCDIMMDevice *dimm = PC_DIMM(dev);
     uint32_t nr_lmbs;
     uint64_t size, addr_start, addr;
     int i;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
 
     size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &error_abort);
     nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
@@ -3667,17 +3733,18 @@ void spapr_core_release(DeviceState *dev)
 
     /* Call the unplug handler chain. This can never fail. */
     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+    object_unparent(OBJECT(dev));
 }
 
 static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
 {
     MachineState *ms = MACHINE(hotplug_dev);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(ms);
     CPUCore *cc = CPU_CORE(dev);
     CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL);
 
     if (smc->pre_2_10_has_unused_icps) {
-        sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
+        SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
         int i;
 
         for (i = 0; i < cc->nr_threads; i++) {
@@ -3689,16 +3756,16 @@ static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
 
     assert(core_slot);
     core_slot->cpu = NULL;
-    object_unparent(OBJECT(dev));
+    object_property_set_bool(OBJECT(dev), false, "realized", NULL);
 }
 
 static
 void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
     int index;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     CPUCore *cc = CPU_CORE(dev);
 
     if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) {
@@ -3720,10 +3787,10 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
     spapr_hotplug_req_remove_by_index(drc);
 }
 
-int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                            void *fdt, int *fdt_start_offset, Error **errp)
 {
-    sPAPRCPUCore *core = SPAPR_CPU_CORE(drc->dev);
+    SpaprCpuCore *core = SPAPR_CPU_CORE(drc->dev);
     CPUState *cs = CPU(core->threads[0]);
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     DeviceClass *dc = DEVICE_GET_CLASS(cs);
@@ -3744,13 +3811,13 @@ int spapr_core_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
 static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                             Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
     MachineClass *mc = MACHINE_GET_CLASS(spapr);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-    sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprCpuCore *core = SPAPR_CPU_CORE(OBJECT(dev));
     CPUCore *cc = CPU_CORE(dev);
     CPUState *cs;
-    sPAPRDRConnector *drc;
+    SpaprDrc *drc;
     Error *local_err = NULL;
     CPUArchId *core_slot;
     int index;
@@ -3808,6 +3875,7 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     const char *type = object_get_typename(OBJECT(dev));
     CPUArchId *core_slot;
     int index;
+    unsigned int smp_threads = machine->smp.threads;
 
     if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
         error_setg(&local_err, "CPU hotplug not supported for this machine");
@@ -3853,10 +3921,10 @@ out:
     error_propagate(errp, local_err);
 }
 
-int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
+int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
                           void *fdt, int *fdt_start_offset, Error **errp)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(drc->dev);
     int intc_phandle;
 
     intc_phandle = spapr_irq_get_phandle(spapr, spapr->fdt_blob, errp);
@@ -3864,8 +3932,8 @@ int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
         return -1;
     }
 
-    if (spapr_populate_pci_dt(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
-                              fdt_start_offset)) {
+    if (spapr_dt_phb(sphb, intc_phandle, fdt, spapr->irq->nr_msis,
+                     fdt_start_offset)) {
         error_setg(errp, "unable to create FDT node for PHB %d", sphb->index);
         return -1;
     }
@@ -3879,9 +3947,9 @@ int spapr_phb_dt_populate(sPAPRDRConnector *drc, sPAPRMachineState *spapr,
 static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
 
     if (dev->hotplugged && !smc->dr_phb_enabled) {
@@ -3901,16 +3969,18 @@ static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
     smc->phb_placement(spapr, sphb->index,
                        &sphb->buid, &sphb->io_win_addr,
                        &sphb->mem_win_addr, &sphb->mem64_win_addr,
-                       windows_supported, sphb->dma_liobn, errp);
+                       windows_supported, sphb->dma_liobn,
+                       &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr,
+                       errp);
 }
 
 static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                            Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
-    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
-    sPAPRDRConnector *drc;
+    SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+    SpaprDrc *drc;
     bool hotplugged = spapr_drc_hotplugged(dev);
     Error *local_err = NULL;
 
@@ -3940,18 +4010,19 @@ void spapr_phb_release(DeviceState *dev)
     HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev);
 
     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
+    object_unparent(OBJECT(dev));
 }
 
 static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
 {
-    object_unparent(OBJECT(dev));
+    object_property_set_bool(OBJECT(dev), false, "realized", NULL);
 }
 
 static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp)
 {
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
-    sPAPRDRConnector *drc;
+    SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+    SpaprDrc *drc;
 
     drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index);
     assert(drc);
@@ -3989,9 +4060,9 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
 static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
                                                 DeviceState *dev, Error **errp)
 {
-    sPAPRMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
+    SpaprMachineState *sms = SPAPR_MACHINE(OBJECT(hotplug_dev));
     MachineClass *mc = MACHINE_GET_CLASS(sms);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
         if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
@@ -4040,6 +4111,17 @@ static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
         object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
         return HOTPLUG_HANDLER(machine);
     }
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
+        PCIDevice *pcidev = PCI_DEVICE(dev);
+        PCIBus *root = pci_device_root_bus(pcidev);
+        SpaprPhbState *phb =
+            (SpaprPhbState *)object_dynamic_cast(OBJECT(BUS(root)->parent),
+                                                 TYPE_SPAPR_PCI_HOST_BRIDGE);
+
+        if (phb) {
+            return HOTPLUG_HANDLER(phb);
+        }
+    }
     return NULL;
 }
 
@@ -4059,14 +4141,16 @@ spapr_cpu_index_to_props(MachineState *machine, unsigned cpu_index)
 
 static int64_t spapr_get_default_cpu_node_id(const MachineState *ms, int idx)
 {
-    return idx / smp_cores % nb_numa_nodes;
+    return idx / ms->smp.cores % nb_numa_nodes;
 }
 
 static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
 {
     int i;
+    unsigned int smp_threads = machine->smp.threads;
+    unsigned int smp_cpus = machine->smp.cpus;
     const char *core_type;
-    int spapr_max_cores = max_cpus / smp_threads;
+    int spapr_max_cores = machine->smp.max_cpus / smp_threads;
     MachineClass *mc = MACHINE_GET_CLASS(machine);
 
     if (!mc->has_hotpluggable_cpus) {
@@ -4098,10 +4182,11 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
     return machine->possible_cpus;
 }
 
-static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
+static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
                                 uint64_t *buid, hwaddr *pio,
                                 hwaddr *mmio32, hwaddr *mmio64,
-                                unsigned n_dma, uint32_t *liobns, Error **errp)
+                                unsigned n_dma, uint32_t *liobns,
+                                hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
 {
     /*
      * New-style PHB window placement.
@@ -4146,18 +4231,21 @@ static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
     *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
     *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
     *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
+
+    *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE;
+    *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE;
 }
 
 static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(dev);
 
     return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL;
 }
 
 static void spapr_ics_resend(XICSFabric *dev)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(dev);
+    SpaprMachineState *spapr = SPAPR_MACHINE(dev);
 
     ics_resend(spapr->ics);
 }
@@ -4172,7 +4260,7 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
 static void spapr_pic_print_info(InterruptStatsProvider *obj,
                                  Monitor *mon)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
+    SpaprMachineState *spapr = SPAPR_MACHINE(obj);
 
     spapr->irq->print_info(spapr, mon);
 }
@@ -4184,7 +4272,8 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu)
 
 void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
 {
-    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    MachineState *ms = MACHINE(spapr);
     int vcpu_id;
 
     vcpu_id = spapr_vcpu_id(spapr, cpu_index);
@@ -4193,7 +4282,7 @@ void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp)
         error_setg(errp, "Can't create CPU with id %d in KVM", vcpu_id);
         error_append_hint(errp, "Adjust the number of cpus to %d "
                           "or try to raise the number of threads per core\n",
-                          vcpu_id * smp_threads / spapr->vsmt);
+                          vcpu_id * ms->smp.threads / spapr->vsmt);
         return;
     }
 
@@ -4218,7 +4307,7 @@ PowerPCCPU *spapr_find_cpu(int vcpu_id)
 static void spapr_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
     FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
     NMIClass *nc = NMI_CLASS(oc);
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
@@ -4267,7 +4356,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
     vhc->hpt_mask = spapr_hpt_mask;
     vhc->map_hptes = spapr_map_hptes;
     vhc->unmap_hptes = spapr_unmap_hptes;
-    vhc->store_hpte = spapr_store_hpte;
+    vhc->hpte_set_c = spapr_hpte_set_c;
+    vhc->hpte_set_r = spapr_hpte_set_r;
     vhc->get_pate = spapr_get_pate;
     vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
     xic->ics_get = spapr_ics_get;
@@ -4279,17 +4369,20 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
      * in which LMBs are represented and hot-added
      */
     mc->numa_mem_align_shift = 28;
+    mc->numa_mem_supported = true;
 
     smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
     smc->default_caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_ON;
     smc->default_caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_ON;
-    smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
-    smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
-    smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
+    smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
+    smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND;
     smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
     smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
+    smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
+    smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
     spapr_caps_add_properties(smc, &error_abort);
-    smc->irq = &spapr_irq_xics;
+    smc->irq = &spapr_irq_dual;
     smc->dr_phb_enabled = true;
 }
 
@@ -4297,10 +4390,10 @@ static const TypeInfo spapr_machine_info = {
     .name          = TYPE_SPAPR_MACHINE,
     .parent        = TYPE_MACHINE,
     .abstract      = true,
-    .instance_size = sizeof(sPAPRMachineState),
+    .instance_size = sizeof(SpaprMachineState),
     .instance_init = spapr_instance_init,
     .instance_finalize = spapr_machine_finalizefn,
-    .class_size    = sizeof(sPAPRMachineClass),
+    .class_size    = sizeof(SpaprMachineClass),
     .class_init    = spapr_machine_class_init,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_FW_PATH_PROVIDER },
@@ -4335,34 +4428,62 @@ static const TypeInfo spapr_machine_info = {
     }                                                                \
     type_init(spapr_machine_register_##suffix)
 
+/*
+ * pseries-4.1
+ */
+static void spapr_machine_4_1_class_options(MachineClass *mc)
+{
+    /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(4_1, "4.1", true);
+
 /*
  * pseries-4.0
  */
+static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
+                              uint64_t *buid, hwaddr *pio,
+                              hwaddr *mmio32, hwaddr *mmio64,
+                              unsigned n_dma, uint32_t *liobns,
+                              hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
+{
+    spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns,
+                        nv2gpa, nv2atsd, errp);
+    *nv2gpa = 0;
+    *nv2atsd = 0;
+}
+
 static void spapr_machine_4_0_class_options(MachineClass *mc)
 {
-    /* Defaults for the latest behaviour inherited from the base class */
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
+    spapr_machine_4_1_class_options(mc);
+    compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
+    smc->phb_placement = phb_placement_4_0;
+    smc->irq = &spapr_irq_xics;
+    smc->pre_4_1_migration = true;
 }
 
-DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
+DEFINE_SPAPR_MACHINE(4_0, "4.0", false);
 
 /*
  * pseries-3.1
  */
 static void spapr_machine_3_1_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-    static GlobalProperty compat[] = {
-        { TYPE_SPAPR_MACHINE, "host-model", "passthrough" },
-        { TYPE_SPAPR_MACHINE, "host-serial", "passthrough" },
-    };
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_4_0_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_3_1, hw_compat_3_1_len);
-    compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
 
     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
     smc->update_dt_enabled = false;
     smc->dr_phb_enabled = false;
+    smc->broken_host_serial_model = true;
+    smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
+    smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
 }
 
 DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
@@ -4373,7 +4494,7 @@ DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
 
 static void spapr_machine_3_0_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_3_1_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_3_0, hw_compat_3_0_len);
@@ -4389,7 +4510,7 @@ DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
  */
 static void spapr_machine_2_12_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" },
         { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" },
@@ -4411,7 +4532,7 @@ DEFINE_SPAPR_MACHINE(2_12, "2.12", false);
 
 static void spapr_machine_2_12_sxxm_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_2_12_class_options(mc);
     smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
@@ -4427,7 +4548,7 @@ DEFINE_SPAPR_MACHINE(2_12_sxxm, "2.12-sxxm", false);
 
 static void spapr_machine_2_11_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_2_12_class_options(mc);
     smc->default_caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_ON;
@@ -4454,7 +4575,7 @@ DEFINE_SPAPR_MACHINE(2_10, "2.10", false);
 
 static void spapr_machine_2_9_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_POWERPC_CPU, "pre-2.10-migration", "on" },
     };
@@ -4491,10 +4612,11 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false);
  * pseries-2.7
  */
 
-static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
+static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
                               uint64_t *buid, hwaddr *pio,
                               hwaddr *mmio32, hwaddr *mmio64,
-                              unsigned n_dma, uint32_t *liobns, Error **errp)
+                              unsigned n_dma, uint32_t *liobns,
+                              hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
 {
     /* Legacy PHB placement for pseries-2.7 and earlier machine types */
     const uint64_t base_buid = 0x800000020000000ULL;
@@ -4538,11 +4660,14 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
      * fallback behaviour of automatically splitting a large "32-bit"
      * window into contiguous 32-bit and 64-bit windows
      */
+
+    *nv2gpa = 0;
+    *nv2atsd = 0;
 }
 
 static void spapr_machine_2_7_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem_win_size", "0xf80000000", },
         { TYPE_SPAPR_PCI_HOST_BRIDGE, "mem64_win_size", "0", },
@@ -4584,7 +4709,7 @@ DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
 
 static void spapr_machine_2_5_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     static GlobalProperty compat[] = {
         { "spapr-vlan", "use-rx-buffer-pools", "off" },
     };
@@ -4603,7 +4728,7 @@ DEFINE_SPAPR_MACHINE(2_5, "2.5", false);
 
 static void spapr_machine_2_4_class_options(MachineClass *mc)
 {
-    sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+    SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
 
     spapr_machine_2_5_class_options(mc);
     smc->dr_lmb_enabled = false;
This page took 0.093847 seconds and 4 git commands to generate.