static gint pc_dimm_addr_sort(gconstpointer a, gconstpointer b) { PCDIMMDevice *x = PC_DIMM(a); PCDIMMDevice *y = PC_DIMM(b); Int128 diff = int128_sub(int128_make64(x->addr), int128_make64(y->addr)); if (int128_lt(diff, int128_zero())) { return -1; } else if (int128_gt(diff, int128_zero())) { return 1; } return 0; }
static void pc_dimm_realize(DeviceState *dev, Error **errp) { PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); if (!dimm->hostmem) { error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set"); return; } else if (host_memory_backend_is_mapped(dimm->hostmem)) { char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem)); error_setg(errp, "can't use already busy memdev: %s", path); g_free(path); return; } if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) || (!nb_numa_nodes && dimm->node)) { error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %" PRIu32 "' which exceeds the number of numa nodes: %d", dimm->node, nb_numa_nodes ? nb_numa_nodes : 1); return; } if (ddc->realize) { ddc->realize(dimm, errp); } host_memory_backend_set_mapped(dimm->hostmem, true); }
static void pc_dimm_md_fill_device_info(const MemoryDeviceState *md, MemoryDeviceInfo *info) { PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1); const DeviceClass *dc = DEVICE_GET_CLASS(md); const PCDIMMDevice *dimm = PC_DIMM(md); const DeviceState *dev = DEVICE(md); if (dev->id) { di->has_id = true; di->id = g_strdup(dev->id); } di->hotplugged = dev->hotplugged; di->hotpluggable = dc->hotpluggable; di->addr = dimm->addr; di->slot = dimm->slot; di->node = dimm->node; di->size = object_property_get_uint(OBJECT(dimm), PC_DIMM_SIZE_PROP, NULL); di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem)); if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { info->u.nvdimm.data = di; info->type = MEMORY_DEVICE_INFO_KIND_NVDIMM; } else { info->u.dimm.data = di; info->type = MEMORY_DEVICE_INFO_KIND_DIMM; } }
static void pc_dimm_realize(DeviceState *dev, Error **errp) { PCDIMMDevice *dimm = PC_DIMM(dev); if (!dimm->hostmem) { error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set"); return; } }
void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms, MemoryRegion *mr) { PCDIMMDevice *dimm = PC_DIMM(dev); numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node); memory_region_del_subregion(&hpms->mr, mr); vmstate_unregister_ram(mr, dev); }
void pc_dimm_unplug(DeviceState *dev, MachineState *machine) { PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm, &error_abort); MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort); memory_device_unplug_region(machine, mr); vmstate_unregister_ram(vmstate_mr, dev); }
void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms, MemoryRegion *mr) { PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm); numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node); memory_region_del_subregion(&hpms->mr, mr); vmstate_unregister_ram(vmstate_mr, dev); }
static void pc_dimm_init(Object *obj) { PCDIMMDevice *dimm = PC_DIMM(obj); object_property_add(obj, PC_DIMM_SIZE_PROP, "int", pc_dimm_get_size, NULL, NULL, NULL, &error_abort); object_property_add_link(obj, PC_DIMM_MEMDEV_PROP, TYPE_MEMORY_BACKEND, (Object **)&dimm->hostmem, pc_dimm_check_memdev_is_busy, OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); }
static void pc_dimm_get_size(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { int64_t value; MemoryRegion *mr; PCDIMMDevice *dimm = PC_DIMM(obj); mr = host_memory_backend_get_memory(dimm->hostmem, errp); value = memory_region_size(mr); visit_type_int(v, &value, name, errp); }
void pc_dimm_plug(DeviceState *dev, MachineState *machine, uint64_t align, Error **errp) { int slot; PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm, &error_abort); MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort); Error *local_err = NULL; uint64_t addr; addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); if (local_err) { goto out; } addr = memory_device_get_free_addr(machine, !addr ? NULL : &addr, align, memory_region_size(mr), &local_err); if (local_err) { goto out; } object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err); if (local_err) { goto out; } trace_mhp_pc_dimm_assigned_address(addr); slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err); if (local_err) { goto out; } slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot, machine->ram_slots, &local_err); if (local_err) { goto out; } object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &local_err); if (local_err) { goto out; } trace_mhp_pc_dimm_assigned_slot(slot); memory_device_plug_region(machine, mr, addr); vmstate_register_ram(vmstate_mr, dev); out: error_propagate(errp, local_err); }
static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { int64_t value; MemoryRegion *mr; PCDIMMDevice *dimm = PC_DIMM(obj); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(obj); mr = ddc->get_memory_region(dimm); value = memory_region_size(mr); visit_type_int(v, name, &value, errp); }
static uint64_t pc_dimm_md_get_region_size(const MemoryDeviceState *md) { /* dropping const here is fine as we don't touch the memory region */ PCDIMMDevice *dimm = PC_DIMM(md); const PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(md); MemoryRegion *mr; mr = ddc->get_memory_region(dimm, &error_abort); if (!mr) { return 0; } return memory_region_size(mr); }
static void pc_dimm_realize(DeviceState *dev, Error **errp) { PCDIMMDevice *dimm = PC_DIMM(dev); if (!dimm->hostmem) { error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set"); return; } if ((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) { error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %" PRIu32 "' which exceeds the number of numa nodes: %d", dimm->node, nb_numa_nodes); return; } }
static void nvdimm_write_label_data(NVDIMMDevice *nvdimm, const void *buf, uint64_t size, uint64_t offset) { MemoryRegion *mr; PCDIMMDevice *dimm = PC_DIMM(nvdimm); uint64_t backend_offset; nvdimm_validate_rw_label_data(nvdimm, size, offset); memcpy(nvdimm->label_data + offset, buf, size); mr = host_memory_backend_get_memory(dimm->hostmem, &error_abort); backend_offset = memory_region_size(mr) - nvdimm->label_size + offset; memory_region_set_dirty(mr, backend_offset, size); }
static int pc_dimm_slot2bitmap(Object *obj, void *opaque) { unsigned long *bitmap = opaque; if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { DeviceState *dev = DEVICE(obj); if (dev->realized) { /* count only realized DIMMs */ PCDIMMDevice *d = PC_DIMM(obj); set_bit(d->slot, bitmap); } } object_child_foreach(obj, pc_dimm_slot2bitmap, opaque); return 0; }
int qmp_pc_dimm_device_list(Object *obj, void *opaque) { MemoryDeviceInfoList ***prev = opaque; if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { DeviceState *dev = DEVICE(obj); if (dev->realized) { MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1); MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1); PCDIMMDeviceInfo *di = g_new0(PCDIMMDeviceInfo, 1); DeviceClass *dc = DEVICE_GET_CLASS(obj); PCDIMMDevice *dimm = PC_DIMM(obj); if (dev->id) { di->has_id = true; di->id = g_strdup(dev->id); } di->hotplugged = dev->hotplugged; di->hotpluggable = dc->hotpluggable; di->addr = dimm->addr; di->slot = dimm->slot; di->node = dimm->node; di->size = object_property_get_uint(OBJECT(dimm), PC_DIMM_SIZE_PROP, NULL); di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem)); info->u.dimm.data = di; elem->value = info; elem->next = NULL; **prev = elem; *prev = &elem->next; } } object_child_foreach(obj, qmp_pc_dimm_device_list, opaque); return 0; }
static void pc_dimm_realize(DeviceState *dev, Error **errp) { PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); if (!dimm->hostmem) { error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set"); return; } if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) || (!nb_numa_nodes && dimm->node)) { error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %" PRIu32 "' which exceeds the number of numa nodes: %d", dimm->node, nb_numa_nodes ? nb_numa_nodes : 1); return; } if (ddc->realize) { ddc->realize(dimm, errp); } host_memory_backend_set_mapped(dimm->hostmem, true); }
static void pc_dimm_unrealize(DeviceState *dev, Error **errp) { PCDIMMDevice *dimm = PC_DIMM(dev); host_memory_backend_set_mapped(dimm->hostmem, false); }
void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms, MemoryRegion *mr, uint64_t align, Error **errp) { int slot; MachineState *machine = MACHINE(qdev_get_machine()); PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); MemoryRegion *vmstate_mr = ddc->get_vmstate_memory_region(dimm); Error *local_err = NULL; uint64_t existing_dimms_capacity = 0; uint64_t addr; addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); if (local_err) { goto out; } addr = pc_dimm_get_free_addr(hpms->base, memory_region_size(&hpms->mr), !addr ? NULL : &addr, align, memory_region_size(mr), &local_err); if (local_err) { goto out; } existing_dimms_capacity = pc_existing_dimms_capacity(&local_err); if (local_err) { 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 hot pluggable 0x" RAM_ADDR_FMT, existing_dimms_capacity, machine->maxram_size - machine->ram_size); goto out; } object_property_set_uint(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err); if (local_err) { goto out; } trace_mhp_pc_dimm_assigned_address(addr); slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err); if (local_err) { goto out; } slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot, machine->ram_slots, &local_err); if (local_err) { goto out; } object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &local_err); if (local_err) { goto out; } trace_mhp_pc_dimm_assigned_slot(slot); if (kvm_enabled() && !kvm_has_free_slot(machine)) { error_setg(&local_err, "hypervisor has no free memory slots left"); goto out; } if (!vhost_has_free_slot()) { error_setg(&local_err, "a used vhost backend has no free" " memory slots left"); goto out; } memory_region_add_subregion(&hpms->mr, addr - hpms->base, mr); vmstate_register_ram(vmstate_mr, dev); numa_set_mem_node_id(addr, memory_region_size(mr), dimm->node); out: error_propagate(errp, local_err); }
static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md) { const PCDIMMDevice *dimm = PC_DIMM(md); return dimm->addr; }