summaryrefslogtreecommitdiff
path: root/hw/i386/pc.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i386/pc.c')
-rw-r--r--hw/i386/pc.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 021ec44768..3d732cf5a5 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1545,6 +1545,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,6 +1587,7 @@ 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 existing_dimms_capacity = 0;
uint64_t align = TARGET_PAGE_SIZE;
uint64_t addr;
@@ -1576,6 +1608,19 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
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;