qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] pci: add romsize property
@ 2020-12-18 18:27 Paolo Bonzini
  2020-12-18 18:54 ` Dr. David Alan Gilbert
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Paolo Bonzini @ 2020-12-18 18:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: dgilbert, mst

This property can be useful for distros to set up known-good ROM sizes for
migration purposes.  The VM will fail to start if the ROM is too large,
and migration compatibility will not be broken if the ROM is too small.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/pci/pci.c             | 19 +++++++++++++++++--
 hw/xen/xen_pt_load_rom.c | 14 ++++++++++++--
 include/hw/pci/pci.h     |  1 +
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index d4349ea577..fd25253c2a 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -67,6 +67,7 @@ static void pcibus_reset(BusState *qbus);
 static Property pci_props[] = {
     DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
     DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
+    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
     DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
     DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
                     QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
@@ -2106,6 +2107,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
     bool is_default_rom;
     uint16_t class_id;
 
+    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
+        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
+        return;
+    }
+
     /* initialize cap_present for pci_is_express() and pci_config_size(),
      * Note that hybrid PCIs are not set automatically and need to manage
      * QEMU_PCI_CAP_EXPRESS manually */
@@ -2366,7 +2372,16 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
         g_free(path);
         return;
     }
-    size = pow2ceil(size);
+    if (pdev->romsize != -1) {
+        if (size > pdev->romsize) {
+            error_setg(errp, "romfile \"%s\" (%d bytes) is too large for ROM size %d",
+                       pdev->romfile, size, pdev->romsize);
+            g_free(path);
+            return;
+        }
+    } else {
+        pdev->romsize = pow2ceil(size);
+    }
 
     vmsd = qdev_get_vmsd(DEVICE(pdev));
 
@@ -2376,7 +2391,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
         snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev)));
     }
     pdev->has_rom = true;
-    memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, size, &error_fatal);
+    memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, pdev->romsize, &error_fatal);
     ptr = memory_region_get_ram_ptr(&pdev->rom);
     if (load_image_size(path, ptr, size) < 0) {
         error_setg(errp, "failed to load romfile \"%s\"", pdev->romfile);
diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c
index a50a80837e..153812f8cd 100644
--- a/hw/xen/xen_pt_load_rom.c
+++ b/hw/xen/xen_pt_load_rom.c
@@ -53,10 +53,20 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev,
     }
     fseek(fp, 0, SEEK_SET);
 
+    if (dev->romsize != -1) {
+        if (st.st_size > dev->romsize) {
+            error_report("ROM BAR \"%s\" (%ld bytes) is too large for ROM size %d",
+                         rom_file, (long) st.st_size, dev->romsize);
+            goto close_rom;
+        }
+    } else {
+        dev->romsize = st.st_size;
+    }
+
     snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));
-    memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);
+    memory_region_init_ram(&dev->rom, owner, name, dev->romsize, &error_abort);
     ptr = memory_region_get_ram_ptr(&dev->rom);
-    memset(ptr, 0xff, st.st_size);
+    memset(ptr, 0xff, dev->romsize);
 
     if (!fread(ptr, 1, st.st_size, fp)) {
         error_report("pci-assign: Cannot read from host %s", rom_file);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 259f9c992d..b028245b62 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -343,6 +343,7 @@ struct PCIDevice {
 
     /* Location of option rom */
     char *romfile;
+    uint32_t romsize;
     bool has_rom;
     MemoryRegion rom;
     uint32_t rom_bar;
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2020-12-18 18:27 [PATCH] pci: add romsize property Paolo Bonzini
@ 2020-12-18 18:54 ` Dr. David Alan Gilbert
  2021-01-19 16:31   ` Peter Xu
  2021-01-19 16:51 ` Philippe Mathieu-Daudé
  2021-01-22 14:30 ` Michael S. Tsirkin
  2 siblings, 1 reply; 10+ messages in thread
From: Dr. David Alan Gilbert @ 2020-12-18 18:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, mst

* Paolo Bonzini (pbonzini@redhat.com) wrote:
> This property can be useful for distros to set up known-good ROM sizes for
> migration purposes.  The VM will fail to start if the ROM is too large,
> and migration compatibility will not be broken if the ROM is too small.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

I suspect something breaks horribly if you set this to the 4GB that the
UINT32 would allow.

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

> ---
>  hw/pci/pci.c             | 19 +++++++++++++++++--
>  hw/xen/xen_pt_load_rom.c | 14 ++++++++++++--
>  include/hw/pci/pci.h     |  1 +
>  3 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index d4349ea577..fd25253c2a 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -67,6 +67,7 @@ static void pcibus_reset(BusState *qbus);
>  static Property pci_props[] = {
>      DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
>      DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
> +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
>      DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
>      DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
>                      QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
> @@ -2106,6 +2107,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>      bool is_default_rom;
>      uint16_t class_id;
>  
> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
> +        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
> +        return;
> +    }
> +
>      /* initialize cap_present for pci_is_express() and pci_config_size(),
>       * Note that hybrid PCIs are not set automatically and need to manage
>       * QEMU_PCI_CAP_EXPRESS manually */
> @@ -2366,7 +2372,16 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
>          g_free(path);
>          return;
>      }
> -    size = pow2ceil(size);
> +    if (pdev->romsize != -1) {
> +        if (size > pdev->romsize) {
> +            error_setg(errp, "romfile \"%s\" (%d bytes) is too large for ROM size %d",
> +                       pdev->romfile, size, pdev->romsize);
> +            g_free(path);
> +            return;
> +        }
> +    } else {
> +        pdev->romsize = pow2ceil(size);
> +    }
>  
>      vmsd = qdev_get_vmsd(DEVICE(pdev));
>  
> @@ -2376,7 +2391,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
>          snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev)));
>      }
>      pdev->has_rom = true;
> -    memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, size, &error_fatal);
> +    memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, pdev->romsize, &error_fatal);
>      ptr = memory_region_get_ram_ptr(&pdev->rom);
>      if (load_image_size(path, ptr, size) < 0) {
>          error_setg(errp, "failed to load romfile \"%s\"", pdev->romfile);
> diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c
> index a50a80837e..153812f8cd 100644
> --- a/hw/xen/xen_pt_load_rom.c
> +++ b/hw/xen/xen_pt_load_rom.c
> @@ -53,10 +53,20 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev,
>      }
>      fseek(fp, 0, SEEK_SET);
>  
> +    if (dev->romsize != -1) {
> +        if (st.st_size > dev->romsize) {
> +            error_report("ROM BAR \"%s\" (%ld bytes) is too large for ROM size %d",
> +                         rom_file, (long) st.st_size, dev->romsize);
> +            goto close_rom;
> +        }
> +    } else {
> +        dev->romsize = st.st_size;
> +    }
> +
>      snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));
> -    memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);
> +    memory_region_init_ram(&dev->rom, owner, name, dev->romsize, &error_abort);
>      ptr = memory_region_get_ram_ptr(&dev->rom);
> -    memset(ptr, 0xff, st.st_size);
> +    memset(ptr, 0xff, dev->romsize);
>  
>      if (!fread(ptr, 1, st.st_size, fp)) {
>          error_report("pci-assign: Cannot read from host %s", rom_file);
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index 259f9c992d..b028245b62 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -343,6 +343,7 @@ struct PCIDevice {
>  
>      /* Location of option rom */
>      char *romfile;
> +    uint32_t romsize;
>      bool has_rom;
>      MemoryRegion rom;
>      uint32_t rom_bar;
> -- 
> 2.26.2
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2020-12-18 18:54 ` Dr. David Alan Gilbert
@ 2021-01-19 16:31   ` Peter Xu
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Xu @ 2021-01-19 16:31 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: Paolo Bonzini, qemu-devel, mst

On Fri, Dec 18, 2020 at 06:54:57PM +0000, Dr. David Alan Gilbert wrote:
> * Paolo Bonzini (pbonzini@redhat.com) wrote:
> > This property can be useful for distros to set up known-good ROM sizes for
> > migration purposes.  The VM will fail to start if the ROM is too large,
> > and migration compatibility will not be broken if the ROM is too small.
> > 
> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> 
> I suspect something breaks horribly if you set this to the 4GB that the
> UINT32 would allow.
> 
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

Indeed, but we do have lots of restrictions (IIUC) in qemu cmdline that it
won't really work if we don't specify things correctly, so I won't worry it too
much, since I assumed qemu cmdline users are advanced users, always. :)

Reviewed-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2020-12-18 18:27 [PATCH] pci: add romsize property Paolo Bonzini
  2020-12-18 18:54 ` Dr. David Alan Gilbert
