From 7b0f4ec9d3ae66ef3b96b05d691d56aa9005ef5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 1 Oct 2018 13:44:20 +0200 Subject: ppc440_pcix: convert SysBus init method to a realize method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédric Le Goater Reviewed-by: Greg Kurz Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/ppc/ppc440_pcix.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index 64ed07a..42ef76b 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -466,17 +466,18 @@ const MemoryRegionOps ppc440_pcix_host_data_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int ppc440_pcix_initfn(SysBusDevice *dev) +static void ppc440_pcix_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); PPC440PCIXState *s; PCIHostState *h; h = PCI_HOST_BRIDGE(dev); s = PPC440_PCIX_HOST_BRIDGE(dev); - sysbus_init_irq(dev, &s->irq); + sysbus_init_irq(sbd, &s->irq); memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); - h->bus = pci_register_root_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq, + h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, ppc440_pcix_map_irq, &s->irq, &s->busmem, get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); @@ -497,17 +498,14 @@ static int ppc440_pcix_initfn(SysBusDevice *dev) memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); - sysbus_init_mmio(dev, &s->container); - - return 0; + sysbus_init_mmio(sbd, &s->container); } static void ppc440_pcix_class_init(ObjectClass *klass, void *data) { - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = ppc440_pcix_initfn; + dc->realize = ppc440_pcix_realize; dc->reset = ppc440_pcix_reset; } -- cgit v1.1 From 95ba5567073c89e8f63557c930bc82d45a8e7c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 1 Oct 2018 13:44:21 +0200 Subject: ppc4xx_pci: convert SysBus init method to a realize method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédric Le Goater Reviewed-by: Greg Kurz Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/ppc/ppc4xx_pci.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index b7642ba..86981be 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -300,8 +300,9 @@ static const VMStateDescription vmstate_ppc4xx_pci = { }; /* XXX Interrupt acknowledge cycles not supported. */ -static int ppc4xx_pcihost_initfn(SysBusDevice *dev) +static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); PPC4xxPCIState *s; PCIHostState *h; PCIBus *b; @@ -311,10 +312,10 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) s = PPC4xx_PCI_HOST_BRIDGE(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { - sysbus_init_irq(dev, &s->irq[i]); + sysbus_init_irq(sbd, &s->irq[i]); } - b = pci_register_root_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq, + b = pci_register_root_bus(dev, NULL, ppc4xx_pci_set_irq, ppc4xx_pci_map_irq, s->irq, get_system_memory(), get_system_io(), 0, 4, TYPE_PCI_BUS); h->bus = b; @@ -332,10 +333,8 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); memory_region_add_subregion(&s->container, PCI_REG_BASE, &s->iomem); - sysbus_init_mmio(dev, &s->container); + sysbus_init_mmio(sbd, &s->container); qemu_register_reset(ppc4xx_pci_reset, s); - - return 0; } static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) @@ -367,10 +366,9 @@ static const TypeInfo ppc4xx_host_bridge_info = { static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data) { - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = ppc4xx_pcihost_initfn; + dc->realize = ppc4xx_pcihost_realize; dc->vmsd = &vmstate_ppc4xx_pci; } -- cgit v1.1 From 73785b329e12bddae32201e4e1d84e0909c21364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Mon, 1 Oct 2018 17:04:13 +0200 Subject: PPC: e500: convert SysBus init method to a realize method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- hw/pci-host/ppce500.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'hw') diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index eb75e08..b8f8c11 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -436,8 +436,9 @@ static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque, return &s->bm_as; } -static int e500_pcihost_initfn(SysBusDevice *dev) +static void e500_pcihost_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); PCIHostState *h; PPCE500PCIState *s; PCIBus *b; @@ -447,7 +448,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) s = PPC_E500_PCI_HOST_BRIDGE(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { - sysbus_init_irq(dev, &s->irq[i]); + sysbus_init_irq(sbd, &s->irq[i]); } for (i = 0; i < PCI_NUM_PINS; i++) { @@ -460,7 +461,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) /* PIO lives at the bottom of our bus space */ memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2); - b = pci_register_root_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, + b = pci_register_root_bus(dev, NULL, mpc85xx_pci_set_irq, mpc85xx_pci_map_irq, s, &s->busmem, &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS); h->bus = b; @@ -483,10 +484,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev) memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem); memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem); - sysbus_init_mmio(dev, &s->container); + sysbus_init_mmio(sbd, &s->container); pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq); - - return 0; } static void e500_host_bridge_class_init(ObjectClass *klass, void *data) @@ -526,9 +525,8 @@ static Property pcihost_properties[] = { static void e500_pcihost_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = e500_pcihost_initfn; + dc->realize = e500_pcihost_realize; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->props = pcihost_properties; dc->vmsd = &vmstate_ppce500_pci; -- cgit v1.1 From 0e947a89ce5911ccc92972e4057dfe7d0643e8f7 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 8 Oct 2018 14:39:42 +0200 Subject: hw/ppc/spapr_rng: Introduce CONFIG_SPAPR_RNG switch for spapr_rng.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spapr-rng device is suboptimal when compared to virtio-rng, so users might want to disable it in their builds. Thus let's introduce a proper CONFIG switch to allow us to compile QEMU without this device. The function spapr_rng_populate_dt is required for linking, so move it to a different location. Signed-off-by: Thomas Huth Reviewed-by: Greg Kurz Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/ppc/Makefile.objs | 3 ++- hw/ppc/spapr.c | 23 +++++++++++++++++++++++ hw/ppc/spapr_rng.c | 23 ----------------------- 3 files changed, 25 insertions(+), 24 deletions(-) (limited to 'hw') diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 4ab5564..4e0c1c0 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -3,8 +3,9 @@ obj-y += ppc.o ppc_booke.o fdt.o # IBM pSeries (sPAPR) obj-$(CONFIG_PSERIES) += spapr.o spapr_caps.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o -obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o +obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o spapr_irq.o +obj-$(CONFIG_SPAPR_RNG) += spapr_rng.o # IBM PowerNV obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c08130f..e47b004 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -610,6 +610,29 @@ static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) g_free(rev); } +static int spapr_rng_populate_dt(void *fdt) +{ + int node; + int ret; + + node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); + if (node <= 0) { + return -1; + } + ret = fdt_setprop_string(fdt, node, "device_type", + "ibm,platform-facilities"); + ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); + ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); + + node = fdt_add_subnode(fdt, node, "ibm,random-v1"); + if (node <= 0) { + return -1; + } + ret |= 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; diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c index d2acd61..644bac9 100644 --- a/hw/ppc/spapr_rng.c +++ b/hw/ppc/spapr_rng.c @@ -132,29 +132,6 @@ static void spapr_rng_realize(DeviceState *dev, Error **errp) } } -int spapr_rng_populate_dt(void *fdt) -{ - int node; - int ret; - - node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities"); - if (node <= 0) { - return -1; - } - ret = fdt_setprop_string(fdt, node, "device_type", - "ibm,platform-facilities"); - ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1); - ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0); - - node = fdt_add_subnode(fdt, node, "ibm,random-v1"); - if (node <= 0) { - return -1; - } - ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random"); - - return ret ? -1 : 0; -} - static Property spapr_rng_properties[] = { DEFINE_PROP_BOOL("use-kvm", sPAPRRngState, use_kvm, false), DEFINE_PROP_LINK("rng", sPAPRRngState, backend, TYPE_RNG_BACKEND, -- cgit v1.1 From 4fc4c6a53d69af50c4421857c749f84f927d09f6 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 12 Oct 2018 11:05:09 +0200 Subject: spapr_pci: convert g_malloc() to g_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When allocating an array, it is a recommended coding practice to call g_new(FooType, n) instead of g_malloc(n * sizeof(FooType)) because it takes care to avoid overflow when calculating the size of the allocated block and it returns FooType *, which allows the compiler to perform type checking. Signed-off-by: Greg Kurz Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/ppc/spapr_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 58afa46..2374d55 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1882,7 +1882,7 @@ static int spapr_pci_pre_save(void *opaque) if (!sphb->msi_devs_num) { return 0; } - sphb->msi_devs = g_malloc(sphb->msi_devs_num * sizeof(spapr_pci_msi_mig)); + sphb->msi_devs = g_new(spapr_pci_msi_mig, sphb->msi_devs_num); g_hash_table_iter_init(&iter, sphb->msi); for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) { -- cgit v1.1 From 0c2adc175398c37cc40b0164849aada9ad9c56c4 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Fri, 27 Jul 2018 13:31:12 +0100 Subject: macio/pmu: Fix missing vmsd terminator Fix missing terminator in VMStateDescription Fixes: d811d61fbc6ca5f2be2185fd7cfa916e7ba613ce Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Mark Cave-Ayland Reviewed-by: Laurent Vivier Signed-off-by: David Gibson --- hw/misc/macio/pmu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw') diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c index d25344f..6e6d96c 100644 --- a/hw/misc/macio/pmu.c +++ b/hw/misc/macio/pmu.c @@ -686,6 +686,7 @@ static const VMStateDescription vmstate_pmu_adb = { VMSTATE_TIMER_PTR(adb_poll_timer, PMUState), VMSTATE_UINT8(adb_reply_size, PMUState), VMSTATE_BUFFER(adb_reply, PMUState), + VMSTATE_END_OF_LIST() } }; -- cgit v1.1 From 1bbd6272a18d6fe3390d4b4200a1a7a566b304fa Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 1 Nov 2018 16:17:58 +0000 Subject: hw/ppc/mac_newworld: Free openpic_irqs array after use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In ppc_core99_init(), we allocate an openpic_irqs array, which we then use to collect up the various qemu_irqs which we're going to connect to the interrupt controller. Once we've called sysbus_connect_irq() to connect them all up, the array is no longer required, but we forgot to free it. Since board init is only run once at startup, the memory leak is not a significant one. Spotted by Coverity: CID 1192916. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/ppc/mac_newworld.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw') diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index a630cb8..14273a1 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -303,6 +303,7 @@ static void ppc_core99_init(MachineState *machine) sysbus_connect_irq(s, k++, openpic_irqs[i][j]); } } + g_free(openpic_irqs); if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ -- cgit v1.1 From d07945e78eb6b593cd17a4640c1fc9eb35e3245d Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Fri, 26 Oct 2018 18:03:58 +0530 Subject: ppc/pnv: check size before data buffer access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While performing PowerNV memory r/w operations, the access length 'sz' could exceed the data[4] buffer size. Add check to avoid OOB access. Reported-by: Moguofang Signed-off-by: Prasad J Pandit Reviewed-by: Cédric Le Goater Signed-off-by: David Gibson --- hw/ppc/pnv_lpc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index d772132..172a915 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -155,9 +155,15 @@ static void pnv_lpc_do_eccb(PnvLpcController *lpc, uint64_t cmd) /* XXX Check for magic bits at the top, addr size etc... */ unsigned int sz = (cmd & ECCB_CTL_SZ_MASK) >> ECCB_CTL_SZ_LSH; uint32_t opb_addr = cmd & ECCB_CTL_ADDR_MASK; - uint8_t data[4]; + uint8_t data[8]; bool success; + if (sz > sizeof(data)) { + qemu_log_mask(LOG_GUEST_ERROR, + "ECCB: invalid operation at @0x%08x size %d\n", opb_addr, sz); + return; + } + if (cmd & ECCB_CTL_READ) { success = opb_read(lpc, opb_addr, data, sz); if (success) { -- cgit v1.1 From 09a333ee3dbbc6cdd88830f5b68dc358cacb0093 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 30 Oct 2018 17:03:53 +0000 Subject: hw/ppc/ppc440_uc: Remove dead code in sdram_size() Coverity points out in CID 1390588 that the test for sh == 0 in sdram_size() can never fire, because we calculate sh with sh = 1024 - ((bcr >> 6) & 0x3ff); which must result in a value between 1 and 1024 inclusive. Without the relevant manual for the SoC, we're not completely sure of the correct behaviour here, but we can remove the dead code without changing how QEMU currently behaves. Signed-off-by: Peter Maydell Reviewed-by: Laurent Vivier Signed-off-by: David Gibson --- hw/ppc/ppc440_uc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 09ccda5..9360f78 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -559,11 +559,7 @@ static target_ulong sdram_size(uint32_t bcr) int sh; sh = 1024 - ((bcr >> 6) & 0x3ff); - if (sh == 0) { - size = -1; - } else { - size = 8 * MiB * sh; - } + size = 8 * MiB * sh; return size; } -- cgit v1.1 From b9a477b725788e47bf653eab36e64f232d259f2a Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Mon, 8 Oct 2018 14:25:39 +1100 Subject: ppc/spapr_caps: Add SPAPR_CAP_NESTED_KVM_HV Add the spapr cap SPAPR_CAP_NESTED_KVM_HV to be used to control the availability of nested kvm-hv to the level 1 (L1) guest. Assuming a hypervisor with support enabled an L1 guest can be allowed to use the kvm-hv module (and thus run it's own kvm-hv guests) by setting: -machine pseries,cap-nested-hv=true or disabled with: -machine pseries,cap-nested-hv=false Signed-off-by: Suraj Jitindar Singh Signed-off-by: David Gibson --- hw/ppc/spapr.c | 2 ++ hw/ppc/spapr_caps.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'hw') diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e47b004..7afd1a1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1938,6 +1938,7 @@ static const VMStateDescription vmstate_spapr = { &vmstate_spapr_cap_sbbc, &vmstate_spapr_cap_ibs, &vmstate_spapr_irq_map, + &vmstate_spapr_cap_nested_kvm_hv, NULL } }; @@ -3902,6 +3903,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) 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_HPT_MAXPAGESIZE] = 16; /* 64kiB */ + smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; spapr_caps_add_properties(smc, &error_abort); smc->irq = &spapr_irq_xics; } diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c index aa605ce..64f98ae 100644 --- a/hw/ppc/spapr_caps.c +++ b/hw/ppc/spapr_caps.c @@ -368,6 +368,28 @@ static void cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr, ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, &maxshift); } +static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr, + uint8_t val, Error **errp) +{ + if (!val) { + /* capability disabled by default */ + return; + } + + if (tcg_enabled()) { + error_setg(errp, + "No Nested KVM-HV support in tcg, try cap-nested-hv=off"); + } else if (kvm_enabled()) { + if (!kvmppc_has_cap_nested_kvm_hv()) { + error_setg(errp, +"KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off"); + } else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) { + error_setg(errp, +"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off"); + } + } +} + sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { [SPAPR_CAP_HTM] = { .name = "htm", @@ -437,6 +459,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { .apply = cap_hpt_maxpagesize_apply, .cpu_apply = cap_hpt_maxpagesize_cpu_apply, }, + [SPAPR_CAP_NESTED_KVM_HV] = { + .name = "nested-hv", + .description = "Allow Nested KVM-HV", + .index = SPAPR_CAP_NESTED_KVM_HV, + .get = spapr_cap_get_bool, + .set = spapr_cap_set_bool, + .type = "bool", + .apply = cap_nested_kvm_hv_apply, + }, }; static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr, @@ -564,6 +595,7 @@ SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP); SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC); SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC); SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS); +SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV); void spapr_caps_init(sPAPRMachineState *spapr) { -- cgit v1.1