static void nvdimm_realize(PCDIMMDevice *dimm, Error **errp) { MemoryRegion *mr = host_memory_backend_get_memory(dimm->hostmem, errp); NVDIMMDevice *nvdimm = NVDIMM(dimm); uint64_t align, pmem_size, size = memory_region_size(mr); align = memory_region_get_alignment(mr); pmem_size = size - nvdimm->label_size; nvdimm->label_data = memory_region_get_ram_ptr(mr) + pmem_size; pmem_size = QEMU_ALIGN_DOWN(pmem_size, align); if (size <= nvdimm->label_size || !pmem_size) { HostMemoryBackend *hostmem = dimm->hostmem; char *path = object_get_canonical_path_component(OBJECT(hostmem)); error_setg(errp, "the size of memdev %s (0x%" PRIx64 ") is too " "small to contain nvdimm label (0x%" PRIx64 ") and " "aligned PMEM (0x%" PRIx64 ")", path, memory_region_size(mr), nvdimm->label_size, align); g_free(path); return; } memory_region_init_alias(&nvdimm->nvdimm_mr, OBJECT(dimm), "nvdimm-memory", mr, 0, pmem_size); nvdimm->nvdimm_mr.align = align; }
static void nvdimm_set_label_size(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { NVDIMMDevice *nvdimm = NVDIMM(obj); Error *local_err = NULL; uint64_t value; if (memory_region_size(&nvdimm->nvdimm_mr)) { error_setg(&local_err, "cannot change property value"); goto out; } visit_type_size(v, name, &value, &local_err); if (local_err) { goto out; } if (value < MIN_NAMESPACE_LABEL_SIZE) { error_setg(&local_err, "Property '%s.%s' (0x%" PRIx64 ") is required" " at least 0x%lx", object_get_typename(obj), name, value, MIN_NAMESPACE_LABEL_SIZE); goto out; } nvdimm->label_size = value; out: error_propagate(errp, local_err); }
static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { NVDIMMDevice *nvdimm = NVDIMM(obj); uint64_t value = nvdimm->label_size; visit_type_size(v, name, &value, errp); }
/* * ACPI 6.0: 5.2.25.2 Memory Device to System Physical Address Range Mapping * Structure */ static void nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev) { NvdimmNfitMemDev *nfit_memdev; NVDIMMDevice *nvdimm = NVDIMM(OBJECT(dev)); uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP, NULL); int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, NULL); uint32_t handle = nvdimm_slot_to_handle(slot); nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev)); nfit_memdev->type = cpu_to_le16(1 /* Memory Device to System Address Range Map Structure*/); nfit_memdev->length = cpu_to_le16(sizeof(*nfit_memdev)); nfit_memdev->nfit_handle = cpu_to_le32(handle); /* * associate memory device with System Physical Address Range * Structure. */ nfit_memdev->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot)); /* associate memory device with Control Region Structure. */ nfit_memdev->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot)); /* The memory region on the device. */ nfit_memdev->region_len = cpu_to_le64(size); /* The device address starts from 0. */ nfit_memdev->region_dpa = cpu_to_le64(0); /* Only one interleave for PMEM. */ nfit_memdev->interleave_ways = cpu_to_le16(1); if (nvdimm->unarmed) { nfit_memdev->flags |= cpu_to_le16(ACPI_NFIT_MEM_NOT_ARMED); } }
static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm) { NVDIMMDevice *nvdimm = NVDIMM(dimm); return &nvdimm->nvdimm_mr; }