@ 2021-01-19 16:51 ` Philippe Mathieu-Daudé
  2021-01-19 17:10   ` Paolo Bonzini
                     ` (2 more replies)
  2021-01-22 14:30 ` Michael S. Tsirkin
  2 siblings, 3 replies; 10+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-01-19 16:51 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel, Haibin Zhang, David Edmondson
  Cc: Markus Armbruster, Laszlo Ersek, dgilbert, mst

+pflash

On 12/18/20 7:27 PM, Paolo Bonzini wrote:
> This property can be useful for distros to set up known-good ROM sizes for
> migration purposes.  The VM will fail to start if the ROM is too large,
> and migration compatibility will not be broken if the ROM is too small.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/pci/pci.c             | 19 +++++++++++++++++--
>  hw/xen/xen_pt_load_rom.c | 14 ++++++++++++--
>  include/hw/pci/pci.h     |  1 +
>  3 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index d4349ea577..fd25253c2a 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -67,6 +67,7 @@ static void pcibus_reset(BusState *qbus);
>  static Property pci_props[] = {
>      DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
>      DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
> +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
>      DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
>      DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
>                      QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
> @@ -2106,6 +2107,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>      bool is_default_rom;
>      uint16_t class_id;
>  
> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
> +        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
> +        return;
> +    }

