Re: [Qemu-devel] [PATCH V5] hw/pci-host: Fix x86 Host Bridges 64bit PCI hole

2017-11-15 Thread Marcel Apfelbaum

On 15/11/2017 4:16, Michael S. Tsirkin wrote:

On Mon, Nov 13, 2017 at 03:07:45PM +0200, Marcel Apfelbaum wrote:

On 11/11/2017 17:25, Marcel Apfelbaum wrote:

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.

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.

Note this is a regression since prev QEMU versions had
some range reserved for 64bit PCI hotplug.

Reviewed-by: Laszlo Ersek 
Reviewed-by: Gerd Hoffmann 
Signed-off-by: Marcel Apfelbaum 
---



Hi Michael,

Can you please merge the patch for QEMU 2.11
if you have no further comments?
I think is an important fix and it worth
having it in 2.11 .

Thanks,
Marcel




Hi Michael,


Just a note: this changes the DSDT to use
QWordMemory in the _CRS.

I expected it to cause trouble for old windows such as winXP
but it does not seem to cause them - at least not boot crashes.

Worth checking that 32 bit hotplug still works though.
Could you pls confirm?



I installed a fresh WinXpSp3 32bit image and I can confirm
there is no issue with both the installation and
PCI hotplug/hot-unplug of a E1000 NIC.

Thanks,
Marcel


V4 -> V5:
   - Renamed a local variable (Laszlo)
   - Added a comment to q35 props (Eduardo)

V3 -> V4:
   - Addressed Laszlo's comments:
  - Added defines for pci-hole64 default size props.
  - Rounded the hole64_end to 1G
  - Moved some info to commit message
   - Addressed Michael's comments:
  - Added more comments.
   - I kept Gerd's "review-by" tag since no functional changes were made.

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"

   hw/i386/pc.c  | 22 ++
   hw/pci-host/piix.c| 32 ++--
   hw/pci-host/q35.c | 42 +++---
   include/hw/i386/pc.h  | 10 +-
   include/hw/pci-host/q35.h |  1 +
   5 files changed, 101 insertions(+), 6 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e11a65b545..fafe5ba5cd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1448,6 +1448,28 @@ void pc_memory_init(PCMachineState *pcms,
   pcms->ioapic_as = _space_memory;
   }
