static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev) { for (; device_list; device_list = device_list->next) { DeviceState *dev = device_list->data; int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, NULL); uint32_t handle = nvdimm_slot_to_handle(slot); Aml *nvdimm_dev; nvdimm_dev = aml_device("NV%02X", slot); /* * ACPI 6.0: 9.20 NVDIMM Devices: * * _ADR object that is used to supply OSPM with unique address * of the NVDIMM device. This is done by returning the NFIT Device * handle that is used to identify the associated entries in ACPI * table NFIT or _FIT. */ aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle))); nvdimm_build_device_dsm(nvdimm_dev); aml_append(root_dev, nvdimm_dev); } }
/* * 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; uint64_t addr = object_property_get_int(OBJECT(dev), PC_DIMM_ADDR_PROP, NULL); uint64_t size = object_property_get_int(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); nfit_memdev->region_dpa = cpu_to_le64(addr); /* Only one interleave for PMEM. */ nfit_memdev->interleave_ways = cpu_to_le16(1); }
static NVDIMMDevice *nvdimm_get_device_by_handle(uint32_t handle) { NVDIMMDevice *nvdimm = NULL; GSList *list, *device_list = nvdimm_get_device_list(); for (list = device_list; list; list = list->next) { NVDIMMDevice *nvd = list->data; int slot = object_property_get_int(OBJECT(nvd), PC_DIMM_SLOT_PROP, NULL); if (nvdimm_slot_to_handle(slot) == handle) { nvdimm = nvd; break; } } g_slist_free(device_list); return nvdimm; }