From nobody Sun Apr 28 10:46:56 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510152564648926.5224256590991; Wed, 8 Nov 2017 06:49:24 -0800 (PST) Received: from localhost ([::1]:60307 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCRfJ-0006Zl-NX for importer@patchew.org; Wed, 08 Nov 2017 09:49:17 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53082) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCReS-0006HG-8T for qemu-devel@nongnu.org; Wed, 08 Nov 2017 09:48:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eCReO-0004zo-8I for qemu-devel@nongnu.org; Wed, 08 Nov 2017 09:48:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:5202) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eCReN-0004zO-VX for qemu-devel@nongnu.org; Wed, 08 Nov 2017 09:48:20 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ED36B81DFB for ; Wed, 8 Nov 2017 14:48:18 +0000 (UTC) Received: from localhost.localdomain (unknown [10.35.206.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9963D5C550; Wed, 8 Nov 2017 14:48:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com ED36B81DFB Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=marcel@redhat.com From: Marcel Apfelbaum To: qemu-devel@nongnu.org Date: Wed, 8 Nov 2017 16:48:09 +0200 Message-Id: <20171108144809.56305-1-marcel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 08 Nov 2017 14:48:19 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH V3] hw/pci-host: Fix x86 Host Bridges 64bit PCI hole X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ehabkost@redhat.com, mst@redhat.com, kraxel@redhat.com, imammedo@redhat.com, marcel@redhat.com, pbonzini@redhat.com, lersek@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Currently there is no MMIO range over 4G reserved for PCI hotplug. Since the 32bit PCI hole depends on the number of cold-plugged PCI devices and other factors, it is very possible is too small to hotplug PCI devices with large BARs. Fix it by reserving 2G for I4400FX chipset in order to comply with older Win32 Guest OSes and 32G for Q35 chipset. Note this is a regression since prev QEMU versions had some range reserved for 64bit PCI hotplug. Signed-off-by: Marcel Apfelbaum Reviewed-by: Gerd Hoffmann Reviewed-by: Laszlo Ersek --- V2 -> V3: - Addressed Gerd's and others comments and re-enabled the pci-hole64-size property defaulting it to 2G for I440FX and 32g for Q35. - Even if the new defaults of pci-hole64-size will appear in "info qtree" also for older machines, the property was not implemented so no changes will be visible to guests. V1 -> V2: Addressed Igor's comments: - aligned the hole64 start to 1Gb (I think all the computations took care of it already, but it can't hurt) - Init compat props to "off" instead of "false" Thanks, Marcel=20 hw/i386/pc.c | 18 ++++++++++++++++++ hw/pci-host/piix.c | 13 ++++++++++++- hw/pci-host/q35.c | 17 +++++++++++++++-- include/hw/i386/pc.h | 10 +++++++++- include/hw/pci-host/q35.h | 1 + 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e11a65b545..af3177cca5 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1448,6 +1448,24 @@ void pc_memory_init(PCMachineState *pcms, pcms->ioapic_as =3D &address_space_memory; } =20 +uint64_t pc_pci_hole64_start(void) +{ + PCMachineState *pcms =3D PC_MACHINE(qdev_get_machine()); + PCMachineClass *pcmc =3D PC_MACHINE_GET_CLASS(pcms); + uint64_t hole64_start =3D 0; + + if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) { + hole64_start =3D pcms->hotplug_memory.base; + if (!pcmc->broken_reserved_end) { + hole64_start +=3D memory_region_size(&pcms->hotplug_memory.mr); + } + } else { + hole64_start =3D 0x100000000ULL + pcms->above_4g_mem_size; + } + + return ROUND_UP(hole64_start, 1ULL << 30); +} + qemu_irq pc_allocate_cpu_irq(void) { return qemu_allocate_irq(pic_irq_request, NULL, 0); diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index a7e2256870..e033ee7df8 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -50,6 +50,7 @@ typedef struct I440FXState { PCIHostState parent_obj; Range pci_hole; uint64_t pci_hole64_size; + bool pci_hole64_fix; uint32_t short_root_bus; } I440FXState; =20 @@ -243,11 +244,15 @@ static void i440fx_pcihost_get_pci_hole64_start(Objec= t *obj, Visitor *v, void *opaque, Error **errp) { PCIHostState *h =3D PCI_HOST_BRIDGE(obj); + I440FXState *s =3D I440FX_PCI_HOST_BRIDGE(obj); Range w64; uint64_t value; =20 pci_bus_get_w64_range(h->bus, &w64); value =3D range_is_empty(&w64) ? 0 : range_lob(&w64); + if (!value && s->pci_hole64_fix) { + value =3D pc_pci_hole64_start(); + } visit_type_uint64(v, name, &value, errp); } =20 @@ -256,11 +261,16 @@ static void i440fx_pcihost_get_pci_hole64_end(Object = *obj, Visitor *v, Error **errp) { PCIHostState *h =3D PCI_HOST_BRIDGE(obj); + I440FXState *s =3D I440FX_PCI_HOST_BRIDGE(obj); + uint64_t hole64_start =3D pc_pci_hole64_start(); Range w64; uint64_t value; =20 pci_bus_get_w64_range(h->bus, &w64); value =3D range_is_empty(&w64) ? 0 : range_upb(&w64) + 1; + if (s->pci_hole64_fix && value < (hole64_start + s->pci_hole64_size)) { + value =3D hole64_start + s->pci_hole64_size; + } visit_type_uint64(v, name, &value, errp); } =20 @@ -863,8 +873,9 @@ static const char *i440fx_pcihost_root_bus_path(PCIHost= State *host_bridge, =20 static Property i440fx_props[] =3D { DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState, - pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), + pci_hole64_size, 1ULL << 31), DEFINE_PROP_UINT32("short_root_bus", I440FXState, short_root_bus, 0), + DEFINE_PROP_BOOL("x-pci-hole64-fix", I440FXState, pci_hole64_fix, true= ), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index ddaa7d1b44..f95337c13a 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -104,11 +104,15 @@ static void q35_host_get_pci_hole64_start(Object *obj= , Visitor *v, Error **errp) { PCIHostState *h =3D PCI_HOST_BRIDGE(obj); + Q35PCIHost *s =3D Q35_HOST_DEVICE(obj); Range w64; uint64_t value; =20 pci_bus_get_w64_range(h->bus, &w64); value =3D range_is_empty(&w64) ? 0 : range_lob(&w64); + if (!value && s->pci_hole64_fix) { + value =3D pc_pci_hole64_start(); + } visit_type_uint64(v, name, &value, errp); } =20 @@ -117,11 +121,16 @@ static void q35_host_get_pci_hole64_end(Object *obj, = Visitor *v, Error **errp) { PCIHostState *h =3D PCI_HOST_BRIDGE(obj); + Q35PCIHost *s =3D Q35_HOST_DEVICE(obj); + uint64_t hole64_start =3D pc_pci_hole64_start(); Range w64; uint64_t value; =20 pci_bus_get_w64_range(h->bus, &w64); value =3D range_is_empty(&w64) ? 0 : range_upb(&w64) + 1; + if (s->pci_hole64_fix && value < (hole64_start + s->mch.pci_hole64_siz= e)) { + value =3D hole64_start + s->mch.pci_hole64_size; + } visit_type_uint64(v, name, &value, errp); } =20 @@ -136,13 +145,15 @@ static void q35_host_get_mmcfg_size(Object *obj, Visi= tor *v, const char *name, static Property q35_host_props[] =3D { DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_ad= dr, MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT), + /* The default value is overriden in q35_host_initfn */ DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost, - mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), + mch.pci_hole64_size, 1ULL << 35), DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0= ), DEFINE_PROP_SIZE(PCI_HOST_BELOW_4G_MEM_SIZE, Q35PCIHost, mch.below_4g_mem_size, 0), DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MEM_SIZE, Q35PCIHost, mch.above_4g_mem_size, 0), + DEFINE_PROP_BOOL("x-pci-hole64-fix", Q35PCIHost, pci_hole64_fix, true), DEFINE_PROP_END_OF_LIST(), }; =20 @@ -174,7 +185,9 @@ static void q35_host_initfn(Object *obj) object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL); qdev_prop_set_int32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0)); qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false); - + /* mch's object_initialize resets the default value, set it again */ + qdev_prop_set_uint64(DEVICE(s), PCI_HOST_PROP_PCI_HOLE64_SIZE, + 1ULL << 35); object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32", q35_host_get_pci_hole_start, NULL, NULL, NULL, NULL); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 087d184ef5..ef438bd765 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -238,7 +238,6 @@ void pc_guest_info_init(PCMachineState *pcms); #define PCI_HOST_PROP_PCI_HOLE64_SIZE "pci-hole64-size" #define PCI_HOST_BELOW_4G_MEM_SIZE "below-4g-mem-size" #define PCI_HOST_ABOVE_4G_MEM_SIZE "above-4g-mem-size" -#define DEFAULT_PCI_HOLE64_SIZE (~0x0ULL) =20 =20 void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory, @@ -249,6 +248,7 @@ void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, MemoryRegion **ram_memory); +uint64_t pc_pci_hole64_start(void); qemu_irq pc_allocate_cpu_irq(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, @@ -375,6 +375,14 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_= t *); .driver =3D TYPE_X86_CPU,\ .property =3D "x-hv-max-vps",\ .value =3D "0x40",\ + },{\ + .driver =3D "i440FX-pcihost",\ + .property =3D "x-pci-hole64-fix",\ + .value =3D "off",\ + },{\ + .driver =3D "q35-pcihost",\ + .property =3D "x-pci-hole64-fix",\ + .value =3D "off",\ }, =20 #define PC_COMPAT_2_9 \ diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index 58983c00b3..8f4ddde393 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -68,6 +68,7 @@ typedef struct Q35PCIHost { PCIExpressHost parent_obj; /*< public >*/ =20 + bool pci_hole64_fix; MCHPCIState mch; } Q35PCIHost; =20 --=20 2.13.5