/* * 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); }
/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */ static void nvdimm_build_structure_spa(GArray *structures, DeviceState *dev) { NvdimmNfitSpa *nfit_spa; uint64_t addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP, NULL); uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP, NULL); uint32_t node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP, NULL); int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, NULL); nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa)); nfit_spa->type = cpu_to_le16(0 /* System Physical Address Range Structure */); nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa)); nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot)); /* * Control region is strict as all the device info, such as SN, index, * is associated with slot id. */ nfit_spa->flags = cpu_to_le16(1 /* Control region is strictly for management during hot add/online operation */ | 2 /* Data in Proximity Domain field is valid*/); /* NUMA node. */ nfit_spa->proximity_domain = cpu_to_le32(node); /* the region reported as PMEM. */ memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid, sizeof(nvdimm_nfit_spa_uuid)); nfit_spa->spa_base = cpu_to_le64(addr); nfit_spa->spa_length = cpu_to_le64(size); /* It is the PMEM and can be cached as writeback. */ nfit_spa->mem_attr = cpu_to_le64(0x8ULL /* EFI_MEMORY_WB */ | 0x8000ULL /* EFI_MEMORY_NV */); }
/* See the comments of nvdimm_slot_to_spa_index(). */ static uint32_t nvdimm_slot_to_dcr_index(int slot) { return nvdimm_slot_to_spa_index(slot) + 1; }