qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v4 2/3] pc & q35: Add new machine opt max-ram-below-


From: Don Slutz
Subject: [Qemu-devel] [PATCH v4 2/3] pc & q35: Add new machine opt max-ram-below-4g
Date: Thu, 5 Jun 2014 12:11:55 -0400

This is a pc & q35 only machine opt.  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 <address@hidden>
---
 hw/core/machine.c                 | 44 +++++++++++++++++++
 hw/i386/pc.c                      | 22 ++++++++++
 hw/i386/pc_piix.c                 | 89 +++++++++++++++++++++++++++++++++++++--
 hw/i386/pc_q35.c                  | 39 ++++++++++++++++-
 include/hw/boards.h               |  1 +
 include/hw/i386/pc-machine-opts.h | 46 ++++++++++++++++++++
 vl.c                              |  5 +++
 7 files changed, 241 insertions(+), 5 deletions(-)
 create mode 100644 include/hw/i386/pc-machine-opts.h

diff --git a/hw/core/machine.c b/hw/core/machine.c
index cbba679..82c0ce6 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -12,6 +12,7 @@
 
 #include "hw/boards.h"
 #include "qapi/visitor.h"
+#include "hw/i386/pc-machine-opts.h"
 
 static char *machine_get_accel(Object *obj, Error **errp)
 {
@@ -235,8 +236,45 @@ static void machine_set_firmware(Object *obj, const char 
*value, Error **errp)
     ms->firmware = g_strdup(value);
 }
 
+static void machine_get_max_ram_below_4g(Object *obj, Visitor *v,
+                                         void *opaque, const char *name,
+                                         Error **errp)
+{
+    PCMachineOptsClass *pmc = opaque;
+    uint64_t value = pmc->max_ram_below_4g;
+
+    visit_type_size(v, &value, name, errp);
+}
+
+static void machine_set_max_ram_below_4g(Object *obj, Visitor *v,
+                                         void *opaque, const char *name,
+                                         Error **errp)
+{
+    PCMachineOptsClass *pmc = opaque;
+    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 then or equal to 4G", value);
+        error_propagate(errp, error);
+        return;
+    }
+
+    pmc->max_ram_below_4g = value;
+}
+
 static void machine_initfn(Object *obj)
 {
+    PCMachineOptsClass *pmc = (PCMachineOptsClass *)
+        object_dynamic_cast(obj, TYPE_PC_MACHINE_OPTS);
+
     object_property_add_str(obj, "accel",
                             machine_get_accel, machine_set_accel, NULL);
     object_property_add_bool(obj, "kernel_irqchip",
@@ -274,6 +312,12 @@ static void machine_initfn(Object *obj)
     object_property_add_bool(obj, "usb", machine_get_usb, machine_set_usb, 
NULL);
     object_property_add_str(obj, "firmware",
                             machine_get_firmware, machine_set_firmware, NULL);
+    if (pmc) {
+        object_property_add(obj, "max-ram-below-4g", "size",
+                            machine_get_max_ram_below_4g,
+                            machine_set_max_ram_below_4g,
+                            NULL, pmc, NULL);
+    }
 }
 
 static void machine_finalize(Object *obj)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e6369d5..b1f3a1c 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -23,6 +23,7 @@
  */
 #include "hw/hw.h"
 #include "hw/i386/pc.h"
+#include "hw/i386/pc-machine-opts.h"
 #include "hw/char/serial.h"
 #include "hw/i386/apic.h"
 #include "hw/block/fdc.h"
@@ -1459,3 +1460,24 @@ void ioapic_init_gsi(GSIState *gsi_state, const char 
*parent_name)
         gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
     }
 }
+
+static void pc_machine_opts_class_init(ObjectClass *klass, void *data)
+{
+    PCMachineOptsClass *pmc = PC_MACHINE_OPTS_CLASS(klass);
+
+    pmc->max_ram_below_4g = 0;
+}
+
+static const TypeInfo pc_machine_opts_info = {
+    .name          = TYPE_PC_MACHINE_OPTS,
+    .parent        = TYPE_INTERFACE,
+    .class_size    = sizeof(PCMachineOptsClass),
+    .class_init    = pc_machine_opts_class_init,
+};
+
+static void pc_machine_opts_register_types(void)
+{
+    type_register_static(&pc_machine_opts_info);
+}
+
+type_init(pc_machine_opts_register_types)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index e619356..f631c5c 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -27,6 +27,7 @@
 #include "hw/hw.h"
 #include "hw/loader.h"
 #include "hw/i386/pc.h"
+#include "hw/i386/pc-machine-opts.h"
 #include "hw/i386/apic.h"
 #include "hw/i386/smbios.h"
 #include "hw/pci/pci.h"