Some cloud providers already complained the pow2 check in the pflash
device (wasting host storage). Personally I find using pow2 easier
and safer.

The pow2 check looks like a separate change however, maybe add in a
separate patch? Or maybe not :)

Regards,

Phil.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2021-01-19 16:51 ` Philippe Mathieu-Daudé
@ 2021-01-19 17:10   ` Paolo Bonzini
  2021-01-19 17:19     ` Philippe Mathieu-Daudé
  2021-01-19 17:20   ` Laszlo Ersek
  2021-01-20 10:14   ` David Edmondson
  2 siblings, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2021-01-19 17:10 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel, Haibin Zhang, David Edmondson
  Cc: Markus Armbruster, Laszlo Ersek, dgilbert, mst

On 19/01/21 17:51, Philippe Mathieu-Daudé wrote:
>> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
>> +        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
>> +        return;
>> +    }
> Some cloud providers already complained the pow2 check in the pflash
> device (wasting host storage). Personally I find using pow2 easier
> and safer.

This check only applies to the value that is specified on the command 
line or in a global property, not to the file (the purpose of the 
property is exactly to override the file size, no matter if the file 
size is a power of two or not).

Even if there is no value for the property, non-power-of-two ROMs files 
are accepted and changed into the next power of two:

	pdev->romsize = pow2ceil(size);

> The pow2 check looks like a separate change however, maybe add in a
> separate patch? Or maybe not:)

Not a separate patch for the above reason: the check is on the 
newly-introduced property.

Paolo



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2021-01-19 17:10   ` Paolo Bonzini
@ 2021-01-19 17:19     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 10+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-01-19 17:19 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel, Haibin Zhang, David Edmondson
  Cc: Markus Armbruster, Laszlo Ersek, dgilbert, mst

On 1/19/21 6:10 PM, Paolo Bonzini wrote:
> On 19/01/21 17:51, Philippe Mathieu-Daudé wrote:
>>> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
>>> +        error_setg(errp, "ROM size %d is not a power of two",
>>> pci_dev->romsize);
>>> +        return;
>>> +    }
>> Some cloud providers already complained the pow2 check in the pflash
>> device (wasting host storage). Personally I find using pow2 easier
>> and safer.
> 
> This check only applies to the value that is specified on the command
> line or in a global property, not to the file (the purpose of the
> property is exactly to override the file size, no matter if the file
> size is a power of two or not).

Doh sorry I completely misunderstood the purpose of the patch.

> Even if there is no value for the property, non-power-of-two ROMs files
> are accepted and changed into the next power of two:
> 
>     pdev->romsize = pow2ceil(size);
> 
>> The pow2 check looks like a separate change however, maybe add in a
>> separate patch? Or maybe not:)
> 
> Not a separate patch for the above reason: the check is on the
> newly-introduced property.

Obviously :)

> 
> Paolo
> 



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2021-01-19 16:51 ` Philippe Mathieu-Daudé
  2021-01-19 17:10   ` Paolo Bonzini