+/*
+ * The 64bit pci hole starts after "above 4G RAM" and
+ * potentially the space reserved for memory hotplug.
+ */
+uint64_t pc_pci_hole64_start(void)
+{
+PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+uint64_t hole64_start = 0;
+
+if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
+hole64_start = pcms->hotplug_memory.base;
+if (!pcmc->broken_reserved_end) {
+hole64_start += memory_region_size(>hotplug_memory.mr);
+}
+} else {
+hole64_start = 0x1ULL + 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..a684a7cca9 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;
@@ -112,6 +113,9 @@ struct PCII440FXState {
   #define I440FX_PAM_SIZE 7
   #define I440FX_SMRAM0x72
+/* Keep it 2G to comply with older win32 guests */
+#define I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 31)
+
   /* Older coreboot versions (4.0 and older) read a config register that 
doesn't
* exist in real hardware, to get the RAM size from QEMU.
*/
@@ -238,29 +242,52 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, 
Visitor *v,
   visit_type_uint32(v, name, , errp);
   }
+/*
+ * The 64bit PCI hole start is set by the Guest firmware
+ * as the address of the first 64bit PCI MEM resource.
+ * If no PCI device has resources on the 64bit area,
+ * the 64bit PCI hole will start after "over 4G RAM" and the
+ * reserved 

Re: [Qemu-devel] [PATCH V5] hw/pci-host: Fix x86 Host Bridges 64bit PCI hole

2017-11-14 Thread Michael S. Tsirkin
On Mon, Nov 13, 2017 at 03:07:45PM +0200, Marcel Apfelbaum wrote:
> On 11/11/2017 17:25, Marcel Apfelbaum wrote:
> > 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.
> > 
> > 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.
> > 
> > Note this is a regression since prev QEMU versions had
> > some range reserved for 64bit PCI hotplug.
> > 
> > Reviewed-by: Laszlo Ersek 
> > Reviewed-by: Gerd Hoffmann 
> > Signed-off-by: Marcel Apfelbaum 
> > ---
> > 
> 
> Hi Michael,
> 
> Can you please merge the patch for QEMU 2.11
> if you have no further comments?
> I think is an important fix and it worth
> having it in 2.11 .
> 
> Thanks,
> Marcel

Just a note: this changes the DSDT to use
QWordMemory in the _CRS.

I expected it to cause trouble for old windows such as winXP
but it does not seem to cause them - at least not boot crashes.

Worth checking that 32 bit hotplug still works though.
Could you pls confirm?

> > V4 -> V5:
> >   - Renamed a local variable (Laszlo)
> >   - Added a comment to q35 props (Eduardo)
> > 
> > V3 -> V4:
> >   - Addressed Laszlo's comments:
> >  - Added defines for pci-hole64 default size props.
> >  - Rounded the hole64_end to 1G
> >  - Moved some info to commit message
> >   - Addressed Michael's comments:
> >  - Added more comments.
> >   - I kept Gerd's "review-by" tag since no functional changes were made.
> > 
> > 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"
> > 
> >   hw/i386/pc.c  | 22 ++
> >   hw/pci-host/piix.c| 32 ++--
> >   hw/pci-host/q35.c | 42 +++---
> >   include/hw/i386/pc.h  | 10 +-
> >   include/hw/pci-host/q35.h |  1 +
> >   5 files changed, 101 insertions(+), 6 deletions(-)
> > 
> > diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> > index e11a65b545..fafe5ba5cd 100644
> > --- a/hw/i386/pc.c
> > +++ b/hw/i386/pc.c
> > @@ -1448,6 +1448,28 @@ void pc_memory_init(PCMachineState *pcms,
> >   pcms->ioapic_as = _space_memory;
> >   }
> > +/*
> > + * The 64bit pci hole starts after "above 4G RAM" and
> > + * potentially the space reserved for memory hotplug.
> > + */
> > +uint64_t pc_pci_hole64_start(void)
> > +{
> > +PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
> > +PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> > +uint64_t hole64_start = 0;
> > +
> > +if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
> > +hole64_start = pcms->hotplug_memory.base;
> > +if (!pcmc->broken_reserved_end) {
> > +hole64_start += memory_region_size(>hotplug_memory.mr);
> > +}
> > +} else {
> > +hole64_start = 0x1ULL + 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..a684a7cca9 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;
> > @@ -112,6 +113,9 @@ struct PCII440FXState {
> >   #define I440FX_PAM_SIZE 7
> >   #define I440FX_SMRAM0x72
> > +/* Keep it 2G to comply with older win32 guests */
> > +#define I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 31)
> > +
> >   /* Older coreboot versions (4.0 and older) read a config register that 
> > doesn't
> >* exist in real hardware, to get the RAM size from QEMU.
> >*/
> > @@ -238,29 +242,52 @@ static void i440fx_pcihost_get_pci_hole_end(Object 
> > *obj, Visitor *v,
> >   visit_type_uint32(v, name, , errp);
> >   }
> > +/*
> > + * The 64bit PCI hole start is set by the 

Re: [Qemu-devel] [PATCH V5] hw/pci-host: Fix x86 Host Bridges 64bit PCI hole

2017-11-13 Thread Marcel Apfelbaum

On 11/11/2017 17:25, Marcel Apfelbaum wrote:

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.

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.

Note this is a regression since prev QEMU versions had
some range reserved for 64bit PCI hotplug.

Reviewed-by: Laszlo Ersek 
Reviewed-by: Gerd Hoffmann 
Signed-off-by: Marcel Apfelbaum 
---



Hi Michael,

Can you please merge the patch for QEMU 2.11
if you have no further comments?
I think is an important fix and it worth
having it in 2.11 .

Thanks,
Marcel


V4 -> V5:
  - Renamed a local variable (Laszlo)
  - Added a comment to q35 props (Eduardo)

V3 -> V4:
  - Addressed Laszlo's comments:
 - Added defines for pci-hole64 default size props.
 - Rounded the hole64_end to 1G
 - Moved some info to commit message
  - Addressed Michael's comments:
 - Added more comments.
  - I kept Gerd's "review-by" tag since no functional changes were made.

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"

  hw/i386/pc.c  | 22 ++
  hw/pci-host/piix.c| 32 ++--
  hw/pci-host/q35.c | 42 +++---
  include/hw/i386/pc.h  | 10 +-
  include/hw/pci-host/q35.h |  1 +
  5 files changed, 101 insertions(+), 6 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e11a65b545..fafe5ba5cd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1448,6 +1448,28 @@ void pc_memory_init(PCMachineState *pcms,
  pcms->ioapic_as = _space_memory;
  }
  
+/*

+ * The 64bit pci hole starts after "above 4G RAM" and
+ * potentially the space reserved for memory hotplug.
+ */
+uint64_t pc_pci_hole64_start(void)
+{
+PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+uint64_t hole64_start = 0;
+
+if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
+hole64_start = pcms->hotplug_memory.base;
+if (!pcmc->broken_reserved_end) {
+hole64_start += memory_region_size(>hotplug_memory.mr);
+}
+} else {
+hole64_start = 0x1ULL + 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..a684a7cca9 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;
  
@@ -112,6 +113,9 @@ struct PCII440FXState {

  #define I440FX_PAM_SIZE 7
  #define I440FX_SMRAM0x72
  
+/* Keep it 2G to comply with older win32 guests */

+#define I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 31)
+
  /* Older coreboot versions (4.0 and older) read a config register that doesn't
   * exist in real hardware, to get the RAM size from QEMU.
   */
@@ -238,29 +242,52 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, 
Visitor *v,
  visit_type_uint32(v, name, , errp);
  }
  
+/*

+ * The 64bit PCI hole start is set by the Guest firmware
+ * as the address of the first 64bit PCI MEM resource.
+ * If no PCI device has resources on the 64bit area,
+ * the 64bit PCI hole will start after "over 4G RAM" and the
+ * reserved space for memory hotplug if any.
+ */
  static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
  const char *name,
  void *opaque, Error **errp)
  {
  PCIHostState *h = PCI_HOST_BRIDGE(obj);
+I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
  Range w64;
  uint64_t value;
  
  pci_bus_get_w64_range(h->bus, );

  value = range_is_empty() ? 0 : range_lob();
+if (!value && s->pci_hole64_fix) {
+value = pc_pci_hole64_start();
+}
  

Re: [Qemu-devel] [PATCH V5] hw/pci-host: Fix x86 Host Bridges 64bit PCI hole

2017-11-13 Thread Laszlo Ersek
On 11/11/17 16:25, Marcel Apfelbaum wrote:
> 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.
> 
> 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.
> 
> Note this is a regression since prev QEMU versions had
> some range reserved for 64bit PCI hotplug.
> 
> Reviewed-by: Laszlo Ersek 
> Reviewed-by: Gerd Hoffmann 
> Signed-off-by: Marcel Apfelbaum 
> ---
> 
> V4 -> V5:
>  - Renamed a local variable (Laszlo)
>  - Added a comment to q35 props (Eduardo)

Looks good to me, thank you.

Laszlo

> 
> V3 -> V4:
>  - Addressed Laszlo's comments:
> - Added defines for pci-hole64 default size props.
> - Rounded the hole64_end to 1G
> - Moved some info to commit message
>  - Addressed Michael's comments:
> - Added more comments.
>  - I kept Gerd's "review-by" tag since no functional changes were made.
> 
> 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"
> 
>  hw/i386/pc.c  | 22 ++
>  hw/pci-host/piix.c| 32 ++--
>  hw/pci-host/q35.c | 42 +++---
>  include/hw/i386/pc.h  | 10 +-
>  include/hw/pci-host/q35.h |  1 +
>  5 files changed, 101 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index e11a65b545..fafe5ba5cd 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -1448,6 +1448,28 @@ void pc_memory_init(PCMachineState *pcms,
>  pcms->ioapic_as = _space_memory;
>  }
>  
> +/*
> + * The 64bit pci hole starts after "above 4G RAM" and
> + * potentially the space reserved for memory hotplug.
> + */
> +uint64_t pc_pci_hole64_start(void)
> +{
> +PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
> +PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +uint64_t hole64_start = 0;
> +
> +if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
> +hole64_start = pcms->hotplug_memory.base;
> +if (!pcmc->broken_reserved_end) {
> +hole64_start += memory_region_size(>hotplug_memory.mr);
> +}
> +} else {
> +hole64_start = 0x1ULL + 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..a684a7cca9 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;
>  
> @@ -112,6 +113,9 @@ struct PCII440FXState {
>  #define I440FX_PAM_SIZE 7
>  #define I440FX_SMRAM0x72
>  
> +/* Keep it 2G to comply with older win32 guests */
> +#define I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 31)
> +
>  /* Older coreboot versions (4.0 and older) read a config register that 
> doesn't
>   * exist in real hardware, to get the RAM size from QEMU.
>   */
> @@ -238,29 +242,52 @@ static void i440fx_pcihost_get_pci_hole_end(Object 
> *obj, Visitor *v,
>  visit_type_uint32(v, name, , errp);
>  }
>  
> +/*
> + * The 64bit PCI hole start is set by the Guest firmware
> + * as the address of the first 64bit PCI MEM resource.
> + * If no PCI device has resources on the 64bit area,
> + * the 64bit PCI hole will start after "over 4G RAM" and the
> + * reserved space for memory hotplug if any.
> + */
>  static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
>  const char *name,
>  void *opaque, Error **errp)
>  {
>  PCIHostState *h = PCI_HOST_BRIDGE(obj);
> +I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
>  Range w64;
>  uint64_t value;
>  
>  pci_bus_get_w64_range(h->bus, );
>  value = range_is_empty() ? 0 : range_lob();
> +if (!value && 

[Qemu-devel] [PATCH V5] hw/pci-host: Fix x86 Host Bridges 64bit PCI hole

2017-11-11 Thread Marcel Apfelbaum
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.

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.

Note this is a regression since prev QEMU versions had
some range reserved for 64bit PCI hotplug.

Reviewed-by: Laszlo Ersek 
Reviewed-by: Gerd Hoffmann 
Signed-off-by: Marcel Apfelbaum 
---

V4 -> V5:
 - Renamed a local variable (Laszlo)
 - Added a comment to q35 props (Eduardo)

V3 -> V4:
 - Addressed Laszlo's comments:
- Added defines for pci-hole64 default size props.
- Rounded the hole64_end to 1G
- Moved some info to commit message
 - Addressed Michael's comments:
- Added more comments.
 - I kept Gerd's "review-by" tag since no functional changes were made.

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"

 hw/i386/pc.c  | 22 ++
 hw/pci-host/piix.c| 32 ++--
 hw/pci-host/q35.c | 42 +++---
 include/hw/i386/pc.h  | 10 +-
 include/hw/pci-host/q35.h |  1 +
 5 files changed, 101 insertions(+), 6 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e11a65b545..fafe5ba5cd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1448,6 +1448,28 @@ void pc_memory_init(PCMachineState *pcms,
 pcms->ioapic_as = _space_memory;
 }
 
+/*
+ * The 64bit pci hole starts after "above 4G RAM" and
+ * potentially the space reserved for memory hotplug.
+ */
+uint64_t pc_pci_hole64_start(void)
+{
+PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+uint64_t hole64_start = 0;
+
+if (pcmc->has_reserved_memory && pcms->hotplug_memory.base) {
+hole64_start = pcms->hotplug_memory.base;
+if (!pcmc->broken_reserved_end) {
+hole64_start += memory_region_size(>hotplug_memory.mr);
+}
+} else {
+hole64_start = 0x1ULL + 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..a684a7cca9 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;
 
@@ -112,6 +113,9 @@ struct PCII440FXState {
 #define I440FX_PAM_SIZE 7
 #define I440FX_SMRAM0x72
 
+/* Keep it 2G to comply with older win32 guests */
+#define I440FX_PCI_HOST_HOLE64_SIZE_DEFAULT (1ULL << 31)
+
 /* Older coreboot versions (4.0 and older) read a config register that doesn't
  * exist in real hardware, to get the RAM size from QEMU.
  */
@@ -238,29 +242,52 @@ static void i440fx_pcihost_get_pci_hole_end(Object *obj, 
Visitor *v,
 visit_type_uint32(v, name, , errp);
 }
 
+/*
+ * The 64bit PCI hole start is set by the Guest firmware
+ * as the address of the first 64bit PCI MEM resource.
+ * If no PCI device has resources on the 64bit area,
+ * the 64bit PCI hole will start after "over 4G RAM" and the
+ * reserved space for memory hotplug if any.
+ */
 static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
 const char *name,
 void *opaque, Error **errp)
 {
 PCIHostState *h = PCI_HOST_BRIDGE(obj);
+I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
 Range w64;
 uint64_t value;
 
 pci_bus_get_w64_range(h->bus, );
 value = range_is_empty() ? 0 : range_lob();
+if (!value && s->pci_hole64_fix) {
+value = pc_pci_hole64_start();
+}
 visit_type_uint64(v, name, , errp);
 }
 
+/*
+ * The 64bit PCI hole end is set by the Guest firmware
+ * as the address of the last 64bit PCI MEM resource.
+ * Then it is expanded to the PCI_HOST_PROP_PCI_HOLE64_SIZE
+ * that can be configured by the user.
+ */
 static void