[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v6 2/3] pc & q35: Add new machine opt max-ram-below-4g



This is a pc & q35 only machine opt.

Remove gigabyte_align (now handled by .default_machine_opts).
Add warning about BIOS.

One use is to allow for more ram in a 32bit guest for example:

-machine pc,max-ram-below-4g=3.75G

If you add enough PCI devices then all mmio for them will not fit
below 4G which may not be the layout the user wanted. This allows
you to increase the below 4G address space that PCI devices can use
(aka decrease ram below 4G) and therefore in more cases not have any
mmio that is above 4G.

For example using "-machine pc,max-ram-below-4g=2G" on the command
line will limit the amount of ram that is below 4G to 2G.

Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
---
v6:
    Added setting of .default_machine_opts to include max-ram-below-4g
      for all pc types.
    Removed gigabyte_align
    Added warning on small value.
    "less then" to "less than"

v5:
    Re-work based on:

    https://github.com/imammedo/qemu/commits/memory-hotplug-v11


 hw/i386/pc.c         | 44 ++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/pc_piix.c    | 46 ++++++++++++++++++++++++++++++++--------------
 hw/i386/pc_q35.c     | 45 +++++++++++++++++++++++++++++++--------------
 include/hw/i386/pc.h |  3 +++
 vl.c                 |  4 ++++
 5 files changed, 114 insertions(+), 28 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e993b0f..a7f4f17 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1647,11 +1647,55 @@ pc_machine_get_hotplug_memory_region_size(Object *obj, 
Visitor *v, void *opaque,
     visit_type_int(v, &value, name, errp);
 }
 
+static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v,
+                                         void *opaque, const char *name,
+                                         Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+    uint64_t value = pcms->max_ram_below_4g;
+
+    visit_type_size(v, &value, name, errp);
+}
+
+static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
+                                         void *opaque, const char *name,
+                                         Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(obj);
+    Error *error = NULL;
+    uint64_t value;
+
+    visit_type_size(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+    if (value > (1ULL << 32)) {
+        error_set(&error, ERROR_CLASS_GENERIC_ERROR,
+                  "Machine option 'max-ram-below-4g=%"PRIu64
+                  "' expects size less than or equal to 4G", value);
+        error_propagate(errp, error);
+        return;
+    }
+
+    if (value > 0 && value < (1ULL << 20)) {
+        error_report("Warning: small max_ram_below_4g(%"PRIu64
+                     ") less than 1M.  BIOS may not work..",
+                     value);
+    }
+
+    pcms->max_ram_below_4g = value;
+}
+
 static void pc_machine_initfn(Object *obj)
 {
     object_property_add(obj, PC_MACHINE_MEMHP_REGION_SIZE, "int",
                         pc_machine_get_hotplug_memory_region_size,
                         NULL, NULL, NULL, NULL);
+    object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G,  "size",
+                        pc_machine_get_max_ram_below_4g,
+                        pc_machine_set_max_ram_below_4g,
+                        NULL, NULL, NULL);
 }
 
 static void pc_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 60057f9..200c225 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -48,6 +48,7 @@
 #include "exec/address-spaces.h"
 #include "hw/acpi/acpi.h"
 #include "cpu.h"
+#include "qemu/error-report.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -62,11 +63,6 @@ static bool has_pci_info;
 static bool has_acpi_build = true;
 static bool smbios_defaults = true;
 static bool smbios_legacy_mode;
-/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
- * host addresses aligned at 1Gbyte boundaries.  This way we can use 1GByte
- * pages in the host.
- */
-static bool gigabyte_align = true;
 static bool has_reserved_memory = true;
 
 /* PC hardware initialisation */
