29
#include "qemu/osdep.h"
31
#include "qapi/error.h"
32
#include "hw/acpi/acpi.h"
33
#include "hw/acpi/aml-build.h"
34
#include "hw/acpi/bios-linker-loader.h"
35
#include "hw/nvram/fw_cfg.h"
36
#include "hw/mem/nvdimm.h"
37
#include "qemu/nvdimm-utils.h"
44
static const uint8_t nvdimm_nfit_spa_uuid[] =
45
UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
46
0x18, 0xb7, 0x8c, 0xdb);
65
uint32_t proximity_domain;
66
uint8_t type_guid[16];
71
typedef struct NvdimmNfitSpa NvdimmNfitSpa;
79
struct NvdimmNfitMemDev {
88
uint64_t region_offset;
90
uint16_t interleave_index;
91
uint16_t interleave_ways;
95
typedef struct NvdimmNfitMemDev NvdimmNfitMemDev;
97
#define ACPI_NFIT_MEM_NOT_ARMED (1 << 3)
104
struct NvdimmNfitControlRegion {
110
uint16_t revision_id;
111
uint16_t sub_vendor_id;
112
uint16_t sub_device_id;
113
uint16_t sub_revision_id;
115
uint32_t serial_number;
121
uint64_t status_offset;
122
uint64_t status_size;
124
uint8_t reserved2[6];
126
typedef struct NvdimmNfitControlRegion NvdimmNfitControlRegion;
133
struct NvdimmNfitPlatformCaps {
138
uint32_t capabilities;
139
uint8_t reserved2[4];
141
typedef struct NvdimmNfitPlatformCaps NvdimmNfitPlatformCaps;
150
static uint32_t nvdimm_slot_to_sn(int slot)
152
return 0x123456 + slot;
163
static uint32_t nvdimm_slot_to_handle(int slot)
176
static uint16_t nvdimm_slot_to_spa_index(int slot)
178
return (slot + 1) << 1;
182
static uint32_t nvdimm_slot_to_dcr_index(int slot)
184
return nvdimm_slot_to_spa_index(slot) + 1;
187
static NVDIMMDevice *nvdimm_get_device_by_handle(uint32_t handle)
189
NVDIMMDevice *nvdimm = NULL;
190
GSList *list, *device_list = nvdimm_get_device_list();
192
for (list = device_list; list; list = list->next) {
193
NVDIMMDevice *nvd = list->data;
194
int slot = object_property_get_int(OBJECT(nvd), PC_DIMM_SLOT_PROP,
197
if (nvdimm_slot_to_handle(slot) == handle) {
203
g_slist_free(device_list);
209
nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
211
NvdimmNfitSpa *nfit_spa;
212
uint64_t addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP,
214
uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP,
216
uint32_t node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
218
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
221
nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
223
nfit_spa->type = cpu_to_le16(0
225
nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
226
nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
232
nfit_spa->flags = cpu_to_le16(1
239
nfit_spa->proximity_domain = cpu_to_le32(node);
241
memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid,
242
sizeof(nvdimm_nfit_spa_uuid));
244
nfit_spa->spa_base = cpu_to_le64(addr);
245
nfit_spa->spa_length = cpu_to_le64(size);
248
nfit_spa->mem_attr = cpu_to_le64(0x8ULL |
257
nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
259
NvdimmNfitMemDev *nfit_memdev;
260
NVDIMMDevice *nvdimm = NVDIMM(OBJECT(dev));
261
uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP,
263
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
265
uint32_t handle = nvdimm_slot_to_handle(slot);
267
nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
269
nfit_memdev->type = cpu_to_le16(1
271
nfit_memdev->length = cpu_to_le16(sizeof(*nfit_memdev));
272
nfit_memdev->nfit_handle = cpu_to_le32(handle);
278
nfit_memdev->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
280
nfit_memdev->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
283
nfit_memdev->region_len = cpu_to_le64(size);
285
nfit_memdev->region_dpa = cpu_to_le64(0);
288
nfit_memdev->interleave_ways = cpu_to_le16(1);
290
if (nvdimm->unarmed) {
291
nfit_memdev->flags |= cpu_to_le16(ACPI_NFIT_MEM_NOT_ARMED);
298
static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
300
NvdimmNfitControlRegion *nfit_dcr;
301
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
303
uint32_t sn = nvdimm_slot_to_sn(slot);
305
nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
307
nfit_dcr->type = cpu_to_le16(4 );
308
nfit_dcr->length = cpu_to_le16(sizeof(*nfit_dcr));
309
nfit_dcr->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
312
nfit_dcr->vendor_id = cpu_to_le16(0x8086);
313
nfit_dcr->device_id = cpu_to_le16(1);
316
nfit_dcr->revision_id = cpu_to_le16(1
318
nfit_dcr->serial_number = cpu_to_le32(sn);
319
nfit_dcr->fic = cpu_to_le16(0x301
329
nvdimm_build_structure_caps(GArray *structures, uint32_t capabilities)
331
NvdimmNfitPlatformCaps *nfit_caps;
333
nfit_caps = acpi_data_push(structures, sizeof(*nfit_caps));
335
nfit_caps->type = cpu_to_le16(7 );
336
nfit_caps->length = cpu_to_le16(sizeof(*nfit_caps));
337
nfit_caps->highest_cap = 31 - clz32(capabilities);
338
nfit_caps->capabilities = cpu_to_le32(capabilities);
341
static GArray *nvdimm_build_device_structure(NVDIMMState *state)
343
GSList *device_list, *list = nvdimm_get_device_list();
344
GArray *structures = g_array_new(false, true , 1);
346
for (device_list = list; device_list; device_list = device_list->next) {
347
DeviceState *dev = device_list->data;
350
nvdimm_build_structure_spa(structures, dev);
356
nvdimm_build_structure_memdev(structures, dev);
359
nvdimm_build_structure_dcr(structures, dev);
363
if (state->persistence) {
364
nvdimm_build_structure_caps(structures, state->persistence);
370
static void nvdimm_init_fit_buffer(NvdimmFitBuffer *fit_buf)
372
fit_buf->fit = g_array_new(false, true , 1);
375
static void nvdimm_build_fit_buffer(NVDIMMState *state)
377
NvdimmFitBuffer *fit_buf = &state->fit_buf;
379
g_array_free(fit_buf->fit, true);
380
fit_buf->fit = nvdimm_build_device_structure(state);
381
fit_buf->dirty = true;
384
void nvdimm_plug(NVDIMMState *state)
386
nvdimm_build_fit_buffer(state);
400
static void nvdimm_build_nfit(NVDIMMState *state, GArray *table_offsets,
401
GArray *table_data, BIOSLinker *linker,
402
const char *oem_id, const char *oem_table_id)
404
NvdimmFitBuffer *fit_buf = &state->fit_buf;
405
AcpiTable table = { .sig = "NFIT", .rev = 1,
406
.oem_id = oem_id, .oem_table_id = oem_table_id };
408
acpi_add_table(table_offsets, table_data);
410
acpi_table_begin(&table, table_data);
412
build_append_int_noprefix(table_data, 0, 4);
414
g_array_append_vals(table_data, fit_buf->fit->data, fit_buf->fit->len);
415
acpi_table_end(linker, &table);
418
#define NVDIMM_DSM_MEMORY_SIZE 4096
429
typedef struct NvdimmDsmIn NvdimmDsmIn;
430
QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmIn) != NVDIMM_DSM_MEMORY_SIZE);
437
typedef struct NvdimmDsmOut NvdimmDsmOut;
438
QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmOut) != NVDIMM_DSM_MEMORY_SIZE);
440
struct NvdimmDsmFunc0Out {
443
uint32_t supported_func;
445
typedef struct NvdimmDsmFunc0Out NvdimmDsmFunc0Out;
447
struct NvdimmDsmFuncNoPayloadOut {
450
uint32_t func_ret_status;
452
typedef struct NvdimmDsmFuncNoPayloadOut NvdimmDsmFuncNoPayloadOut;
454
struct NvdimmFuncGetLabelSizeOut {
457
uint32_t func_ret_status;
465
typedef struct NvdimmFuncGetLabelSizeOut NvdimmFuncGetLabelSizeOut;
466
QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelSizeOut) > NVDIMM_DSM_MEMORY_SIZE);
468
struct NvdimmFuncGetLabelDataIn {
472
typedef struct NvdimmFuncGetLabelDataIn NvdimmFuncGetLabelDataIn;
473
QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataIn) +
474
offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
476
struct NvdimmFuncGetLabelDataOut {
479
uint32_t func_ret_status;
482
typedef struct NvdimmFuncGetLabelDataOut NvdimmFuncGetLabelDataOut;
483
QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > NVDIMM_DSM_MEMORY_SIZE);
485
struct NvdimmFuncSetLabelDataIn {
490
typedef struct NvdimmFuncSetLabelDataIn NvdimmFuncSetLabelDataIn;
491
QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncSetLabelDataIn) +
492
offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
494
struct NvdimmFuncReadFITIn {
497
typedef struct NvdimmFuncReadFITIn NvdimmFuncReadFITIn;
498
QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITIn) +
499
offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
501
struct NvdimmFuncReadFITOut {
504
uint32_t func_ret_status;
507
typedef struct NvdimmFuncReadFITOut NvdimmFuncReadFITOut;
508
QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITOut) > NVDIMM_DSM_MEMORY_SIZE);
511
nvdimm_dsm_function0(uint32_t supported_func, hwaddr dsm_mem_addr)
513
NvdimmDsmFunc0Out func0 = {
514
.len = cpu_to_le32(sizeof(func0)),
515
.supported_func = cpu_to_le32(supported_func),
517
cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof(func0));
521
nvdimm_dsm_no_payload(uint32_t func_ret_status, hwaddr dsm_mem_addr)
523
NvdimmDsmFuncNoPayloadOut out = {
524
.len = cpu_to_le32(sizeof(out)),
525
.func_ret_status = cpu_to_le32(func_ret_status),
527
cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out));
530
#define NVDIMM_DSM_RET_STATUS_SUCCESS 0
531
#define NVDIMM_DSM_RET_STATUS_UNSUPPORT 1
532
#define NVDIMM_DSM_RET_STATUS_NOMEMDEV 2
533
#define NVDIMM_DSM_RET_STATUS_INVALID 3
534
#define NVDIMM_DSM_RET_STATUS_FIT_CHANGED 0x100
536
#define NVDIMM_QEMU_RSVD_HANDLE_ROOT 0x10000
539
static void nvdimm_dsm_func_read_fit(NVDIMMState *state, NvdimmDsmIn *in,
542
NvdimmFitBuffer *fit_buf = &state->fit_buf;
543
NvdimmFuncReadFITIn *read_fit;
544
NvdimmFuncReadFITOut *read_fit_out;
546
uint32_t read_len = 0, func_ret_status;
549
read_fit = (NvdimmFuncReadFITIn *)in->arg3;
550
read_fit->offset = le32_to_cpu(read_fit->offset);
554
trace_acpi_nvdimm_read_fit(read_fit->offset, fit->len,
555
fit_buf->dirty ? "Yes" : "No");
557
if (read_fit->offset > fit->len) {
558
func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID;
563
if (!read_fit->offset) {
564
fit_buf->dirty = false;
565
} else if (fit_buf->dirty) {
566
func_ret_status = NVDIMM_DSM_RET_STATUS_FIT_CHANGED;
570
func_ret_status = NVDIMM_DSM_RET_STATUS_SUCCESS;
571
read_len = MIN(fit->len - read_fit->offset,
572
NVDIMM_DSM_MEMORY_SIZE - sizeof(NvdimmFuncReadFITOut));
575
size = sizeof(NvdimmFuncReadFITOut) + read_len;
576
read_fit_out = g_malloc(size);
578
read_fit_out->len = cpu_to_le32(size);
579
read_fit_out->func_ret_status = cpu_to_le32(func_ret_status);
580
memcpy(read_fit_out->fit, fit->data + read_fit->offset, read_len);
582
cpu_physical_memory_write(dsm_mem_addr, read_fit_out, size);
584
g_free(read_fit_out);
588
nvdimm_dsm_handle_reserved_root_method(NVDIMMState *state,
589
NvdimmDsmIn *in, hwaddr dsm_mem_addr)
591
switch (in->function) {
593
nvdimm_dsm_function0(0x1 | 1 << 1 , dsm_mem_addr);
596
nvdimm_dsm_func_read_fit(state, in, dsm_mem_addr);
600
nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
603
static void nvdimm_dsm_root(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
610
nvdimm_dsm_function0(0
616
nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
624
static uint32_t nvdimm_get_max_xfer_label_size(void)
626
uint32_t max_get_size, max_set_size, dsm_memory_size;
628
dsm_memory_size = NVDIMM_DSM_MEMORY_SIZE;
634
max_get_size = dsm_memory_size - sizeof(NvdimmFuncGetLabelDataOut);
640
max_set_size = dsm_memory_size - offsetof(NvdimmDsmIn, arg3) -
641
sizeof(NvdimmFuncSetLabelDataIn);
643
return MIN(max_get_size, max_set_size);
652
static void nvdimm_dsm_label_size(NVDIMMDevice *nvdimm, hwaddr dsm_mem_addr)
654
NvdimmFuncGetLabelSizeOut label_size_out = {
655
.len = cpu_to_le32(sizeof(label_size_out)),
657
uint32_t label_size, mxfer;
659
label_size = nvdimm->label_size;
660
mxfer = nvdimm_get_max_xfer_label_size();
662
trace_acpi_nvdimm_label_info(label_size, mxfer);
664
label_size_out.func_ret_status = cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS);
665
label_size_out.label_size = cpu_to_le32(label_size);
666
label_size_out.max_xfer = cpu_to_le32(mxfer);
668
cpu_physical_memory_write(dsm_mem_addr, &label_size_out,
669
sizeof(label_size_out));
672
static uint32_t nvdimm_rw_label_data_check(NVDIMMDevice *nvdimm,
673
uint32_t offset, uint32_t length,
676
uint32_t ret = NVDIMM_DSM_RET_STATUS_INVALID;
678
if (offset + length < offset) {
679
trace_acpi_nvdimm_label_overflow(offset, length);
683
if (nvdimm->label_size < offset + length) {
684
trace_acpi_nvdimm_label_oversize(offset + length, nvdimm->label_size);
688
if (length > nvdimm_get_max_xfer_label_size()) {
689
trace_acpi_nvdimm_label_xfer_exceed(length,
690
nvdimm_get_max_xfer_label_size());
694
if (is_write && nvdimm->readonly) {
695
return NVDIMM_DSM_RET_STATUS_UNSUPPORT;
698
return NVDIMM_DSM_RET_STATUS_SUCCESS;
704
static void nvdimm_dsm_get_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
707
NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
708
NvdimmFuncGetLabelDataIn *get_label_data;
709
NvdimmFuncGetLabelDataOut *get_label_data_out;
713
get_label_data = (NvdimmFuncGetLabelDataIn *)in->arg3;
714
get_label_data->offset = le32_to_cpu(get_label_data->offset);
715
get_label_data->length = le32_to_cpu(get_label_data->length);
717
trace_acpi_nvdimm_read_label(get_label_data->offset,
718
get_label_data->length);
720
status = nvdimm_rw_label_data_check(nvdimm, get_label_data->offset,
721
get_label_data->length, false);
722
if (status != NVDIMM_DSM_RET_STATUS_SUCCESS) {
723
nvdimm_dsm_no_payload(status, dsm_mem_addr);
727
size = sizeof(*get_label_data_out) + get_label_data->length;
728
assert(size <= NVDIMM_DSM_MEMORY_SIZE);
729
get_label_data_out = g_malloc(size);
731
get_label_data_out->len = cpu_to_le32(size);
732
get_label_data_out->func_ret_status =
733
cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS);
734
nvc->read_label_data(nvdimm, get_label_data_out->out_buf,
735
get_label_data->length, get_label_data->offset);
737
cpu_physical_memory_write(dsm_mem_addr, get_label_data_out, size);
738
g_free(get_label_data_out);
744
static void nvdimm_dsm_set_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
747
NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
748
NvdimmFuncSetLabelDataIn *set_label_data;
751
set_label_data = (NvdimmFuncSetLabelDataIn *)in->arg3;
753
set_label_data->offset = le32_to_cpu(set_label_data->offset);
754
set_label_data->length = le32_to_cpu(set_label_data->length);
756
trace_acpi_nvdimm_write_label(set_label_data->offset,
757
set_label_data->length);
759
status = nvdimm_rw_label_data_check(nvdimm, set_label_data->offset,
760
set_label_data->length, true);
761
if (status != NVDIMM_DSM_RET_STATUS_SUCCESS) {
762
nvdimm_dsm_no_payload(status, dsm_mem_addr);
766
assert(offsetof(NvdimmDsmIn, arg3) + sizeof(*set_label_data) +
767
set_label_data->length <= NVDIMM_DSM_MEMORY_SIZE);
769
nvc->write_label_data(nvdimm, set_label_data->in_buf,
770
set_label_data->length, set_label_data->offset);
771
nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_SUCCESS, dsm_mem_addr);
774
static void nvdimm_dsm_device(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
776
NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(in->handle);
780
uint32_t supported_func = 0;
782
if (nvdimm && nvdimm->label_size) {
783
supported_func |= 0x1
790
nvdimm_dsm_function0(supported_func, dsm_mem_addr);
795
nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_NOMEMDEV,
801
switch (in->function) {
803
if (nvdimm->label_size) {
804
nvdimm_dsm_label_size(nvdimm, dsm_mem_addr);
809
if (nvdimm->label_size) {
810
nvdimm_dsm_get_label_data(nvdimm, in, dsm_mem_addr);
815
if (nvdimm->label_size) {
816
nvdimm_dsm_set_label_data(nvdimm, in, dsm_mem_addr);
822
nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
826
nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
828
trace_acpi_nvdimm_read_io_port();
833
nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
835
NVDIMMState *state = opaque;
837
hwaddr dsm_mem_addr = val;
839
trace_acpi_nvdimm_dsm_mem_addr(dsm_mem_addr);
846
in = g_new(NvdimmDsmIn, 1);
847
cpu_physical_memory_read(dsm_mem_addr, in, sizeof(*in));
849
in->revision = le32_to_cpu(in->revision);
850
in->function = le32_to_cpu(in->function);
851
in->handle = le32_to_cpu(in->handle);
853
trace_acpi_nvdimm_dsm_info(in->revision, in->handle, in->function);
855
if (in->revision != 0x1 ) {
856
trace_acpi_nvdimm_invalid_revision(in->revision);
857
nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
861
if (in->handle == NVDIMM_QEMU_RSVD_HANDLE_ROOT) {
862
nvdimm_dsm_handle_reserved_root_method(state, in, dsm_mem_addr);
868
nvdimm_dsm_root(in, dsm_mem_addr);
872
nvdimm_dsm_device(in, dsm_mem_addr);
878
static const MemoryRegionOps nvdimm_dsm_ops = {
879
.read = nvdimm_dsm_read,
880
.write = nvdimm_dsm_write,
881
.endianness = DEVICE_LITTLE_ENDIAN,
883
.min_access_size = 4,
884
.max_access_size = 4,
888
void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev)
890
if (dev->hotplugged) {
891
acpi_send_event(DEVICE(hotplug_dev), ACPI_NVDIMM_HOTPLUG_STATUS);
895
void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io,
896
struct AcpiGenericAddress dsm_io,
897
FWCfgState *fw_cfg, Object *owner)
899
state->dsm_io = dsm_io;
900
memory_region_init_io(&state->io_mr, owner, &nvdimm_dsm_ops, state,
901
"nvdimm-acpi-io", dsm_io.bit_width >> 3);
902
memory_region_add_subregion(io, dsm_io.address, &state->io_mr);
904
state->dsm_mem = g_array_new(false, true , 1);
905
acpi_data_push(state->dsm_mem, sizeof(NvdimmDsmIn));
906
fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data,
907
state->dsm_mem->len);
909
nvdimm_init_fit_buffer(&state->fit_buf);
912
#define NVDIMM_COMMON_DSM "NCAL"
913
#define NVDIMM_ACPI_MEM_ADDR "MEMA"
915
#define NVDIMM_DSM_MEMORY "NRAM"
916
#define NVDIMM_DSM_IOPORT "NPIO"
918
#define NVDIMM_DSM_NOTIFY "NTFI"
919
#define NVDIMM_DSM_HANDLE "HDLE"
920
#define NVDIMM_DSM_REVISION "REVS"
921
#define NVDIMM_DSM_FUNCTION "FUNC"
922
#define NVDIMM_DSM_ARG3 "FARG"
924
#define NVDIMM_DSM_OUT_BUF_SIZE "RLEN"
925
#define NVDIMM_DSM_OUT_BUF "ODAT"
927
#define NVDIMM_DSM_RFIT_STATUS "RSTA"
929
#define NVDIMM_QEMU_RSVD_UUID "648B9CF2-CDA1-4312-8AD9-49C4AF32BD62"
930
#define NVDIMM_DEVICE_DSM_UUID "4309AC30-0D11-11E4-9191-0800200C9A66"
932
static void nvdimm_build_common_dsm(Aml *dev,
933
NVDIMMState *nvdimm_state)
935
Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *elsectx2;
936
Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid;
937
Aml *pckg, *pckg_index, *pckg_buf, *field, *dsm_out_buf, *dsm_out_buf_size;
938
Aml *whilectx, *offset;
939
uint8_t byte_list[1];
942
method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED);
944
function = aml_arg(2);
946
dsm_mem = aml_local(6);
947
dsm_out_buf = aml_local(7);
949
aml_append(method, aml_store(aml_name(NVDIMM_ACPI_MEM_ADDR), dsm_mem));
951
if (nvdimm_state->dsm_io.space_id == AML_AS_SYSTEM_IO) {
954
rs = AML_SYSTEM_MEMORY;
958
aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, rs,
959
aml_int(nvdimm_state->dsm_io.address),
960
nvdimm_state->dsm_io.bit_width >> 3));
961
aml_append(method, aml_operation_region(NVDIMM_DSM_MEMORY,
962
AML_SYSTEM_MEMORY, dsm_mem, sizeof(NvdimmDsmIn)));
972
field = aml_field(NVDIMM_DSM_IOPORT, AML_DWORD_ACC, AML_NOLOCK,
974
aml_append(field, aml_named_field(NVDIMM_DSM_NOTIFY,
975
nvdimm_state->dsm_io.bit_width));
976
aml_append(method, field);
990
field = aml_field(NVDIMM_DSM_MEMORY, AML_DWORD_ACC, AML_NOLOCK,
992
aml_append(field, aml_named_field(NVDIMM_DSM_HANDLE,
993
sizeof(typeof_field(NvdimmDsmIn, handle)) * BITS_PER_BYTE));
994
aml_append(field, aml_named_field(NVDIMM_DSM_REVISION,
995
sizeof(typeof_field(NvdimmDsmIn, revision)) * BITS_PER_BYTE));
996
aml_append(field, aml_named_field(NVDIMM_DSM_FUNCTION,
997
sizeof(typeof_field(NvdimmDsmIn, function)) * BITS_PER_BYTE));
998
aml_append(field, aml_named_field(NVDIMM_DSM_ARG3,
999
(sizeof(NvdimmDsmIn) - offsetof(NvdimmDsmIn, arg3)) * BITS_PER_BYTE));
1000
aml_append(method, field);
1011
field = aml_field(NVDIMM_DSM_MEMORY, AML_DWORD_ACC, AML_NOLOCK,
1013
aml_append(field, aml_named_field(NVDIMM_DSM_OUT_BUF_SIZE,
1014
sizeof(typeof_field(NvdimmDsmOut, len)) * BITS_PER_BYTE));
1015
aml_append(field, aml_named_field(NVDIMM_DSM_OUT_BUF,
1016
(sizeof(NvdimmDsmOut) - offsetof(NvdimmDsmOut, data)) * BITS_PER_BYTE));
1017
aml_append(method, field);
1023
unpatched = aml_equal(dsm_mem, aml_int(0x0));
1025
expected_uuid = aml_local(0);
1027
ifctx = aml_if(aml_equal(handle, aml_int(0x0)));
1028
aml_append(ifctx, aml_store(
1029
aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA")
1031
aml_append(method, ifctx);
1032
elsectx = aml_else();
1033
ifctx = aml_if(aml_equal(handle, aml_int(NVDIMM_QEMU_RSVD_HANDLE_ROOT)));
1034
aml_append(ifctx, aml_store(aml_touuid(NVDIMM_QEMU_RSVD_UUID
1036
aml_append(elsectx, ifctx);
1037
elsectx2 = aml_else();
1038
aml_append(elsectx2, aml_store(aml_touuid(NVDIMM_DEVICE_DSM_UUID)
1040
aml_append(elsectx, elsectx2);
1041
aml_append(method, elsectx);
1043
uuid_invalid = aml_lnot(aml_equal(uuid, expected_uuid));
1045
unsupport = aml_if(aml_lor(unpatched, uuid_invalid));
1051
ifctx = aml_if(aml_equal(function, aml_int(0)));
1053
aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
1054
aml_append(unsupport, ifctx);
1057
byte_list[0] = NVDIMM_DSM_RET_STATUS_UNSUPPORT;
1058
aml_append(unsupport, aml_return(aml_buffer(1, byte_list)));
1059
aml_append(method, unsupport);
1066
aml_append(method, aml_store(handle, aml_name(NVDIMM_DSM_HANDLE)));
1067
aml_append(method, aml_store(aml_arg(1), aml_name(NVDIMM_DSM_REVISION)));
1068
aml_append(method, aml_store(function, aml_name(NVDIMM_DSM_FUNCTION)));
1077
ifctx = aml_if(aml_land(aml_equal(aml_object_type(pckg),
1079
aml_equal(aml_sizeof(pckg), aml_int(1)) ));
1081
pckg_index = aml_local(2);
1082
pckg_buf = aml_local(3);
1083
aml_append(ifctx, aml_store(aml_index(pckg, aml_int(0)), pckg_index));
1084
aml_append(ifctx, aml_store(aml_derefof(pckg_index), pckg_buf));
1085
aml_append(ifctx, aml_store(pckg_buf, aml_name(NVDIMM_DSM_ARG3)));
1086
aml_append(method, ifctx);
1092
aml_append(method, aml_store(dsm_mem, aml_name(NVDIMM_DSM_NOTIFY)));
1094
dsm_out_buf_size = aml_local(1);
1096
aml_append(method, aml_subtract(aml_name(NVDIMM_DSM_OUT_BUF_SIZE),
1097
aml_int(4), dsm_out_buf_size));
1112
ifctx = aml_if(aml_lless(dsm_out_buf_size, aml_int(8)));
1113
offset = aml_local(2);
1114
aml_append(ifctx, aml_store(aml_int(0), offset));
1115
aml_append(ifctx, aml_name_decl("TBUF", aml_buffer(1, NULL)));
1116
aml_append(ifctx, aml_store(aml_buffer(0, NULL), dsm_out_buf));
1118
whilectx = aml_while(aml_lless(offset, dsm_out_buf_size));
1120
aml_append(whilectx, aml_store(aml_derefof(aml_index(
1121
aml_name(NVDIMM_DSM_OUT_BUF), offset)),
1122
aml_index(aml_name("TBUF"), aml_int(0))));
1123
aml_append(whilectx, aml_concatenate(dsm_out_buf, aml_name("TBUF"),
1125
aml_append(whilectx, aml_increment(offset));
1126
aml_append(ifctx, whilectx);
1128
aml_append(ifctx, aml_return(dsm_out_buf));
1129
aml_append(method, ifctx);
1132
aml_append(method, aml_store(aml_shiftleft(dsm_out_buf_size, aml_int(3)),
1134
aml_append(method, aml_create_field(aml_name(NVDIMM_DSM_OUT_BUF),
1135
aml_int(0), dsm_out_buf_size, "OBUF"));
1136
aml_append(method, aml_return(aml_name("OBUF")));
1138
aml_append(dev, method);
1141
static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
1145
method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
1146
aml_append(method, aml_return(aml_call5(NVDIMM_COMMON_DSM, aml_arg(0),
1147
aml_arg(1), aml_arg(2), aml_arg(3),
1149
aml_append(dev, method);
1152
static void nvdimm_build_fit(Aml *dev)
1154
Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
1155
Aml *whilectx, *ifcond, *ifctx, *elsectx, *fit;
1158
buf_size = aml_local(1);
1161
aml_append(dev, aml_name_decl(NVDIMM_DSM_RFIT_STATUS, aml_int(0)));
1164
method = aml_method("RFIT", 1, AML_SERIALIZED);
1165
aml_append(method, aml_name_decl("OFST", aml_int(0)));
1168
pkg = aml_package(1);
1169
aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
1170
aml_append(pkg, aml_name("OFST"));
1173
call_result = aml_call5(NVDIMM_COMMON_DSM,
1174
aml_touuid(NVDIMM_QEMU_RSVD_UUID),
1177
pkg, aml_int(NVDIMM_QEMU_RSVD_HANDLE_ROOT));
1178
aml_append(method, aml_store(call_result, buf));
1181
aml_append(method, aml_create_dword_field(buf,
1182
aml_int(0) , "STAU"));
1184
aml_append(method, aml_store(aml_name("STAU"),
1185
aml_name(NVDIMM_DSM_RFIT_STATUS)));
1188
ifcond = aml_equal(aml_int(NVDIMM_DSM_RET_STATUS_SUCCESS),
1190
ifctx = aml_if(aml_lnot(ifcond));
1191
aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
1192
aml_append(method, ifctx);
1194
aml_append(method, aml_store(aml_sizeof(buf), buf_size));
1195
aml_append(method, aml_subtract(buf_size,
1200
ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
1201
aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
1202
aml_append(method, ifctx);
1204
aml_append(method, aml_create_field(buf,
1205
aml_int(4 * BITS_PER_BYTE),
1206
aml_shiftleft(buf_size, aml_int(3)), "BUFF"));
1207
aml_append(method, aml_return(aml_name("BUFF")));
1208
aml_append(dev, method);
1211
method = aml_method("_FIT", 0, AML_SERIALIZED);
1212
offset = aml_local(3);
1214
aml_append(method, aml_store(aml_buffer(0, NULL), fit));
1215
aml_append(method, aml_store(aml_int(0), offset));
1217
whilectx = aml_while(aml_int(1));
1218
aml_append(whilectx, aml_store(aml_call1("RFIT", offset), buf));
1219
aml_append(whilectx, aml_store(aml_sizeof(buf), buf_size));
1225
ifctx = aml_if(aml_equal(aml_name(NVDIMM_DSM_RFIT_STATUS),
1226
aml_int(NVDIMM_DSM_RET_STATUS_FIT_CHANGED)));
1227
aml_append(ifctx, aml_store(aml_buffer(0, NULL), fit));
1228
aml_append(ifctx, aml_store(aml_int(0), offset));
1229
aml_append(whilectx, ifctx);
1231
elsectx = aml_else();
1234
ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
1235
aml_append(ifctx, aml_return(fit));
1236
aml_append(elsectx, ifctx);
1239
aml_append(elsectx, aml_add(offset, buf_size, offset));
1241
aml_append(elsectx, aml_concatenate(fit, buf, fit));
1242
aml_append(whilectx, elsectx);
1243
aml_append(method, whilectx);
1245
aml_append(dev, method);
1248
static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots)
1251
Aml *method, *pkg, *field, *com_call;
1253
for (slot = 0; slot < ram_slots; slot++) {
1254
uint32_t handle = nvdimm_slot_to_handle(slot);
1257
nvdimm_dev = aml_device("NV%02X", slot);
1267
aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
1273
method = aml_method("_LSI", 0, AML_SERIALIZED);
1274
com_call = aml_call5(NVDIMM_COMMON_DSM,
1275
aml_touuid(NVDIMM_DEVICE_DSM_UUID),
1276
aml_int(1), aml_int(4), aml_int(0),
1278
aml_append(method, aml_store(com_call, aml_local(0)));
1280
aml_append(method, aml_create_dword_field(aml_local(0),
1281
aml_int(0), "STTS"));
1282
aml_append(method, aml_create_dword_field(aml_local(0), aml_int(4),
1284
aml_append(method, aml_create_dword_field(aml_local(0), aml_int(8),
1287
pkg = aml_package(3);
1288
aml_append(pkg, aml_name("STTS"));
1289
aml_append(pkg, aml_name("SLSA"));
1290
aml_append(pkg, aml_name("MAXT"));
1291
aml_append(method, aml_store(pkg, aml_local(1)));
1292
aml_append(method, aml_return(aml_local(1)));
1294
aml_append(nvdimm_dev, method);
1297
method = aml_method("_LSR", 2, AML_SERIALIZED);
1298
aml_append(method, aml_name_decl("INPT", aml_buffer(8, NULL)));
1300
aml_append(method, aml_create_dword_field(aml_name("INPT"),
1301
aml_int(0), "OFST"));
1302
aml_append(method, aml_create_dword_field(aml_name("INPT"),
1303
aml_int(4), "LEN"));
1304
aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
1305
aml_append(method, aml_store(aml_arg(1), aml_name("LEN")));
1307
pkg = aml_package(1);
1308
aml_append(pkg, aml_name("INPT"));
1309
aml_append(method, aml_store(pkg, aml_local(0)));
1311
com_call = aml_call5(NVDIMM_COMMON_DSM,
1312
aml_touuid(NVDIMM_DEVICE_DSM_UUID),
1313
aml_int(1), aml_int(5), aml_local(0),
1315
aml_append(method, aml_store(com_call, aml_local(3)));
1316
field = aml_create_dword_field(aml_local(3), aml_int(0), "STTS");
1317
aml_append(method, field);
1318
field = aml_create_field(aml_local(3), aml_int(32),
1319
aml_shiftleft(aml_name("LEN"), aml_int(3)),
1321
aml_append(method, field);
1322
aml_append(method, aml_name_decl("LSA", aml_buffer(0, NULL)));
1323
aml_append(method, aml_to_buffer(aml_name("LDAT"), aml_name("LSA")));
1325
pkg = aml_package(2);
1326
aml_append(pkg, aml_name("STTS"));
1327
aml_append(pkg, aml_name("LSA"));
1329
aml_append(method, aml_store(pkg, aml_local(1)));
1330
aml_append(method, aml_return(aml_local(1)));
1332
aml_append(nvdimm_dev, method);
1335
method = aml_method("_LSW", 3, AML_SERIALIZED);
1336
aml_append(method, aml_store(aml_arg(2), aml_local(2)));
1337
aml_append(method, aml_name_decl("INPT", aml_buffer(8, NULL)));
1338
field = aml_create_dword_field(aml_name("INPT"),
1339
aml_int(0), "OFST");
1340
aml_append(method, field);
1341
field = aml_create_dword_field(aml_name("INPT"),
1342
aml_int(4), "TLEN");
1343
aml_append(method, field);
1344
aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
1345
aml_append(method, aml_store(aml_arg(1), aml_name("TLEN")));
1347
aml_append(method, aml_concatenate(aml_name("INPT"), aml_local(2),
1349
pkg = aml_package(1);
1350
aml_append(pkg, aml_name("INPT"));
1351
aml_append(method, aml_store(pkg, aml_local(0)));
1352
com_call = aml_call5(NVDIMM_COMMON_DSM,
1353
aml_touuid(NVDIMM_DEVICE_DSM_UUID),
1354
aml_int(1), aml_int(6), aml_local(0),
1356
aml_append(method, aml_store(com_call, aml_local(3)));
1357
field = aml_create_dword_field(aml_local(3), aml_int(0), "STTS");
1358
aml_append(method, field);
1359
aml_append(method, aml_return(aml_name("STTS")));
1361
aml_append(nvdimm_dev, method);
1363
nvdimm_build_device_dsm(nvdimm_dev, handle);
1364
aml_append(root_dev, nvdimm_dev);
1368
static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
1370
NVDIMMState *nvdimm_state,
1371
uint32_t ram_slots, const char *oem_id)
1373
int mem_addr_offset;
1374
Aml *ssdt, *sb_scope, *dev;
1375
AcpiTable table = { .sig = "SSDT", .rev = 1,
1376
.oem_id = oem_id, .oem_table_id = "NVDIMM" };
1378
acpi_add_table(table_offsets, table_data);
1380
acpi_table_begin(&table, table_data);
1381
ssdt = init_aml_allocator();
1382
sb_scope = aml_scope("\\_SB");
1384
dev = aml_device("NVDR");
1397
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
1399
nvdimm_build_common_dsm(dev, nvdimm_state);
1402
nvdimm_build_device_dsm(dev, 0);
1403
nvdimm_build_fit(dev);
1405
nvdimm_build_nvdimm_devices(dev, ram_slots);
1407
aml_append(sb_scope, dev);
1408
aml_append(ssdt, sb_scope);
1411
g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
1412
mem_addr_offset = build_append_named_dword(table_data,
1413
NVDIMM_ACPI_MEM_ADDR);
1415
bios_linker_loader_alloc(linker,
1416
NVDIMM_DSM_MEM_FILE, nvdimm_state->dsm_mem,
1417
sizeof(NvdimmDsmIn), false );
1418
bios_linker_loader_add_pointer(linker,
1419
ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
1420
NVDIMM_DSM_MEM_FILE, 0);
1421
free_aml_allocator();
1427
acpi_table_end(linker, &table);
1430
void nvdimm_build_srat(GArray *table_data)
1432
GSList *device_list, *list = nvdimm_get_device_list();
1434
for (device_list = list; device_list; device_list = device_list->next) {
1435
DeviceState *dev = device_list->data;
1436
Object *obj = OBJECT(dev);
1437
uint64_t addr, size;
1440
node = object_property_get_int(obj, PC_DIMM_NODE_PROP, &error_abort);
1441
addr = object_property_get_uint(obj, PC_DIMM_ADDR_PROP, &error_abort);
1442
size = object_property_get_uint(obj, PC_DIMM_SIZE_PROP, &error_abort);
1444
build_srat_memory(table_data, addr, size, node,
1445
MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE);
1450
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
1451
BIOSLinker *linker, NVDIMMState *state,
1452
uint32_t ram_slots, const char *oem_id,
1453
const char *oem_table_id)
1455
GSList *device_list;
1462
nvdimm_build_ssdt(table_offsets, table_data, linker, state,
1465
device_list = nvdimm_get_device_list();
1471
nvdimm_build_nfit(state, table_offsets, table_data, linker,
1472
oem_id, oem_table_id);
1473
g_slist_free(device_list);