@ 2021-01-19 17:20   ` Laszlo Ersek
  2021-01-22 14:54     ` Paolo Bonzini
  2021-01-20 10:14   ` David Edmondson
  2 siblings, 1 reply; 10+ messages in thread
From: Laszlo Ersek @ 2021-01-19 17:20 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé,
	Paolo Bonzini, qemu-devel, Haibin Zhang, David Edmondson
  Cc: Markus Armbruster, dgilbert, mst

On 01/19/21 17:51, Philippe Mathieu-Daudé wrote:
> +pflash
> 
> On 12/18/20 7:27 PM, Paolo Bonzini wrote:
>> This property can be useful for distros to set up known-good ROM sizes for
>> migration purposes.  The VM will fail to start if the ROM is too large,
>> and migration compatibility will not be broken if the ROM is too small.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>  hw/pci/pci.c             | 19 +++++++++++++++++--
>>  hw/xen/xen_pt_load_rom.c | 14 ++++++++++++--
>>  include/hw/pci/pci.h     |  1 +
>>  3 files changed, 30 insertions(+), 4 deletions(-)
>>
>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>> index d4349ea577..fd25253c2a 100644
>> --- a/hw/pci/pci.c
>> +++ b/hw/pci/pci.c
>> @@ -67,6 +67,7 @@ static void pcibus_reset(BusState *qbus);
>>  static Property pci_props[] = {
>>      DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
>>      DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
>> +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
>>      DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
>>      DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
>>                      QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
>> @@ -2106,6 +2107,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>>      bool is_default_rom;
>>      uint16_t class_id;
>>  
>> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
>> +        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
>> +        return;
>> +    }
> 
> Some cloud providers already complained the pow2 check in the pflash
> device (wasting host storage). Personally I find using pow2 easier
> and safer.
> 
> The pow2 check looks like a separate change however, maybe add in a
> separate patch? Or maybe not :)
> 
> Regards,
> 
> Phil.
> 

I only have superficial comments:

- if we're talking uint32_t, I'd kind of prefer UINT32_MAX to (-1),
style-wise -- but feel free to ignore

- we should print a uint32_t with ("%" PRIu32), not "%d" (again, only
pedantry, but PRIu32 is widely used in qemu, AFAICS)

- Phil: you CC'd me on a context from which the larger part of the patch
had been removed. That's not really useful (I have no idea what the new
property actually does.) Hmmm let me see the patch in qemu-devel...

- OK, so get_image_size() returns an int64_t, which pci_add_option_rom()
assigns to an "int" without any range checking. Then we compare that int
against the new uint32_t property... or else, on the other branch, we
assign pow2ceil() -- a uint64_t -- to the new (uint32_t) property.

- In pci_assign_dev_load_option_rom(), "st.st_size" (which is an off_t)
is assigned to the new property...


I find it hard to reason about whether this is safe. I'd suggest first
cleaning up "int size" in pci_add_option_rom() -- use an int64_t, and
maybe check it explicitly against some 32-bit limit? --, then introduce
the new property as uint64_t. (Print it with PRIu64 then, I guess.) NB
"size" is also passed to pci_patch_ids(), which takes it as an "int" too
(shudder).

BTW there's another aspect of is_power_of_2(): it catches the zero
value. If the power-of-two check is dropped, I wonder if a zero property
value could cause a mess, so it might be prudent to catch that
explicitly. (Precedent: see the (size == 0) check in pci_add_option_rom().)

Anyway, feel free to ignore all of my points; I just find it hard to
reason about the "logic" when the code is not obviously overflow-free in
the first place. (I'm not implying there are overflows; the code may be
free of overflows -- it's just not *obviously* so, to me anyway.)

Thanks
Laszlo



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2021-01-19 16:51 ` Philippe Mathieu-Daudé
  2021-01-19 17:10   ` Paolo Bonzini
  2021-01-19 17:20   ` Laszlo Ersek