@@ -99,6 +95,19 @@ static void pc_init1(MachineState *machine,
     FWCfgState *fw_cfg = NULL;
     PcGuestInfo *guest_info;
 
+    /* Make sure that 2.0 guest addresses aligned at 1Gbyte
+     * boundaries get mapped to host addresses aligned at 1Gbyte
+     * boundaries.  This way we can use 1GByte pages in the host.
+     */
+
+    if (pc_machine->max_ram_below_4g == 0) {
+        if (machine->ram_size >= 0xe0000000) {
+            pc_machine->max_ram_below_4g = 0xc0000000;
+        } else {
+            pc_machine->max_ram_below_4g = 0xe0000000;
+        }
+    }
+
     /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
      * If it doesn't, we need to split it in chunks below and above 4G.
      * In any case, try to make sure that guest addresses aligned at
@@ -106,10 +115,15 @@ static void pc_init1(MachineState *machine,
      * For old machine types, use whatever split we used historically to avoid
      * breaking migration.
      */
-    if (machine->ram_size >= 0xe0000000) {
-        ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
-        above_4g_mem_size = machine->ram_size - lowmem;
-        below_4g_mem_size = lowmem;
+    if (machine->ram_size >= pc_machine->max_ram_below_4g) {
+        above_4g_mem_size = machine->ram_size - pc_machine->max_ram_below_4g;
+        below_4g_mem_size = pc_machine->max_ram_below_4g;
+        if (pc_machine->max_ram_below_4g && above_4g_mem_size > 
below_4g_mem_size &&
+            pc_machine->max_ram_below_4g & ((1ULL << 30) - 1)) {
+                error_report("Warning: Large machine and 
max_ram_below_4g(%"PRIu64
+                             ") not a multiple of 1G; possible bad 
performance.",
+                             pc_machine->max_ram_below_4g);
+        }
     } else {
         above_4g_mem_size = 0;
         below_4g_mem_size = machine->ram_size;
@@ -285,7 +299,6 @@ static void pc_compat_1_7(MachineState *machine)
 {
     pc_compat_2_0(machine);
     smbios_defaults = false;
-    gigabyte_align = false;
     option_rom_has_mr = true;
     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
 }
@@ -411,7 +424,7 @@ static void pc_xen_hvm_init(MachineState *machine)
 
 #define PC_I440FX_2_1_MACHINE_OPTIONS                           \
     PC_I440FX_MACHINE_OPTIONS,                                  \
-    .default_machine_opts = "firmware=bios-256k.bin"
+    .default_machine_opts = "firmware=bios-256k.bin,max-ram-below-4g=3G"
 
 static QEMUMachine pc_i440fx_machine_v2_1 = {
     PC_I440FX_2_1_MACHINE_OPTIONS,
@@ -421,7 +434,9 @@ static QEMUMachine pc_i440fx_machine_v2_1 = {
     .is_default = 1,
 };
 
-#define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS
+#define PC_I440FX_2_0_MACHINE_OPTIONS                           \
+    PC_I440FX_MACHINE_OPTIONS,                                  \
+    .default_machine_opts = "firmware=bios-256k.bin,max-ram-below-4g=0"
 
 static QEMUMachine pc_i440fx_machine_v2_0 = {
     PC_I440FX_2_0_MACHINE_OPTIONS,
@@ -433,7 +448,9 @@ static QEMUMachine pc_i440fx_machine_v2_0 = {
     },
 };
 
-#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
+#define PC_I440FX_1_7_MACHINE_OPTIONS                           \
+    PC_I440FX_MACHINE_OPTIONS,                                  \
+    .default_machine_opts = "max-ram-below-4g=3.5G"
 
 static QEMUMachine pc_i440fx_machine_v1_7 = {
     PC_I440FX_1_7_MACHINE_OPTIONS,
@@ -445,7 +462,7 @@ static QEMUMachine pc_i440fx_machine_v1_7 = {
     },
 };
 
-#define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
+#define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_1_7_MACHINE_OPTIONS
 
 static QEMUMachine pc_i440fx_machine_v1_6 = {
     PC_I440FX_1_6_MACHINE_OPTIONS,
@@ -821,6 +838,7 @@ static QEMUMachine pc_machine_v0_10 = {
 
 static QEMUMachine isapc_machine = {
     PC_COMMON_MACHINE_OPTIONS,
+    .default_machine_opts = "max-ram-below-4g=3.5G",
     .name = "isapc",
     .desc = "ISA-only PC",
     .init = pc_init_isa,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 2cb743c..43365cb 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -44,6 +44,7 @@
 #include "hw/ide/ahci.h"
 #include "hw/usb.h"
 #include "hw/cpu/icc_bus.h"
+#include "qemu/error-report.h"
 
 /* ICH9 AHCI has 6 ports */
 #define MAX_SATA_PORTS     6
@@ -52,11 +53,6 @@ static bool has_pci_info;
 static bool has_acpi_build = true;
 static bool smbios_defaults = true;
 static bool smbios_legacy_mode;
-/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
- * host addresses aligned at 1Gbyte boundaries.  This way we can use 1GByte
- * pages in the host.
- */
-static bool gigabyte_align = true;
 static bool has_reserved_memory = true;
 
 /* PC hardware initialisation */
@@ -86,6 +82,19 @@ static void pc_q35_init(MachineState *machine)
     DeviceState *icc_bridge;
     PcGuestInfo *guest_info;
 
+    /* Make sure that 2.0 guest addresses aligned at 1Gbyte
+     * boundaries get mapped to host addresses aligned at 1Gbyte
+     * boundaries.  This way we can use 1GByte pages in the host.
+     */
+
+    if (pc_machine->max_ram_below_4g == 0) {
+        if (machine->ram_size >= 0xb0000000) {
+            pc_machine->max_ram_below_4g = 0x80000000;
+        } else {
+            pc_machine->max_ram_below_4g = 0xb0000000;
+        }
+    }
+
     /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
      * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
      * also known as MMCFG).
@@ -95,10 +104,15 @@ static void pc_q35_init(MachineState *machine)
      * For old machine types, use whatever split we used historically to avoid
      * breaking migration.
      */
-    if (machine->ram_size >= 0xb0000000) {
-        ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
-        above_4g_mem_size = machine->ram_size - lowmem;
-        below_4g_mem_size = lowmem;
+    if (machine->ram_size >= pc_machine->max_ram_below_4g) {
+        above_4g_mem_size = machine->ram_size - pc_machine->max_ram_below_4g;
+        below_4g_mem_size = pc_machine->max_ram_below_4g;
+        if (pc_machine->max_ram_below_4g && above_4g_mem_size > 
below_4g_mem_size &&
+            pc_machine->max_ram_below_4g & ((1ULL << 30) - 1)) {
+                error_report("Warning: Large machine and 
max_ram_below_4g(%"PRIu64
+                             ") not a multiple of 1G; possible bad 
performance.",
+                             pc_machine->max_ram_below_4g);
+       }
     } else {
         above_4g_mem_size = 0;
         below_4g_mem_size = machine->ram_size;
@@ -263,7 +277,6 @@ static void pc_compat_1_7(MachineState *machine)
 {
     pc_compat_2_0(machine);
     smbios_defaults = false;
-    gigabyte_align = false;
     option_rom_has_mr = true;
     x86_cpu_compat_disable_kvm_features(FEAT_1_ECX, CPUID_EXT_X2APIC);
 }
@@ -325,7 +338,7 @@ static void pc_q35_init_1_4(MachineState *machine)
 
 #define PC_Q35_2_1_MACHINE_OPTIONS                      \
     PC_Q35_MACHINE_OPTIONS,                             \
-    .default_machine_opts = "firmware=bios-256k.bin"
+    .default_machine_opts = "firmware=bios-256k.bin,max-ram-below-4g=2G"
 
 static QEMUMachine pc_q35_machine_v2_1 = {
     PC_Q35_2_1_MACHINE_OPTIONS,
@@ -334,7 +347,9 @@ static QEMUMachine pc_q35_machine_v2_1 = {
     .init = pc_q35_init,
 };
 
-#define PC_Q35_2_0_MACHINE_OPTIONS PC_Q35_2_1_MACHINE_OPTIONS
+#define PC_Q35_2_0_MACHINE_OPTIONS                      \
+    PC_Q35_MACHINE_OPTIONS,                             \
+    .default_machine_opts = "firmware=bios-256k.bin,max-ram-below-4g=0"
 
 static QEMUMachine pc_q35_machine_v2_0 = {
     PC_Q35_2_0_MACHINE_OPTIONS,
@@ -346,7 +361,9 @@ static QEMUMachine pc_q35_machine_v2_0 = {
     },
 };
 
-#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
+#define PC_Q35_1_7_MACHINE_OPTIONS                      \
+    PC_Q35_MACHINE_OPTIONS,                             \
+    .default_machine_opts = "max-ram-below-4g=2.75G"
 
 static QEMUMachine pc_q35_machine_v1_7 = {
     PC_Q35_1_7_MACHINE_OPTIONS,
@@ -358,7 +375,7 @@ static QEMUMachine pc_q35_machine_v1_7 = {
     },
 };
 
-#define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
+#define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_1_7_MACHINE_OPTIONS
 
 static QEMUMachine pc_q35_machine_v1_6 = {
     PC_Q35_1_6_MACHINE_OPTIONS,
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 76d4c6e..f5672ee 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -33,10 +33,13 @@ struct PCMachineState {
     MemoryRegion hotplug_memory;
 
     HotplugHandler *acpi_dev;
+
+    uint64_t max_ram_below_4g;
 };
 
 #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
 #define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
+#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
 
 /**
  * PCMachineClass:
diff --git a/vl.c b/vl.c
index 1617013..27c60eb 100644
--- a/vl.c
+++ b/vl.c
@@ -381,6 +381,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "kvm-type",
             .type = QEMU_OPT_STRING,
             .help = "Specifies the KVM virtualization mode (HV, PR)",
+        },{
+            .name = PC_MACHINE_MAX_RAM_BELOW_4G,
+            .type = QEMU_OPT_SIZE,
+            .help = "maximum ram below the 4G boundary (32bit boundary)",
         },
         { /* End of list */ }
     },
-- 
1.8.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.