diff mbox series

[2/2] add maximum combined fw size as machine configuration option

Message ID 20200918042339.3477-1-erich.mcmillan@hp.com
State New
Headers show
Series None | expand

Commit Message

Erich Mcmillan Sept. 18, 2020, 4:23 a.m. UTC
From: Erich McMillan <erich.mcmillan@hp.com>

Signed-off-by: Erich McMillan <erich.mcmillan@hp.com>
---
 hw/i386/pc.c         | 40 ++++++++++++++++++++++++++++++++++++++++
 hw/i386/pc_sysfw.c   | 13 ++-----------
 include/hw/i386/pc.h | 22 ++++++++++++----------
 3 files changed, 54 insertions(+), 21 deletions(-)

Comments

Philippe Mathieu-Daudé Sept. 18, 2020, 8:17 a.m. UTC | #1
Hi Erich,

On 9/18/20 6:23 AM, Erich Mcmillan wrote:
> From: Erich McMillan <erich.mcmillan@hp.com>

Description/rationale?

> 
> Signed-off-by: Erich McMillan <erich.mcmillan@hp.com>
> ---
>  hw/i386/pc.c         | 40 ++++++++++++++++++++++++++++++++++++++++
>  hw/i386/pc_sysfw.c   | 13 ++-----------
>  include/hw/i386/pc.h | 22 ++++++++++++----------
>  3 files changed, 54 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index d11daac..b304988 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -1869,6 +1869,39 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
>      pcms->max_ram_below_4g = value;
>  }
>  
> +static void pc_machine_get_max_fw_size(Object *obj, Visitor *v,
> +                                             const char *name, void *opaque,
> +                                             Error **errp)
> +{
> +    PCMachineState *pcms = PC_MACHINE(obj);
> +    uint64_t value = pcms->max_fw_size;
> +
> +    visit_type_size(v, name, &value, errp);
> +}
> +
> +static void pc_machine_set_max_fw_size(Object *obj, Visitor *v,
> +                                             const char *name, void *opaque,
> +                                             Error **errp)
> +{
> +    PCMachineState *pcms = PC_MACHINE(obj);
> +    Error *error = NULL;
> +    uint64_t value;
> +
> +    visit_type_size(v, name, &value, &error);
> +    if (error) {
> +        error_propagate(errp, error);
> +        return;
> +    }
> +
> +    if (value > 16 * MiB) {
> +        warn_report("User specifed max allowed firmware size %" PRIu64 " is greater than 16MiB,"
> +                    "if combined firwmare size exceeds 16MiB system may not boot,"

Typos "specified", "firmware".

> +                    "or experience intermittent stability issues.", value);
> +    }
> +
> +    pcms->max_fw_size = value;
> +}
> +
>  static void pc_machine_initfn(Object *obj)
>  {
>      PCMachineState *pcms = PC_MACHINE(obj);
> @@ -1884,6 +1917,7 @@ static void pc_machine_initfn(Object *obj)
>      pcms->smbus_enabled = true;
>      pcms->sata_enabled = true;
>      pcms->pit_enabled = true;
> +    pcms->max_fw_size = 8 * MiB;

I'm very confused by pc_system_flash_map()... Why not check
that no pflash exceeds 8MiB? Then 2 combined would be always
<16MiB.

>  
>      pc_system_flash_create(pcms);
>      pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
> @@ -2004,6 +2038,12 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
>  
>      object_class_property_add_bool(oc, PC_MACHINE_PIT,
>          pc_machine_get_pit, pc_machine_set_pit);
> +
> +    object_class_property_add(oc, PC_MACHINE_MAX_FW_SIZE, "size",
> +        pc_machine_get_max_fw_size, pc_machine_set_max_fw_size,
> +        NULL, NULL);
> +    object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
> +        "Maximum combined firmware size");
>  }
>  
>  static const TypeInfo pc_machine_info = {
> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
> index b6c0822..22450ba 100644
> --- a/hw/i386/pc_sysfw.c
> +++ b/hw/i386/pc_sysfw.c
> @@ -39,15 +39,6 @@
>  #include "hw/block/flash.h"
>  #include "sysemu/kvm.h"
>  
> -/*
> - * We don't have a theoretically justifiable exact lower bound on the base
> - * address of any flash mapping. In practice, the IO-APIC MMIO range is
> - * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
> - * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
> - * size.
> - */
> -#define FLASH_SIZE_LIMIT (8 * MiB)
> -
>  #define FLASH_SECTOR_SIZE 4096
>  
>  static void pc_isa_bios_init(MemoryRegion *rom_memory,
> @@ -182,10 +173,10 @@ static void pc_system_flash_map(PCMachineState *pcms,
>          }
>          if ((hwaddr)size != size
>              || total_size > HWADDR_MAX - size
> -            || total_size + size > FLASH_SIZE_LIMIT) {
> +            || total_size + size > pcms->max_fw_size) {
>              error_report("combined size of system firmware exceeds "
>                           "%" PRIu64 " bytes",
> -                         FLASH_SIZE_LIMIT);
> +                         pcms->max_fw_size);
>              exit(1);
>          }
>  
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index fe52e16..cae213d 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -39,10 +39,11 @@ struct PCMachineState {
>      uint64_t max_ram_below_4g;
>      OnOffAuto vmport;
>  
> -    bool acpi_build_enabled;
> -    bool smbus_enabled;
> -    bool sata_enabled;
> -    bool pit_enabled;
> +    bool     acpi_build_enabled;
> +    bool     smbus_enabled;
> +    bool     sata_enabled;
> +    bool     pit_enabled;
> +    uint64_t max_fw_size;
>  
>      /* NUMA information: */
>      uint64_t numa_nodes;
> @@ -52,13 +53,14 @@ struct PCMachineState {
>      hwaddr memhp_io_base;
>  };
>  
> -#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
> -#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
> +#define PC_MACHINE_ACPI_DEVICE_PROP   "acpi-device"
> +#define PC_MACHINE_MAX_RAM_BELOW_4G   "max-ram-below-4g"
>  #define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
> -#define PC_MACHINE_VMPORT           "vmport"
> -#define PC_MACHINE_SMBUS            "smbus"
> -#define PC_MACHINE_SATA             "sata"
> -#define PC_MACHINE_PIT              "pit"
> +#define PC_MACHINE_VMPORT             "vmport"
> +#define PC_MACHINE_SMBUS              "smbus"
> +#define PC_MACHINE_SATA               "sata"
> +#define PC_MACHINE_PIT                "pit"
> +#define PC_MACHINE_MAX_FW_SIZE        "max-fw-size"

Having the space alignment changes in a previous "sanitize"
patch would ease the review of this one.

>  
>  /**
>   * PCMachineClass:
>
Daniel P. Berrangé Sept. 18, 2020, 8:31 a.m. UTC | #2
On Fri, Sep 18, 2020 at 04:23:39AM +0000, Erich Mcmillan wrote:
> From: Erich McMillan <erich.mcmillan@hp.com>
> 
> Signed-off-by: Erich McMillan <erich.mcmillan@hp.com>
> ---
>  hw/i386/pc.c         | 40 ++++++++++++++++++++++++++++++++++++++++
>  hw/i386/pc_sysfw.c   | 13 ++-----------
>  include/hw/i386/pc.h | 22 ++++++++++++----------
>  3 files changed, 54 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index d11daac..b304988 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -1869,6 +1869,39 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
>      pcms->max_ram_below_4g = value;
>  }
>  
> +static void pc_machine_get_max_fw_size(Object *obj, Visitor *v,
> +                                             const char *name, void *opaque,
> +                                             Error **errp)
> +{
> +    PCMachineState *pcms = PC_MACHINE(obj);
> +    uint64_t value = pcms->max_fw_size;
> +
> +    visit_type_size(v, name, &value, errp);
> +}
> +
> +static void pc_machine_set_max_fw_size(Object *obj, Visitor *v,
> +                                             const char *name, void *opaque,
> +                                             Error **errp)
> +{
> +    PCMachineState *pcms = PC_MACHINE(obj);
> +    Error *error = NULL;
> +    uint64_t value;
> +
> +    visit_type_size(v, name, &value, &error);
> +    if (error) {
> +        error_propagate(errp, error);
> +        return;
> +    }
> +

Just here we should have a comment explaining why we pick this max limit.
The comment you removed later can be transplanted to here...

> +    if (value > 16 * MiB) {
> +        warn_report("User specifed max allowed firmware size %" PRIu64 " is greater than 16MiB,"
> +                    "if combined firwmare size exceeds 16MiB system may not boot,"
> +                    "or experience intermittent stability issues.", value);
> +    }
> +
> +    pcms->max_fw_size = value;
> +}
> +
>  static void pc_machine_initfn(Object *obj)
>  {
>      PCMachineState *pcms = PC_MACHINE(obj);
> @@ -1884,6 +1917,7 @@ static void pc_machine_initfn(Object *obj)
>      pcms->smbus_enabled = true;
>      pcms->sata_enabled = true;
>      pcms->pit_enabled = true;
> +    pcms->max_fw_size = 8 * MiB;
>  
>      pc_system_flash_create(pcms);
>      pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
> @@ -2004,6 +2038,12 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
>  
>      object_class_property_add_bool(oc, PC_MACHINE_PIT,
>          pc_machine_get_pit, pc_machine_set_pit);
> +
> +    object_class_property_add(oc, PC_MACHINE_MAX_FW_SIZE, "size",
> +        pc_machine_get_max_fw_size, pc_machine_set_max_fw_size,
> +        NULL, NULL);
> +    object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
> +        "Maximum combined firmware size");
>  }
>  
>  static const TypeInfo pc_machine_info = {
> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
> index b6c0822..22450ba 100644
> --- a/hw/i386/pc_sysfw.c
> +++ b/hw/i386/pc_sysfw.c
> @@ -39,15 +39,6 @@
>  #include "hw/block/flash.h"
>  #include "sysemu/kvm.h"
>  
> -/*
> - * We don't have a theoretically justifiable exact lower bound on the base
> - * address of any flash mapping. In practice, the IO-APIC MMIO range is
> - * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
> - * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
> - * size.
> - */

....this comment should be transplanted above^^

> -#define FLASH_SIZE_LIMIT (8 * MiB)
> -
>  #define FLASH_SECTOR_SIZE 4096
>  
>  static void pc_isa_bios_init(MemoryRegion *rom_memory,
> @@ -182,10 +173,10 @@ static void pc_system_flash_map(PCMachineState *pcms,
>          }
>          if ((hwaddr)size != size
>              || total_size > HWADDR_MAX - size
> -            || total_size + size > FLASH_SIZE_LIMIT) {
> +            || total_size + size > pcms->max_fw_size) {
>              error_report("combined size of system firmware exceeds "
>                           "%" PRIu64 " bytes",
> -                         FLASH_SIZE_LIMIT);
> +                         pcms->max_fw_size);
>              exit(1);
>          }
>  
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index fe52e16..cae213d 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -39,10 +39,11 @@ struct PCMachineState {
>      uint64_t max_ram_below_4g;
>      OnOffAuto vmport;
>  
> -    bool acpi_build_enabled;
> -    bool smbus_enabled;
> -    bool sata_enabled;
> -    bool pit_enabled;
> +    bool     acpi_build_enabled;
> +    bool     smbus_enabled;
> +    bool     sata_enabled;
> +    bool     pit_enabled;
> +    uint64_t max_fw_size;

Don't change whitespace in the existing fields - trying to
horizontally align fields has no benefit and needlessly
creates bigger diffs.

>  
>      /* NUMA information: */
>      uint64_t numa_nodes;
> @@ -52,13 +53,14 @@ struct PCMachineState {
>      hwaddr memhp_io_base;
>  };
>  
> -#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
> -#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
> +#define PC_MACHINE_ACPI_DEVICE_PROP   "acpi-device"
> +#define PC_MACHINE_MAX_RAM_BELOW_4G   "max-ram-below-4g"
>  #define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
> -#define PC_MACHINE_VMPORT           "vmport"
> -#define PC_MACHINE_SMBUS            "smbus"
> -#define PC_MACHINE_SATA             "sata"
> -#define PC_MACHINE_PIT              "pit"
> +#define PC_MACHINE_VMPORT             "vmport"
> +#define PC_MACHINE_SMBUS              "smbus"
> +#define PC_MACHINE_SATA               "sata"
> +#define PC_MACHINE_PIT                "pit"
> +#define PC_MACHINE_MAX_FW_SIZE        "max-fw-size"

Same here, just don't change whitespace alignment please.

Regards,
Daniel
Laszlo Ersek Sept. 22, 2020, 7:34 a.m. UTC | #3
On 09/18/20 10:17, Philippe Mathieu-Daudé wrote:

> I'm very confused by pc_system_flash_map()... Why not check
> that no pflash exceeds 8MiB? Then 2 combined would be always
> <16MiB.

The requirement (limit) is on the total address range that is occupied
by the flash chips that are mapped in sequence. There is no size limit
that applies to an individual chip. It's also not required that chips
have the same size (or be limited by the same individual size).

Thanks
Laszlo
Laszlo Ersek Sept. 22, 2020, 7:39 a.m. UTC | #4
On 09/18/20 10:31, Daniel P. Berrangé wrote:
> On Fri, Sep 18, 2020 at 04:23:39AM +0000, Erich Mcmillan wrote:
>> From: Erich McMillan <erich.mcmillan@hp.com>
>>
>> Signed-off-by: Erich McMillan <erich.mcmillan@hp.com>
>> ---
>>  hw/i386/pc.c         | 40 ++++++++++++++++++++++++++++++++++++++++
>>  hw/i386/pc_sysfw.c   | 13 ++-----------
>>  include/hw/i386/pc.h | 22 ++++++++++++----------
>>  3 files changed, 54 insertions(+), 21 deletions(-)
>>
>> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
>> index d11daac..b304988 100644
>> --- a/hw/i386/pc.c
>> +++ b/hw/i386/pc.c
>> @@ -1869,6 +1869,39 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
>>      pcms->max_ram_below_4g = value;
>>  }
>>  
>> +static void pc_machine_get_max_fw_size(Object *obj, Visitor *v,
>> +                                             const char *name, void *opaque,
>> +                                             Error **errp)
>> +{
>> +    PCMachineState *pcms = PC_MACHINE(obj);
>> +    uint64_t value = pcms->max_fw_size;
>> +
>> +    visit_type_size(v, name, &value, errp);
>> +}
>> +
>> +static void pc_machine_set_max_fw_size(Object *obj, Visitor *v,
>> +                                             const char *name, void *opaque,
>> +                                             Error **errp)
>> +{
>> +    PCMachineState *pcms = PC_MACHINE(obj);
>> +    Error *error = NULL;
>> +    uint64_t value;
>> +
>> +    visit_type_size(v, name, &value, &error);
>> +    if (error) {
>> +        error_propagate(errp, error);
>> +        return;
>> +    }
>> +
> 
> Just here we should have a comment explaining why we pick this max limit.
> The comment you removed later can be transplanted to here...
> 
>> +    if (value > 16 * MiB) {
>> +        warn_report("User specifed max allowed firmware size %" PRIu64 " is greater than 16MiB,"
>> +                    "if combined firwmare size exceeds 16MiB system may not boot,"
>> +                    "or experience intermittent stability issues.", value);
>> +    }
>> +
>> +    pcms->max_fw_size = value;
>> +}
>> +
>>  static void pc_machine_initfn(Object *obj)
>>  {
>>      PCMachineState *pcms = PC_MACHINE(obj);
>> @@ -1884,6 +1917,7 @@ static void pc_machine_initfn(Object *obj)
>>      pcms->smbus_enabled = true;
>>      pcms->sata_enabled = true;
>>      pcms->pit_enabled = true;
>> +    pcms->max_fw_size = 8 * MiB;
>>  
>>      pc_system_flash_create(pcms);
>>      pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
>> @@ -2004,6 +2038,12 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
>>  
>>      object_class_property_add_bool(oc, PC_MACHINE_PIT,
>>          pc_machine_get_pit, pc_machine_set_pit);
>> +
>> +    object_class_property_add(oc, PC_MACHINE_MAX_FW_SIZE, "size",
>> +        pc_machine_get_max_fw_size, pc_machine_set_max_fw_size,
>> +        NULL, NULL);
>> +    object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
>> +        "Maximum combined firmware size");
>>  }
>>  
>>  static const TypeInfo pc_machine_info = {
>> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
>> index b6c0822..22450ba 100644
>> --- a/hw/i386/pc_sysfw.c
>> +++ b/hw/i386/pc_sysfw.c
>> @@ -39,15 +39,6 @@
>>  #include "hw/block/flash.h"
>>  #include "sysemu/kvm.h"
>>  
>> -/*
>> - * We don't have a theoretically justifiable exact lower bound on the base
>> - * address of any flash mapping. In practice, the IO-APIC MMIO range is
>> - * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
>> - * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
>> - * size.
>> - */
> 
> ....this comment should be transplanted above^^
> 
>> -#define FLASH_SIZE_LIMIT (8 * MiB)
>> -
>>  #define FLASH_SECTOR_SIZE 4096
>>  
>>  static void pc_isa_bios_init(MemoryRegion *rom_memory,
>> @@ -182,10 +173,10 @@ static void pc_system_flash_map(PCMachineState *pcms,
>>          }
>>          if ((hwaddr)size != size
>>              || total_size > HWADDR_MAX - size
>> -            || total_size + size > FLASH_SIZE_LIMIT) {
>> +            || total_size + size > pcms->max_fw_size) {
>>              error_report("combined size of system firmware exceeds "
>>                           "%" PRIu64 " bytes",
>> -                         FLASH_SIZE_LIMIT);
>> +                         pcms->max_fw_size);
>>              exit(1);
>>          }
>>  
>> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
>> index fe52e16..cae213d 100644
>> --- a/include/hw/i386/pc.h
>> +++ b/include/hw/i386/pc.h
>> @@ -39,10 +39,11 @@ struct PCMachineState {
>>      uint64_t max_ram_below_4g;
>>      OnOffAuto vmport;
>>  
>> -    bool acpi_build_enabled;
>> -    bool smbus_enabled;
>> -    bool sata_enabled;
>> -    bool pit_enabled;
>> +    bool     acpi_build_enabled;
>> +    bool     smbus_enabled;
>> +    bool     sata_enabled;
>> +    bool     pit_enabled;
>> +    uint64_t max_fw_size;
> 
> Don't change whitespace in the existing fields - trying to
> horizontally align fields has no benefit and needlessly
> creates bigger diffs.
> 
>>  
>>      /* NUMA information: */
>>      uint64_t numa_nodes;
>> @@ -52,13 +53,14 @@ struct PCMachineState {
>>      hwaddr memhp_io_base;
>>  };
>>  
>> -#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
>> -#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
>> +#define PC_MACHINE_ACPI_DEVICE_PROP   "acpi-device"
>> +#define PC_MACHINE_MAX_RAM_BELOW_4G   "max-ram-below-4g"
>>  #define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
>> -#define PC_MACHINE_VMPORT           "vmport"
>> -#define PC_MACHINE_SMBUS            "smbus"
>> -#define PC_MACHINE_SATA             "sata"
>> -#define PC_MACHINE_PIT              "pit"
>> +#define PC_MACHINE_VMPORT             "vmport"
>> +#define PC_MACHINE_SMBUS              "smbus"
>> +#define PC_MACHINE_SATA               "sata"
>> +#define PC_MACHINE_PIT                "pit"
>> +#define PC_MACHINE_MAX_FW_SIZE        "max-fw-size"
> 
> Same here, just don't change whitespace alignment please.

On a total tangent: I'm generally OK with changing whitespace for lining
up stuff visually, but whenever that's done, IMO it should be the *only*
thing done in a patch. First add the amount of whitespace that you know
you're going to need, to the existent fields / macros, and then
introduce the new fields / macros.

But, I understand that some maintainers dislike even that approach,
because it makes "git-blame" a bit more cumbersome to use. (The first
git-blame invocation gives you the whitespace-changing commit, and you
have to rerun git-blame at the *parent* of that commit, to get what you
actually want.)

Tangent ends, anyway...

Thanks
Laszlo
diff mbox series

Patch

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d11daac..b304988 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1869,6 +1869,39 @@  static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
     pcms->max_ram_below_4g = value;
 }
 
+static void pc_machine_get_max_fw_size(Object *obj, Visitor *v,
+                                             const char *name, void *opaque,
+                                             Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+    uint64_t value = pcms->max_fw_size;
+
+    visit_type_size(v, name, &value, errp);
+}
+
+static void pc_machine_set_max_fw_size(Object *obj, Visitor *v,
+                                             const char *name, void *opaque,
+                                             Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+    Error *error = NULL;
+    uint64_t value;
+
+    visit_type_size(v, name, &value, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+
+    if (value > 16 * MiB) {
+        warn_report("User specifed max allowed firmware size %" PRIu64 " is greater than 16MiB,"
+                    "if combined firwmare size exceeds 16MiB system may not boot,"
+                    "or experience intermittent stability issues.", value);
+    }
+
+    pcms->max_fw_size = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
     PCMachineState *pcms = PC_MACHINE(obj);
@@ -1884,6 +1917,7 @@  static void pc_machine_initfn(Object *obj)
     pcms->smbus_enabled = true;
     pcms->sata_enabled = true;
     pcms->pit_enabled = true;
+    pcms->max_fw_size = 8 * MiB;
 
     pc_system_flash_create(pcms);
     pcms->pcspk = isa_new(TYPE_PC_SPEAKER);
@@ -2004,6 +2038,12 @@  static void pc_machine_class_init(ObjectClass *oc, void *data)
 
     object_class_property_add_bool(oc, PC_MACHINE_PIT,
         pc_machine_get_pit, pc_machine_set_pit);
+
+    object_class_property_add(oc, PC_MACHINE_MAX_FW_SIZE, "size",
+        pc_machine_get_max_fw_size, pc_machine_set_max_fw_size,
+        NULL, NULL);
+    object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
+        "Maximum combined firmware size");
 }
 
 static const TypeInfo pc_machine_info = {
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index b6c0822..22450ba 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -39,15 +39,6 @@ 
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
 
-/*
- * We don't have a theoretically justifiable exact lower bound on the base
- * address of any flash mapping. In practice, the IO-APIC MMIO range is
- * [0xFEE00000..0xFEE01000] -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
- * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
- * size.
- */
-#define FLASH_SIZE_LIMIT (8 * MiB)
-
 #define FLASH_SECTOR_SIZE 4096
 
 static void pc_isa_bios_init(MemoryRegion *rom_memory,
@@ -182,10 +173,10 @@  static void pc_system_flash_map(PCMachineState *pcms,
         }
         if ((hwaddr)size != size
             || total_size > HWADDR_MAX - size
-            || total_size + size > FLASH_SIZE_LIMIT) {
+            || total_size + size > pcms->max_fw_size) {
             error_report("combined size of system firmware exceeds "
                          "%" PRIu64 " bytes",
-                         FLASH_SIZE_LIMIT);
+                         pcms->max_fw_size);
             exit(1);
         }
 
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index fe52e16..cae213d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -39,10 +39,11 @@  struct PCMachineState {
     uint64_t max_ram_below_4g;
     OnOffAuto vmport;
 
-    bool acpi_build_enabled;
-    bool smbus_enabled;
-    bool sata_enabled;
-    bool pit_enabled;
+    bool     acpi_build_enabled;
+    bool     smbus_enabled;
+    bool     sata_enabled;
+    bool     pit_enabled;
+    uint64_t max_fw_size;
 
     /* NUMA information: */
     uint64_t numa_nodes;
@@ -52,13 +53,14 @@  struct PCMachineState {
     hwaddr memhp_io_base;
 };
 
-#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
-#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
+#define PC_MACHINE_ACPI_DEVICE_PROP   "acpi-device"
+#define PC_MACHINE_MAX_RAM_BELOW_4G   "max-ram-below-4g"
 #define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"
-#define PC_MACHINE_VMPORT           "vmport"
-#define PC_MACHINE_SMBUS            "smbus"
-#define PC_MACHINE_SATA             "sata"
-#define PC_MACHINE_PIT              "pit"
+#define PC_MACHINE_VMPORT             "vmport"
+#define PC_MACHINE_SMBUS              "smbus"
+#define PC_MACHINE_SATA               "sata"
+#define PC_MACHINE_PIT                "pit"
+#define PC_MACHINE_MAX_FW_SIZE        "max-fw-size"
 
 /**
  * PCMachineClass: