[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v4 2/3] pc & q35: Add new machine opt max-ram-be
From: |
Igor Mammedov |
Subject: |
Re: [Qemu-devel] [PATCH v4 2/3] pc & q35: Add new machine opt max-ram-below-4g |
Date: |
Thu, 5 Jun 2014 18:27:27 +0200 |
On Thu, 5 Jun 2014 12:11:55 -0400
Don Slutz <address@hidden> wrote:
> 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>
this patch would look better if rebased on top of
http://lists.gnu.org/archive/html/qemu-devel/2014-06/msg00133.html
and would use PCMachine type to add PC specific "max-ram-below-4g" property.
> ---
> 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);