@ 2021-01-20 10:14   ` David Edmondson
  2 siblings, 0 replies; 10+ messages in thread
From: David Edmondson @ 2021-01-20 10:14 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Paolo Bonzini, qemu-devel, Haibin Zhang
  Cc: Markus Armbruster, Laszlo Ersek, dgilbert, mst

On Tuesday, 2021-01-19 at 17:51:32 +01, Philippe Mathieu-Daudé wrote:

> +pflash
>
> On 12/18/20 7:27 PM, Paolo Bonzini wrote:
>> This property can be useful for distros to set up known-good ROM sizes for
>> migration purposes.  The VM will fail to start if the ROM is too large,
>> and migration compatibility will not be broken if the ROM is too small.
>> 
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>  hw/pci/pci.c             | 19 +++++++++++++++++--
>>  hw/xen/xen_pt_load_rom.c | 14 ++++++++++++--
>>  include/hw/pci/pci.h     |  1 +
>>  3 files changed, 30 insertions(+), 4 deletions(-)
>> 
>> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
>> index d4349ea577..fd25253c2a 100644
>> --- a/hw/pci/pci.c
>> +++ b/hw/pci/pci.c
>> @@ -67,6 +67,7 @@ static void pcibus_reset(BusState *qbus);
>>  static Property pci_props[] = {
>>      DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
>>      DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
>> +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
>>      DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
>>      DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
>>                      QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
>> @@ -2106,6 +2107,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>>      bool is_default_rom;
>>      uint16_t class_id;
>>  
>> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
>> +        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
>> +        return;
>> +    }
>
> Some cloud providers already complained the pow2 check in the pflash
> device (wasting host storage). Personally I find using pow2 easier
> and safer.
>
> The pow2 check looks like a separate change however, maybe add in a
> separate patch? Or maybe not :)

Even for flash, padding a read-only device seems straightforward.

For a writable device, is it assumed that a write into the padding
should extend the file?

(I realise that this patch is just for the ROM.)

dme.
-- 
You bring light in.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2020-12-18 18:27 [PATCH] pci: add romsize property Paolo Bonzini
  2020-12-18 18:54 ` Dr. David Alan Gilbert
  2021-01-19 16:51 ` Philippe Mathieu-Daudé
@ 2021-01-22 14:30 ` Michael S. Tsirkin
  2 siblings, 0 replies; 10+ messages in thread
From: Michael S. Tsirkin @ 2021-01-22 14:30 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, dgilbert

On Fri, Dec 18, 2020 at 01:27:36PM -0500, Paolo Bonzini wrote:
> This property can be useful for distros to set up known-good ROM sizes for
> migration purposes.  The VM will fail to start if the ROM is too large,
> and migration compatibility will not be broken if the ROM is too small.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/pci/pci.c             | 19 +++++++++++++++++--
>  hw/xen/xen_pt_load_rom.c | 14 ++++++++++++--
>  include/hw/pci/pci.h     |  1 +
>  3 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index d4349ea577..fd25253c2a 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -67,6 +67,7 @@ static void pcibus_reset(BusState *qbus);
>  static Property pci_props[] = {
>      DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
>      DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
> +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
>      DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
>      DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
>                      QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),


Would a size32 property be better? E.g. 4k is nicer than 4096 ...