@@ -96,6 +97,14 @@ static void pc_init1(MachineState *machine,
     DeviceState *icc_bridge;
     FWCfgState *fw_cfg = NULL;
     PcGuestInfo *guest_info;
+    Object *mo = qdev_get_machine();
+    PCMachineOptsClass *pmc = (PCMachineOptsClass *)
+        object_dynamic_cast(mo, TYPE_PC_MACHINE_OPTS);
+    ram_addr_t lowmem = 0xe0000000;
+
+    if (pmc && pmc->max_ram_below_4g) {
+        lowmem = pmc->max_ram_below_4g;
+    }
 
     /* 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.
@@ -104,8 +113,10 @@ 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;
+    if (machine->ram_size >= lowmem) {
+        if (!(pmc && pmc->max_ram_below_4g) && gigabyte_align) {
+            lowmem = 0xc0000000;
+        }
         above_4g_mem_size = machine->ram_size - lowmem;
         below_4g_mem_size = lowmem;
     } else {
@@ -120,7 +131,7 @@ static void pc_init1(MachineState *machine,
     }
 
     icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
-    object_property_add_child(qdev_get_machine(), "icc-bridge",
+    object_property_add_child(mo, "icc-bridge",
                               OBJECT(icc_bridge), NULL);
 
     pc_cpus_init(machine->cpu_model, icc_bridge);
@@ -408,6 +419,10 @@ static QEMUMachine pc_i440fx_machine_v2_1 = {
     .alias = "pc",
     .init = pc_init_pci,
     .is_default = 1,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_I440FX_2_0_MACHINE_OPTIONS PC_I440FX_2_1_MACHINE_OPTIONS
@@ -420,6 +435,10 @@ static QEMUMachine pc_i440fx_machine_v2_0 = {
         PC_COMPAT_2_0,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
@@ -432,6 +451,10 @@ static QEMUMachine pc_i440fx_machine_v1_7 = {
         PC_COMPAT_1_7,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
@@ -444,6 +467,10 @@ static QEMUMachine pc_i440fx_machine_v1_6 = {
         PC_COMPAT_1_6,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 static QEMUMachine pc_i440fx_machine_v1_5 = {
@@ -454,6 +481,10 @@ static QEMUMachine pc_i440fx_machine_v1_5 = {
         PC_COMPAT_1_5,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_I440FX_1_4_MACHINE_OPTIONS \
@@ -468,6 +499,10 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
         PC_COMPAT_1_4,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_1_3 \
@@ -498,6 +533,10 @@ static QEMUMachine pc_machine_v1_3 = {
         PC_COMPAT_1_3,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_1_2 \
@@ -539,6 +578,10 @@ static QEMUMachine pc_machine_v1_2 = {
         PC_COMPAT_1_2,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_1_1 \
@@ -580,6 +623,10 @@ static QEMUMachine pc_machine_v1_1 = {
         PC_COMPAT_1_1,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_1_0 \
@@ -610,6 +657,10 @@ static QEMUMachine pc_machine_v1_0 = {
         { /* end of list */ }
     },
     .hw_version = "1.0",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_0_15 \
@@ -623,6 +674,10 @@ static QEMUMachine pc_machine_v0_15 = {
         { /* end of list */ }
     },
     .hw_version = "0.15",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_0_14 \
@@ -662,6 +717,10 @@ static QEMUMachine pc_machine_v0_14 = {
         { /* end of list */ }
     },
     .hw_version = "0.14",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_0_13 \
@@ -701,6 +760,10 @@ static QEMUMachine pc_machine_v0_13 = {
         { /* end of list */ }
     },
     .hw_version = "0.13",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_0_12 \
@@ -744,6 +807,10 @@ static QEMUMachine pc_machine_v0_12 = {
         { /* end of list */ }
     },
     .hw_version = "0.12",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_COMPAT_0_11 \
