[PATCH v2 2/2] pci: add romsize property

Paolo Bonzini posted 2 patches 4 years, 9 months ago
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Paul Durrant <paul@xen.org>, Stefano Stabellini <sstabellini@kernel.org>, Anthony Perard <anthony.perard@citrix.com>
There is a newer version of this series
[PATCH v2 2/2] pci: add romsize property
Posted by Paolo Bonzini 4 years, 9 months ago
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.

Note that even though romsize is a uint32_t, it has to be between 1
(because empty ROM files are not accepted, and romsize must be greater
than the file) and 2^31 (because values above are not powers of two and
are rejected).

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
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 bbce10050b..5b3fe3c294 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -68,6 +68,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),
@@ -2107,6 +2108,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 */
@@ -2372,7 +2378,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\" (%u bytes) is too large for ROM size %u",
+                       pdev->romfile, (uint32_t)size, pdev->romsize);
+            g_free(path);
+            return;
+        }
+    } else {
+        pdev->romsize = pow2ceil(size);
+    }
 
     vmsd = qdev_get_vmsd(DEVICE(pdev));
 
@@ -2382,7 +2397,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.29.2


Re: [PATCH v2 2/2] pci: add romsize property
Posted by Gerd Hoffmann 4 years, 9 months ago
  Hi,

> +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),

IIRC we have a DEFINE_PROP_SIZE() which can parse units and therefore
accepts -- for example -- "512k" or "1M".

take care,
  Gerd


Re: [PATCH v2 2/2] pci: add romsize property
Posted by Peter Xu 4 years, 9 months ago
On Mon, Feb 01, 2021 at 08:56:32AM +0100, Gerd Hoffmann wrote:
>   Hi,
> 
> > +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
> 
> IIRC we have a DEFINE_PROP_SIZE() which can parse units and therefore
> accepts -- for example -- "512k" or "1M".

Actually IMHO there's some fair point to make it uint32: even 1 byte would
matter here or migration fails.  Hence, we don't need to worry about things
like 512KB or 512KiB, for example.

Not to mention that I bet 99.99% qemu users won't really use this parameter,
only if we'd migrate across distros.  That's rare, we'd copy the exact byte
value of the source ROM size here (e.g. via "info ramblock", or "ls -l" the
romfile then round to pow2 and specify on dest) or we simply copy this param
over from another source VM.

Thanks,

-- 
Peter Xu


Re: [PATCH v2 2/2] pci: add romsize property
Posted by Dr. David Alan Gilbert 4 years, 9 months ago
* Peter Xu (peterx@redhat.com) wrote:
> On Mon, Feb 01, 2021 at 08:56:32AM +0100, Gerd Hoffmann wrote:
> >   Hi,
> > 
> > > +    DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1),
> > 
> > IIRC we have a DEFINE_PROP_SIZE() which can parse units and therefore
> > accepts -- for example -- "512k" or "1M".
> 
> Actually IMHO there's some fair point to make it uint32: even 1 byte would
> matter here or migration fails.  Hence, we don't need to worry about things
> like 512KB or 512KiB, for example.
> 
> Not to mention that I bet 99.99% qemu users won't really use this parameter,
> only if we'd migrate across distros.  That's rare, we'd copy the exact byte
> value of the source ROM size here (e.g. via "info ramblock", or "ls -l" the
> romfile then round to pow2 and specify on dest) or we simply copy this param
> over from another source VM.

Well, we should sometime, set it for the default upstream machine types,
so that distros get a better chance of getting their rom images right
and consistent.

Dave

> Thanks,
> 
> -- 
> Peter Xu
> 
-- 
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK


Re: [PATCH v2 2/2] pci: add romsize property
Posted by David Edmondson 4 years, 9 months ago
On Friday, 2021-01-29 at 20:28:38 +01, 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.
>
> Note that even though romsize is a uint32_t, it has to be between 1
> (because empty ROM files are not accepted, and romsize must be greater
> than the file) and 2^31 (because values above are not powers of two and
> are rejected).
>
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Reviewed-by: Peter Xu <peterx@redhat.com>
> 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 bbce10050b..5b3fe3c294 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -68,6 +68,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),
> @@ -2107,6 +2108,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;

It would be nice to be consistent with the format type when reporting
errors - it's %d here...

> +    }
> +
>      /* 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 */
> @@ -2372,7 +2378,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\" (%u bytes) is too large for ROM size %u",
> +                       pdev->romfile, (uint32_t)size, pdev->romsize);

%u here...

> +            g_free(path);
> +            return;
> +        }
> +    } else {
> +        pdev->romsize = pow2ceil(size);
> +    }
>  
>      vmsd = qdev_get_vmsd(DEVICE(pdev));
>  
> @@ -2382,7 +2397,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",

%d here...

> +                         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.29.2

dme.
-- 
Tell her I'll be waiting, in the usual place.