> @@ -2106,6 +2107,11 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
>      bool is_default_rom;
>      uint16_t class_id;
>  
> +    if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) {
> +        error_setg(errp, "ROM size %d is not a power of two", pci_dev->romsize);
> +        return;
> +    }
> +
>      /* initialize cap_present for pci_is_express() and pci_config_size(),
>       * Note that hybrid PCIs are not set automatically and need to manage
>       * QEMU_PCI_CAP_EXPRESS manually */
> @@ -2366,7 +2372,16 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
>          g_free(path);
>          return;
>      }
> -    size = pow2ceil(size);
> +    if (pdev->romsize != -1) {
> +        if (size > pdev->romsize) {
> +            error_setg(errp, "romfile \"%s\" (%d bytes) is too large for ROM size %d",
> +                       pdev->romfile, size, pdev->romsize);
> +            g_free(path);
> +            return;
> +        }
> +    } else {
> +        pdev->romsize = pow2ceil(size);
> +    }
>  
>      vmsd = qdev_get_vmsd(DEVICE(pdev));
>  
> @@ -2376,7 +2391,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom,
>          snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev)));
>      }
>      pdev->has_rom = true;
> -    memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, size, &error_fatal);
> +    memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, pdev->romsize, &error_fatal);
>      ptr = memory_region_get_ram_ptr(&pdev->rom);
>      if (load_image_size(path, ptr, size) < 0) {
>          error_setg(errp, "failed to load romfile \"%s\"", pdev->romfile);
> diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c
> index a50a80837e..153812f8cd 100644
> --- a/hw/xen/xen_pt_load_rom.c
> +++ b/hw/xen/xen_pt_load_rom.c
> @@ -53,10 +53,20 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev,
>      }
>      fseek(fp, 0, SEEK_SET);
>  
> +    if (dev->romsize != -1) {
> +        if (st.st_size > dev->romsize) {
> +            error_report("ROM BAR \"%s\" (%ld bytes) is too large for ROM size %d",
> +                         rom_file, (long) st.st_size, dev->romsize);
> +            goto close_rom;
> +        }
> +    } else {
> +        dev->romsize = st.st_size;
> +    }
> +
>      snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));
> -    memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);
> +    memory_region_init_ram(&dev->rom, owner, name, dev->romsize, &error_abort);
>      ptr = memory_region_get_ram_ptr(&dev->rom);
> -    memset(ptr, 0xff, st.st_size);
> +    memset(ptr, 0xff, dev->romsize);
>  
>      if (!fread(ptr, 1, st.st_size, fp)) {
>          error_report("pci-assign: Cannot read from host %s", rom_file);
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index 259f9c992d..b028245b62 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -343,6 +343,7 @@ struct PCIDevice {
>  
>      /* Location of option rom */
>      char *romfile;
> +    uint32_t romsize;
>      bool has_rom;
>      MemoryRegion rom;
>      uint32_t rom_bar;
> -- 
> 2.26.2



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] pci: add romsize property
  2021-01-19 17:20   ` Laszlo Ersek
@ 2021-01-22 14:54     ` Paolo Bonzini
  0 siblings, 0 replies; 10+ messages in thread
From: Paolo Bonzini @ 2021-01-22 14:54 UTC (permalink / raw)
  To: Laszlo Ersek, Philippe Mathieu-Daudé,
	qemu-devel, Haibin Zhang, David Edmondson
  Cc: mst, Markus Armbruster, dgilbert

On 19/01/21 18:20, Laszlo Ersek wrote:
> I only have superficial comments:
> 
> - if we're talking uint32_t, I'd kind of prefer UINT32_MAX to (-1),
> style-wise -- but feel free to ignore
> 
> - we should print a uint32_t with ("%" PRIu32), not "%d" (again, only
> pedantry, but PRIu32 is widely used in qemu, AFAICS)

I would use %u, but yeah you're correct.

> - OK, so get_image_size() returns an int64_t, which pci_add_option_rom()
> assigns to an "int" without any range checking.

This is pre-existing, but it should be fixed indeed.

> Then we compare that int
> against the new uint32_t property... or else, on the other branch, we
> assign pow2ceil() -- a uint64_t -- to the new (uint32_t) property.
> 
> - In pci_assign_dev_load_option_rom(), "st.st_size" (which is an off_t)
> is assigned to the new property...
> 
> 
> I find it hard to reason about whether this is safe. I'd suggest first
> cleaning up "int size" in pci_add_option_rom() -- use an int64_t, and
> maybe check it explicitly against some 32-bit limit? --, then introduce
> the new property as uint64_t. (Print it with PRIu64 then, I guess.)

ROM BARs cannot be 64-bit in size.  There's just no room in 
configuration space for that.  Anyway yes pci_add_option_rom() is iffy 
and I'll send v2.

Paolo

> BTW there's another aspect of is_power_of_2(): it catches the zero
> value. If the power-of-two check is dropped, I wonder if a zero property
> value could cause a mess, so it might be prudent to catch that
> explicitly. (Precedent: see the (size == 0) check in pci_add_option_rom().)
> 
> Anyway, feel free to ignore all of my points; I just find it hard to
> reason about the "logic" when the code is not obviously overflow-free in
> the first place. (I'm not implying there are overflows; the code may be
> free of overflows -- it's just not*obviously*  so, to me anyway.)



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-01-22 14:56 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-18 18:27 [PATCH] pci: add romsize property Paolo Bonzini
2020-12-18 18:54 ` Dr. David Alan Gilbert
2021-01-19 16:31   ` Peter Xu
2021-01-19 16:51 ` Philippe Mathieu-Daudé
2021-01-19 17:10   ` Paolo Bonzini
2021-01-19 17:19     ` Philippe Mathieu-Daudé
2021-01-19 17:20   ` Laszlo Ersek
2021-01-22 14:54     ` Paolo Bonzini
2021-01-20 10:14   ` David Edmondson
2021-01-22 14:30 ` Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).