diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-11-24 19:31:50 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-11-24 19:31:50 +0000 |
commit | ca6028185d19d3f2bd331c15175c3ef5afc30c77 (patch) | |
tree | 88d51adb56c3598d6b4a8241ed2e4c4ca395652e /hw/i386/pc.c | |
parent | 3d4a70f80fead02a3b3872790b4c8f07ee804494 (diff) | |
parent | dd0247e09a542d2a7ba6e390c70b5616edb9ec56 (diff) | |
download | qemu-ca6028185d19d3f2bd331c15175c3ef5afc30c77.zip qemu-ca6028185d19d3f2bd331c15175c3ef5afc30c77.tar.gz qemu-ca6028185d19d3f2bd331c15175c3ef5afc30c77.tar.bz2 |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc, pci, misc bugfixes
A bunch of bugfixes for 2.2.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Mon 24 Nov 2014 18:59:47 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream:
pc: acpi: mark all possible CPUs as enabled in SRAT
pcie: fix improper use of negative value
pcie: fix typo in pcie_cap_deverr_init()
target-i386: move generic memory hotplug methods to DSDTs
acpi-build: mark RAM dirty on table update
hw/pci: fix crash on shpc error flow
pc: count in 1Gb hugepage alignment when sizing hotplug-memory container
pc: explicitly check maxmem limit when adding DIMM
pc: pc-dimm: use backend alignment during address auto allocation
pc: align DIMM's address/size by backend's alignment value
memory: expose alignment used for allocating RAM as MemoryRegion API
pc: limit DIMM address and size to page aligned values
pc: make pc_dimm_plug() more readble
pc: kvm: check if KVM has free memory slots to avoid abort()
qemu-char: fix tcp_get_fds
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/i386/pc.c')
-rw-r--r-- | hw/i386/pc.c | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1205db8..8be50a4 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1247,6 +1247,11 @@ FWCfgState *pc_memory_init(MachineState *machine, pcms->hotplug_memory_base = ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30); + if (pcms->enforce_aligned_dimm) { + /* size hotplug region assuming 1G page max alignment per slot */ + hotplug_mem_size += (1ULL << 30) * machine->ram_slots; + } + if ((pcms->hotplug_memory_base + hotplug_mem_size) < hotplug_mem_size) { error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT, @@ -1545,6 +1550,37 @@ void qemu_register_pc_machine(QEMUMachine *m) g_free(name); } +static int pc_dimm_count(Object *obj, void *opaque) +{ + int *count = opaque; + + if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { + (*count)++; + } + + object_child_foreach(obj, pc_dimm_count, opaque); + return 0; +} + +static int pc_existing_dimms_capacity(Object *obj, void *opaque) +{ + Error *local_err = NULL; + uint64_t *size = opaque; + + if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { + (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, &local_err); + + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + return 1; + } + } + + object_child_foreach(obj, pc_dimm_count, opaque); + return 0; +} + static void pc_dimm_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1556,20 +1592,40 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *mr = ddc->get_memory_region(dimm); - uint64_t addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, - &local_err); + uint64_t existing_dimms_capacity = 0; + uint64_t align = TARGET_PAGE_SIZE; + uint64_t addr; + + addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); if (local_err) { goto out; } + if (memory_region_get_alignment(mr) && pcms->enforce_aligned_dimm) { + align = memory_region_get_alignment(mr); + } + addr = pc_dimm_get_free_addr(pcms->hotplug_memory_base, memory_region_size(&pcms->hotplug_memory), - !addr ? NULL : &addr, + !addr ? NULL : &addr, align, memory_region_size(mr), &local_err); if (local_err) { goto out; } + if (pc_existing_dimms_capacity(OBJECT(machine), &existing_dimms_capacity)) { + error_setg(&local_err, "failed to get total size of existing DIMMs"); + goto out; + } + + if (existing_dimms_capacity + memory_region_size(mr) > + machine->maxram_size - machine->ram_size) { + error_setg(&local_err, "not enough space, currently 0x%" PRIx64 + " in use of total 0x" RAM_ADDR_FMT, + existing_dimms_capacity, machine->maxram_size); + goto out; + } + object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err); if (local_err) { goto out; @@ -1598,6 +1654,11 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, goto out; } + if (kvm_enabled() && !kvm_has_free_slot(machine)) { + error_setg(&local_err, "hypervisor has no free memory slots left"); + goto out; + } + memory_region_add_subregion(&pcms->hotplug_memory, addr - pcms->hotplug_memory_base, mr); vmstate_register_ram(mr, dev); @@ -1725,6 +1786,13 @@ static void pc_machine_set_vmport(Object *obj, bool value, Error **errp) pcms->vmport = value; } +static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + return pcms->enforce_aligned_dimm; +} + static void pc_machine_initfn(Object *obj) { PCMachineState *pcms = PC_MACHINE(obj); @@ -1737,11 +1805,17 @@ static void pc_machine_initfn(Object *obj) pc_machine_get_max_ram_below_4g, pc_machine_set_max_ram_below_4g, NULL, NULL, NULL); + pcms->vmport = !xen_enabled(); object_property_add_bool(obj, PC_MACHINE_VMPORT, pc_machine_get_vmport, pc_machine_set_vmport, NULL); + + pcms->enforce_aligned_dimm = true; + object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM, + pc_machine_get_aligned_dimm, + NULL, NULL); } static void pc_machine_class_init(ObjectClass *oc, void *data) |