Re: [PATCH v2 2/2] pci: add romsize property
Posted by Laszlo Ersek 4 years, 9 months ago
On 02/02/21 11:05, David Edmondson wrote:
> On Friday, 2021-01-29 at 20:28:38 +01, 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.
>>
>> Note that even though romsize is a uint32_t, it has to be between 1
>> (because empty ROM files are not accepted, and romsize must be greater
>> than the file) and 2^31 (because values above are not powers of two and
>> are rejected).
>>
>> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Reviewed-by: Peter Xu <peterx@redhat.com>
>> 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 bbce10050b..5b3fe3c294 100644
>> --- a/hw/pci/pci.c
>> +++ b/hw/pci/pci.c
>> @@ -68,6 +68,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),
>> @@ -2107,6 +2108,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;
> 
> It would be nice to be consistent with the format type when reporting
> errors - it's %d here...
> 
>> +    }
>> +
>>      /* 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 */
>> @@ -2372,7 +2378,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\" (%u bytes) is too large for ROM size %u",
>> +                       pdev->romfile, (uint32_t)size, pdev->romsize);
> 
> %u here...
> 
>> +            g_free(path);
>> +            return;
>> +        }
>> +    } else {
>> +        pdev->romsize = pow2ceil(size);
>> +    }
>>  
>>      vmsd = qdev_get_vmsd(DEVICE(pdev));
>>  
>> @@ -2382,7 +2397,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",
> 
> %d here...
> 
>> +                         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.29.2
> 
> dme.
> 

I believe this may be worth a v3; for that:

Acked-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo


Re: [PATCH v2 2/2] pci: add romsize property
Posted by BALATON Zoltan 4 years, 9 months ago
On Fri, 29 Jan 2021, 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.
>
> Note that even though romsize is a uint32_t, it has to be between 1
> (because empty ROM files are not accepted, and romsize must be greater
> than the file) and 2^31 (because values above are not powers of two and
> are rejected).

I've found I have to use this command to disable vgabios-ati.bin:

qemu-system-ppc -M sam460ex -device ati-vga,romfile=""

otherwise the BIOS emulator in the guest firmware crashes and this works 
so I think romfile can be empty and it's a useful feature to have in this 
case for example. I don't know if this patch changes anything about that 
but the commit message saying that romfile cannot be empty may be wrong.

Regards,
BALATON Zoltan

> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Reviewed-by: Peter Xu <peterx@redhat.com>
> 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 bbce10050b..5b3fe3c294 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -68,6 +68,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),
> @@ -2107,6 +2108,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 */
> @@ -2372,7 +2378,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\" (%u bytes) is too large for ROM size %u",
> +                       pdev->romfile, (uint32_t)size, pdev->romsize);
> +            g_free(path);
> +            return;
> +        }
> +    } else {
> +        pdev->romsize = pow2ceil(size);
> +    }
>
>     vmsd = qdev_get_vmsd(DEVICE(pdev));
>
> @@ -2382,7 +2397,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;
>

Re: [PATCH v2 2/2] pci: add romsize property
Posted by Paolo Bonzini 4 years, 9 months ago
On 29/01/21 20:51, BALATON Zoltan wrote:
> otherwise the BIOS emulator in the guest firmware crashes and this works 
> so I think romfile can be empty and it's a useful feature to have in 
> this case for example. I don't know if this patch changes anything about 
> that but the commit message saying that romfile cannot be empty may be 
> wrong.

The empty property value configures the device not to have a ROM file at 
all.  The commit message says that ROM files (if they exist) cannot be 
empty, corresponding to this code in pci_add_option_rom:

     } else if (size == 0) {
         error_setg(errp, "romfile \"%s\" is empty", pdev->romfile);
         g_free(path);
         return;
     }

Paolo


Re: [PATCH v2 2/2] pci: add romsize property
Posted by BALATON Zoltan 4 years, 9 months ago
On Fri, 29 Jan 2021, Paolo Bonzini wrote:
> On 29/01/21 20:51, BALATON Zoltan wrote:
>> otherwise the BIOS emulator in the guest firmware crashes and this works so 
>> I think romfile can be empty and it's a useful feature to have in this case 
>> for example. I don't know if this patch changes anything about that but the 
>> commit message saying that romfile cannot be empty may be wrong.
>
> The empty property value configures the device not to have a ROM file at all. 
> The commit message says that ROM files (if they exist) cannot be empty, 
> corresponding to this code in pci_add_option_rom:
>
>    } else if (size == 0) {
>        error_setg(errp, "romfile \"%s\" is empty", pdev->romfile);
>        g_free(path);
>        return;
>    }

OK, then it was just not clear to me that the commit message talks about 
the romfile itself and not the property.

By the way, does it make sense to compare uint32_t value to -1 and could 
that provoke some compiler/sanitiser warnings? Is it better to have a 
signed type or use UINT32_MAX or simlar instead?

Regards,
BALATON Zoltan

Re: [PATCH v2 2/2] pci: add romsize property
Posted by Paolo Bonzini 4 years, 9 months ago
On 29/01/21 21:06, BALATON Zoltan wrote:
>> The empty property value configures the device not to have a ROM file 
>> at all. The commit message says that ROM files (if they exist) cannot 
>> be empty, corresponding to this code in pci_add_option_rom:
>>
>>    } else if (size == 0) {
>>        error_setg(errp, "romfile \"%s\" is empty", pdev->romfile);
>>        g_free(path);
>>        return;
>>    }
> 
> OK, then it was just not clear to me that the commit message talks about 
> the romfile itself and not the property.
> 
> By the way, does it make sense to compare uint32_t value to -1 and could 
> that provoke some compiler/sanitiser warnings? Is it better to have a 
> signed type or use UINT32_MAX or simlar instead?

There is probably some warning for it but I think not even -Wextra 
enables it by default.

Paolo