@@ -775,6 +842,10 @@ static QEMUMachine pc_machine_v0_11 = {
         { /* end of list */ }
     },
     .hw_version = "0.11",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 static QEMUMachine pc_machine_v0_10 = {
@@ -806,6 +877,10 @@ static QEMUMachine pc_machine_v0_10 = {
         { /* end of list */ }
     },
     .hw_version = "0.10",
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 static QEMUMachine isapc_machine = {
@@ -817,6 +892,10 @@ static QEMUMachine isapc_machine = {
     .compat_props = (GlobalProperty[]) {
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #ifdef CONFIG_XEN
@@ -839,6 +918,10 @@ static QEMUMachine xenfv_machine = {
         },
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 #endif
 
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 30a8911..ba4ada2 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -39,6 +39,7 @@
 #include "hw/pci-host/q35.h"
 #include "exec/address-spaces.h"
 #include "hw/i386/ich9.h"
+#include "hw/i386/pc-machine-opts.h"
 #include "hw/i386/smbios.h"
 #include "hw/ide/pci.h"
 #include "hw/ide/ahci.h"
@@ -83,6 +84,14 @@ static void pc_q35_init(MachineState *machine)
     PCIDevice *ahci;
     DeviceState *icc_bridge;
     PcGuestInfo *guest_info;
+    Object *mo = qdev_get_machine();
+    PCMachineOptsClass *pmc = (PCMachineOptsClass *)
+        object_dynamic_cast(mo, TYPE_PC_MACHINE_OPTS);
+    ram_addr_t lowmem = 0xb0000000;
+
+    if (pmc && pmc->max_ram_below_4g) {
+        lowmem = pmc->max_ram_below_4g;
+    }
 
     /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
      * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
@@ -93,8 +102,10 @@ 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;
+    if (machine->ram_size >= lowmem) {
+        if (!(pmc && pmc->max_ram_below_4g) && gigabyte_align) {
+            lowmem = 0x800000000;
+        }
         above_4g_mem_size = machine->ram_size - lowmem;
         below_4g_mem_size = lowmem;
     } else {
@@ -321,6 +332,10 @@ static QEMUMachine pc_q35_machine_v2_1 = {
     .name = "pc-q35-2.1",
     .alias = "q35",
     .init = pc_q35_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_Q35_2_0_MACHINE_OPTIONS PC_Q35_2_1_MACHINE_OPTIONS
@@ -333,6 +348,10 @@ static QEMUMachine pc_q35_machine_v2_0 = {
         PC_Q35_COMPAT_2_0,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
@@ -345,6 +364,10 @@ static QEMUMachine pc_q35_machine_v1_7 = {
         PC_Q35_COMPAT_1_7,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
@@ -357,6 +380,10 @@ static QEMUMachine pc_q35_machine_v1_6 = {
         PC_Q35_COMPAT_1_6,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 static QEMUMachine pc_q35_machine_v1_5 = {
@@ -367,6 +394,10 @@ static QEMUMachine pc_q35_machine_v1_5 = {
         PC_Q35_COMPAT_1_5,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 #define PC_Q35_1_4_MACHINE_OPTIONS \
@@ -381,6 +412,10 @@ static QEMUMachine pc_q35_machine_v1_4 = {
         PC_COMPAT_1_4,
         { /* end of list */ }
     },
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_PC_MACHINE_OPTS },
+        { }
+    }
 };
 
 static void pc_q35_machine_init(void)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 2d2e2be..87b45cf 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -41,6 +41,7 @@ struct QEMUMachine {
     const char *default_boot_order;
     GlobalProperty *compat_props;
     const char *hw_version;
+    InterfaceInfo *interfaces;
 };
 
 #define TYPE_MACHINE_SUFFIX "-machine"
diff --git a/include/hw/i386/pc-machine-opts.h 
b/include/hw/i386/pc-machine-opts.h
new file mode 100644
index 0000000..b90e42b
--- /dev/null
+++ b/include/hw/i386/pc-machine-opts.h
@@ -0,0 +1,46 @@
+/*
+ *  PC Machine private opts
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License,
+ *  or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PC_MACHINE_OPTS_H
+#define PC_MACHINE_OPTS_H 1
+
+#include "qemu-common.h"
+#include "qom/object.h"
+
+#define TYPE_PC_MACHINE_OPTS "pc-machine-opts"
+
+#define PC_MACHINE_OPTS_CLASS(klass) \
+    OBJECT_CLASS_CHECK(PCMachineOptsClass, (klass), TYPE_PC_MACHINE_OPTS)
+#define PC_MACHINE_OPTS_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(PCMachineOptsClass, (obj), TYPE_PC_MACHINE_OPTS)
+#define PC_MACHINE_OPTS(obj) \
+    INTERFACE_CHECK(PCMachineOpts, (obj), TYPE_PC_MACHINE_OPTS)
+
+typedef struct PCMachineOpts {
+    /*< private >*/
+    Object parent_obj;
+    /*< public >*/
+} PCMachineOpts;
+
+typedef struct PCMachineOptsClass {
+    /*< private >*/
+    InterfaceClass parent_class;
+    /*< public >*/
+    uint64_t max_ram_below_4g;
+} PCMachineOptsClass;
+
+#endif /* PC_MACHINE_OPTS_H */
diff --git a/vl.c b/vl.c
index 0c15608..c67ea5c 100644
--- a/vl.c
+++ b/vl.c
@@ -382,6 +382,10 @@ static QemuOptsList qemu_machine_opts = {
             .name = "kvm-type",
             .type = QEMU_OPT_STRING,
             .help = "Specifies the KVM virtualization mode (HV, PR)",
+        },{
+            .name = "max-ram-below-4g",
+            .type = QEMU_OPT_SIZE,
+            .help = "maximum ram below the 4G boundary (32bit boundary)",
         },
         { /* End of list */ }
     },
@@ -1623,6 +1627,7 @@ int qemu_register_machine(QEMUMachine *m)
         .parent     = TYPE_MACHINE,
         .class_init = machine_class_init,
         .class_data = (void *)m,
+        .interfaces = m->interfaces,
     };
 
     type_register(&ti);
-- 
1.8.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]