]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/acpi/nvdimm.c
mem: move nvdimm_device_list to utilities
[thirdparty/qemu.git] / hw / acpi / nvdimm.c
CommitLineData
87252e1b
XG
1/*
2 * NVDIMM ACPI Implementation
3 *
4 * Copyright(C) 2015 Intel Corporation.
5 *
6 * Author:
7 * Xiao Guangrong <guangrong.xiao@linux.intel.com>
8 *
9 * NFIT is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
10 * and the DSM specification can be found at:
11 * http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
12 *
13 * Currently, it only supports PMEM Virtualization.
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, see <http://www.gnu.org/licenses/>
27 */
28
b6a0aa05 29#include "qemu/osdep.h"
87252e1b
XG
30#include "hw/acpi/acpi.h"
31#include "hw/acpi/aml-build.h"
b9951413 32#include "hw/acpi/bios-linker-loader.h"
5fe79386 33#include "hw/nvram/fw_cfg.h"
87252e1b 34#include "hw/mem/nvdimm.h"
3f350f6b 35#include "qemu/nvdimm-utils.h"
87252e1b
XG
36
37#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
38 { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
39 (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, \
40 (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
41
42/*
43 * define Byte Addressable Persistent Memory (PM) Region according to
44 * ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
45 */
46static const uint8_t nvdimm_nfit_spa_uuid[] =
47 NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
48 0x18, 0xb7, 0x8c, 0xdb);
49
50/*
51 * NVDIMM Firmware Interface Table
52 * @signature: "NFIT"
53 *
54 * It provides information that allows OSPM to enumerate NVDIMM present in
55 * the platform and associate system physical address ranges created by the
56 * NVDIMMs.
57 *
58 * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
59 */
60struct NvdimmNfitHeader {
61 ACPI_TABLE_HEADER_DEF
62 uint32_t reserved;
63} QEMU_PACKED;
64typedef struct NvdimmNfitHeader NvdimmNfitHeader;
65
66/*
67 * define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
68 * Interface Table (NFIT).
69 */
70
71/*
72 * System Physical Address Range Structure
73 *
74 * It describes the system physical address ranges occupied by NVDIMMs and
75 * the types of the regions.
76 */
77struct NvdimmNfitSpa {
78 uint16_t type;
79 uint16_t length;
80 uint16_t spa_index;
81 uint16_t flags;
82 uint32_t reserved;
83 uint32_t proximity_domain;
84 uint8_t type_guid[16];
85 uint64_t spa_base;
86 uint64_t spa_length;
87 uint64_t mem_attr;
88} QEMU_PACKED;
89typedef struct NvdimmNfitSpa NvdimmNfitSpa;
90
91/*
92 * Memory Device to System Physical Address Range Mapping Structure
93 *
94 * It enables identifying each NVDIMM region and the corresponding SPA
95 * describing the memory interleave
96 */
97struct NvdimmNfitMemDev {
98 uint16_t type;
99 uint16_t length;
100 uint32_t nfit_handle;
101 uint16_t phys_id;
102 uint16_t region_id;
103 uint16_t spa_index;
104 uint16_t dcr_index;
105 uint64_t region_len;
106 uint64_t region_offset;
107 uint64_t region_dpa;
108 uint16_t interleave_index;
109 uint16_t interleave_ways;
110 uint16_t flags;
111 uint16_t reserved;
112} QEMU_PACKED;
113typedef struct NvdimmNfitMemDev NvdimmNfitMemDev;
114
cb836434
HZ
115#define ACPI_NFIT_MEM_NOT_ARMED (1 << 3)
116
87252e1b
XG
117/*
118 * NVDIMM Control Region Structure
119 *
120 * It describes the NVDIMM and if applicable, Block Control Window.
121 */
122struct NvdimmNfitControlRegion {
123 uint16_t type;
124 uint16_t length;
125 uint16_t dcr_index;
126 uint16_t vendor_id;
127 uint16_t device_id;
128 uint16_t revision_id;
129 uint16_t sub_vendor_id;
130 uint16_t sub_device_id;
131 uint16_t sub_revision_id;
132 uint8_t reserved[6];
133 uint32_t serial_number;
134 uint16_t fic;
135 uint16_t num_bcw;
136 uint64_t bcw_size;
137 uint64_t cmd_offset;
138 uint64_t cmd_size;
139 uint64_t status_offset;
140 uint64_t status_size;
141 uint16_t flags;
142 uint8_t reserved2[6];
143} QEMU_PACKED;
144typedef struct NvdimmNfitControlRegion NvdimmNfitControlRegion;
145
9ab3aad2
RZ
146/*
147 * NVDIMM Platform Capabilities Structure
148 *
149 * Defined in section 5.2.25.9 of ACPI 6.2 Errata A, September 2017
150 */
151struct NvdimmNfitPlatformCaps {
152 uint16_t type;
153 uint16_t length;
154 uint8_t highest_cap;
155 uint8_t reserved[3];
156 uint32_t capabilities;
157 uint8_t reserved2[4];
158} QEMU_PACKED;
159typedef struct NvdimmNfitPlatformCaps NvdimmNfitPlatformCaps;
160
87252e1b
XG
161/*
162 * Module serial number is a unique number for each device. We use the
163 * slot id of NVDIMM device to generate this number so that each device
164 * associates with a different number.
165 *
166 * 0x123456 is a magic number we arbitrarily chose.
167 */
168static uint32_t nvdimm_slot_to_sn(int slot)
169{
170 return 0x123456 + slot;
171}
172
173/*
174 * handle is used to uniquely associate nfit_memdev structure with NVDIMM
175 * ACPI device - nfit_memdev.nfit_handle matches with the value returned
176 * by ACPI device _ADR method.
177 *
178 * We generate the handle with the slot id of NVDIMM device and reserve
179 * 0 for NVDIMM root device.
180 */
181static uint32_t nvdimm_slot_to_handle(int slot)
182{
183 return slot + 1;
184}
185
186/*
187 * index uniquely identifies the structure, 0 is reserved which indicates
188 * that the structure is not valid or the associated structure is not
189 * present.
190 *
191 * Each NVDIMM device needs two indexes, one for nfit_spa and another for
192 * nfit_dc which are generated by the slot id of NVDIMM device.
193 */
194static uint16_t nvdimm_slot_to_spa_index(int slot)
195{
196 return (slot + 1) << 1;
197}
198
199/* See the comments of nvdimm_slot_to_spa_index(). */
200static uint32_t nvdimm_slot_to_dcr_index(int slot)
201{
202 return nvdimm_slot_to_spa_index(slot) + 1;
203}
204
5797dcdc
XG
205static NVDIMMDevice *nvdimm_get_device_by_handle(uint32_t handle)
206{
207 NVDIMMDevice *nvdimm = NULL;
cf7c0ff5 208 GSList *list, *device_list = nvdimm_get_device_list();
5797dcdc
XG
209
210 for (list = device_list; list; list = list->next) {
211 NVDIMMDevice *nvd = list->data;
212 int slot = object_property_get_int(OBJECT(nvd), PC_DIMM_SLOT_PROP,
213 NULL);
214
215 if (nvdimm_slot_to_handle(slot) == handle) {
216 nvdimm = nvd;
217 break;
218 }
219 }
220
221 g_slist_free(device_list);
222 return nvdimm;
223}
224
87252e1b
XG
225/* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure */
226static void
227nvdimm_build_structure_spa(GArray *structures, DeviceState *dev)
228{
229 NvdimmNfitSpa *nfit_spa;
9ed442b8
MAL
230 uint64_t addr = object_property_get_uint(OBJECT(dev), PC_DIMM_ADDR_PROP,
231 NULL);
b053ef61
MAL
232 uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP,
233 NULL);
9ed442b8
MAL
234 uint32_t node = object_property_get_uint(OBJECT(dev), PC_DIMM_NODE_PROP,
235 NULL);
87252e1b 236 int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
9ed442b8 237 NULL);
87252e1b
XG
238
239 nfit_spa = acpi_data_push(structures, sizeof(*nfit_spa));
240
241 nfit_spa->type = cpu_to_le16(0 /* System Physical Address Range
242 Structure */);
243 nfit_spa->length = cpu_to_le16(sizeof(*nfit_spa));
244 nfit_spa->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
245
246 /*
247 * Control region is strict as all the device info, such as SN, index,
248 * is associated with slot id.
249 */
250 nfit_spa->flags = cpu_to_le16(1 /* Control region is strictly for
251 management during hot add/online
252 operation */ |
253 2 /* Data in Proximity Domain field is
254 valid*/);
255
256 /* NUMA node. */
257 nfit_spa->proximity_domain = cpu_to_le32(node);
258 /* the region reported as PMEM. */
259 memcpy(nfit_spa->type_guid, nvdimm_nfit_spa_uuid,
260 sizeof(nvdimm_nfit_spa_uuid));
261
262 nfit_spa->spa_base = cpu_to_le64(addr);
263 nfit_spa->spa_length = cpu_to_le64(size);
264
265 /* It is the PMEM and can be cached as writeback. */
266 nfit_spa->mem_attr = cpu_to_le64(0x8ULL /* EFI_MEMORY_WB */ |
267 0x8000ULL /* EFI_MEMORY_NV */);
268}
269
270/*
271 * ACPI 6.0: 5.2.25.2 Memory Device to System Physical Address Range Mapping
272 * Structure
273 */
274static void
275nvdimm_build_structure_memdev(GArray *structures, DeviceState *dev)
276{
277 NvdimmNfitMemDev *nfit_memdev;
cb836434 278 NVDIMMDevice *nvdimm = NVDIMM(OBJECT(dev));
b053ef61
MAL
279 uint64_t size = object_property_get_uint(OBJECT(dev), PC_DIMM_SIZE_PROP,
280 NULL);
87252e1b
XG
281 int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
282 NULL);
283 uint32_t handle = nvdimm_slot_to_handle(slot);
284
285 nfit_memdev = acpi_data_push(structures, sizeof(*nfit_memdev));
286
287 nfit_memdev->type = cpu_to_le16(1 /* Memory Device to System Address
288 Range Map Structure*/);
289 nfit_memdev->length = cpu_to_le16(sizeof(*nfit_memdev));
290 nfit_memdev->nfit_handle = cpu_to_le32(handle);
291
292 /*
293 * associate memory device with System Physical Address Range
294 * Structure.
295 */
296 nfit_memdev->spa_index = cpu_to_le16(nvdimm_slot_to_spa_index(slot));
297 /* associate memory device with Control Region Structure. */
298 nfit_memdev->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
299
300 /* The memory region on the device. */
301 nfit_memdev->region_len = cpu_to_le64(size);
6ab0c4bd
XG
302 /* The device address starts from 0. */
303 nfit_memdev->region_dpa = cpu_to_le64(0);
87252e1b
XG
304
305 /* Only one interleave for PMEM. */
306 nfit_memdev->interleave_ways = cpu_to_le16(1);
cb836434
HZ
307
308 if (nvdimm->unarmed) {
309 nfit_memdev->flags |= cpu_to_le16(ACPI_NFIT_MEM_NOT_ARMED);
310 }
87252e1b
XG
311}
312
313/*
314 * ACPI 6.0: 5.2.25.5 NVDIMM Control Region Structure.
315 */
316static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
317{
318 NvdimmNfitControlRegion *nfit_dcr;
319 int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
320 NULL);
321 uint32_t sn = nvdimm_slot_to_sn(slot);
322
323 nfit_dcr = acpi_data_push(structures, sizeof(*nfit_dcr));
324
325 nfit_dcr->type = cpu_to_le16(4 /* NVDIMM Control Region Structure */);
326 nfit_dcr->length = cpu_to_le16(sizeof(*nfit_dcr));
327 nfit_dcr->dcr_index = cpu_to_le16(nvdimm_slot_to_dcr_index(slot));
328
329 /* vendor: Intel. */
330 nfit_dcr->vendor_id = cpu_to_le16(0x8086);
331 nfit_dcr->device_id = cpu_to_le16(1);
332
333 /* The _DSM method is following Intel's DSM specification. */
334 nfit_dcr->revision_id = cpu_to_le16(1 /* Current Revision supported
335 in ACPI 6.0 is 1. */);
336 nfit_dcr->serial_number = cpu_to_le32(sn);
20fdef58
HZ
337 nfit_dcr->fic = cpu_to_le16(0x301 /* Format Interface Code:
338 Byte addressable, no energy backed.
339 See ACPI 6.2, sect 5.2.25.6 and
340 JEDEC Annex L Release 3. */);
87252e1b
XG
341}
342
9ab3aad2
RZ
343/*
344 * ACPI 6.2 Errata A: 5.2.25.9 NVDIMM Platform Capabilities Structure
345 */
346static void
347nvdimm_build_structure_caps(GArray *structures, uint32_t capabilities)
348{
349 NvdimmNfitPlatformCaps *nfit_caps;
350
351 nfit_caps = acpi_data_push(structures, sizeof(*nfit_caps));
352
353 nfit_caps->type = cpu_to_le16(7 /* NVDIMM Platform Capabilities */);
354 nfit_caps->length = cpu_to_le16(sizeof(*nfit_caps));
355 nfit_caps->highest_cap = 31 - clz32(capabilities);
356 nfit_caps->capabilities = cpu_to_le32(capabilities);
357}
358
c1404bde 359static GArray *nvdimm_build_device_structure(NVDIMMState *state)
87252e1b 360{
cf7c0ff5 361 GSList *device_list = nvdimm_get_device_list();
87252e1b
XG
362 GArray *structures = g_array_new(false, true /* clear */, 1);
363
364 for (; device_list; device_list = device_list->next) {
365 DeviceState *dev = device_list->data;
366
367 /* build System Physical Address Range Structure. */
368 nvdimm_build_structure_spa(structures, dev);
369
370 /*
371 * build Memory Device to System Physical Address Range Mapping
372 * Structure.
373 */
374 nvdimm_build_structure_memdev(structures, dev);
375
376 /* build NVDIMM Control Region Structure. */
377 nvdimm_build_structure_dcr(structures, dev);
378 }
75b0713e 379 g_slist_free(device_list);
87252e1b 380
11c39b5c
RZ
381 if (state->persistence) {
382 nvdimm_build_structure_caps(structures, state->persistence);
9ab3aad2
RZ
383 }
384
87252e1b
XG
385 return structures;
386}
387
75b0713e
XG
388static void nvdimm_init_fit_buffer(NvdimmFitBuffer *fit_buf)
389{
75b0713e
XG
390 fit_buf->fit = g_array_new(false, true /* clear */, 1);
391}
392
c1404bde 393static void nvdimm_build_fit_buffer(NVDIMMState *state)
75b0713e 394{
9ab3aad2
RZ
395 NvdimmFitBuffer *fit_buf = &state->fit_buf;
396
75b0713e 397 g_array_free(fit_buf->fit, true);
9ab3aad2 398 fit_buf->fit = nvdimm_build_device_structure(state);
75b0713e 399 fit_buf->dirty = true;
75b0713e
XG
400}
401
c1404bde 402void nvdimm_plug(NVDIMMState *state)
75b0713e 403{
9ab3aad2 404 nvdimm_build_fit_buffer(state);
75b0713e
XG
405}
406
c1404bde 407static void nvdimm_build_nfit(NVDIMMState *state, GArray *table_offsets,
0e9b9eda 408 GArray *table_data, BIOSLinker *linker)
87252e1b 409{
75b0713e 410 NvdimmFitBuffer *fit_buf = &state->fit_buf;
c8e6c938 411 unsigned int header;
87252e1b
XG
412
413 acpi_add_table(table_offsets, table_data);
414
415 /* NFIT header. */
c8e6c938
HZ
416 header = table_data->len;
417 acpi_data_push(table_data, sizeof(NvdimmNfitHeader));
87252e1b 418 /* NVDIMM device structures. */
75b0713e 419 g_array_append_vals(table_data, fit_buf->fit->data, fit_buf->fit->len);
87252e1b 420
c8e6c938
HZ
421 build_header(linker, table_data,
422 (void *)(table_data->data + header), "NFIT",
75b0713e 423 sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, NULL, NULL);
87252e1b
XG
424}
425
cb88ebd7
XG
426#define NVDIMM_DSM_MEMORY_SIZE 4096
427
18c440e1
XG
428struct NvdimmDsmIn {
429 uint32_t handle;
430 uint32_t revision;
431 uint32_t function;
432 /* the remaining size in the page is used by arg3. */
433 union {
35c5a52d 434 uint8_t arg3[4084];
18c440e1
XG
435 };
436} QEMU_PACKED;
437typedef struct NvdimmDsmIn NvdimmDsmIn;
cb88ebd7 438QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmIn) != NVDIMM_DSM_MEMORY_SIZE);
18c440e1
XG
439
440struct NvdimmDsmOut {
441 /* the size of buffer filled by QEMU. */
442 uint32_t len;
35c5a52d 443 uint8_t data[4092];
18c440e1
XG
444} QEMU_PACKED;
445typedef struct NvdimmDsmOut NvdimmDsmOut;
cb88ebd7 446QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmOut) != NVDIMM_DSM_MEMORY_SIZE);
18c440e1 447
f7df22de
XG
448struct NvdimmDsmFunc0Out {
449 /* the size of buffer filled by QEMU. */
450 uint32_t len;
451 uint32_t supported_func;
452} QEMU_PACKED;
453typedef struct NvdimmDsmFunc0Out NvdimmDsmFunc0Out;
454
455struct NvdimmDsmFuncNoPayloadOut {
456 /* the size of buffer filled by QEMU. */
457 uint32_t len;
458 uint32_t func_ret_status;
459} QEMU_PACKED;
460typedef struct NvdimmDsmFuncNoPayloadOut NvdimmDsmFuncNoPayloadOut;
461
5797dcdc
XG
462struct NvdimmFuncGetLabelSizeOut {
463 /* the size of buffer filled by QEMU. */
464 uint32_t len;
465 uint32_t func_ret_status; /* return status code. */
466 uint32_t label_size; /* the size of label data area. */
467 /*
468 * Maximum size of the namespace label data length supported by
469 * the platform in Get/Set Namespace Label Data functions.
470 */
471 uint32_t max_xfer;
472} QEMU_PACKED;
473typedef struct NvdimmFuncGetLabelSizeOut NvdimmFuncGetLabelSizeOut;
cb88ebd7 474QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelSizeOut) > NVDIMM_DSM_MEMORY_SIZE);
5797dcdc 475
2b9e57fc
XG
476struct NvdimmFuncGetLabelDataIn {
477 uint32_t offset; /* the offset in the namespace label data area. */
478 uint32_t length; /* the size of data is to be read via the function. */
479} QEMU_PACKED;
480typedef struct NvdimmFuncGetLabelDataIn NvdimmFuncGetLabelDataIn;
481QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataIn) +
cb88ebd7 482 offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
2b9e57fc 483
5797dcdc
XG
484struct NvdimmFuncGetLabelDataOut {
485 /* the size of buffer filled by QEMU. */
486 uint32_t len;
487 uint32_t func_ret_status; /* return status code. */
488 uint8_t out_buf[0]; /* the data got via Get Namesapce Label function. */
489} QEMU_PACKED;
490typedef struct NvdimmFuncGetLabelDataOut NvdimmFuncGetLabelDataOut;
cb88ebd7 491QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > NVDIMM_DSM_MEMORY_SIZE);
5797dcdc
XG
492
493struct NvdimmFuncSetLabelDataIn {
494 uint32_t offset; /* the offset in the namespace label data area. */
495 uint32_t length; /* the size of data is to be written via the function. */
496 uint8_t in_buf[0]; /* the data written to label data area. */
497} QEMU_PACKED;
498typedef struct NvdimmFuncSetLabelDataIn NvdimmFuncSetLabelDataIn;
14e44198 499QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncSetLabelDataIn) +
cb88ebd7 500 offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
5797dcdc 501
806864d9 502struct NvdimmFuncReadFITIn {
7adbce63 503 uint32_t offset; /* the offset into FIT buffer. */
806864d9
XG
504} QEMU_PACKED;
505typedef struct NvdimmFuncReadFITIn NvdimmFuncReadFITIn;
506QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITIn) +
cb88ebd7 507 offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
806864d9
XG
508
509struct NvdimmFuncReadFITOut {
510 /* the size of buffer filled by QEMU. */
511 uint32_t len;
512 uint32_t func_ret_status; /* return status code. */
513 uint8_t fit[0]; /* the FIT data. */
514} QEMU_PACKED;
515typedef struct NvdimmFuncReadFITOut NvdimmFuncReadFITOut;
cb88ebd7 516QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITOut) > NVDIMM_DSM_MEMORY_SIZE);
806864d9 517
189f4d56
XG
518static void
519nvdimm_dsm_function0(uint32_t supported_func, hwaddr dsm_mem_addr)
520{
521 NvdimmDsmFunc0Out func0 = {
522 .len = cpu_to_le32(sizeof(func0)),
523 .supported_func = cpu_to_le32(supported_func),
524 };
525 cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof(func0));
526}
527
528static void
529nvdimm_dsm_no_payload(uint32_t func_ret_status, hwaddr dsm_mem_addr)
530{
531 NvdimmDsmFuncNoPayloadOut out = {
532 .len = cpu_to_le32(sizeof(out)),
533 .func_ret_status = cpu_to_le32(func_ret_status),
534 };
535 cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out));
536}
537
c2fa3075
XG
538#define NVDIMM_DSM_RET_STATUS_SUCCESS 0 /* Success */
539#define NVDIMM_DSM_RET_STATUS_UNSUPPORT 1 /* Not Supported */
540#define NVDIMM_DSM_RET_STATUS_NOMEMDEV 2 /* Non-Existing Memory Device */
541#define NVDIMM_DSM_RET_STATUS_INVALID 3 /* Invalid Input Parameters */
542#define NVDIMM_DSM_RET_STATUS_FIT_CHANGED 0x100 /* FIT Changed */
543
544#define NVDIMM_QEMU_RSVD_HANDLE_ROOT 0x10000
806864d9
XG
545
546/* Read FIT data, defined in docs/specs/acpi_nvdimm.txt. */
c1404bde 547static void nvdimm_dsm_func_read_fit(NVDIMMState *state, NvdimmDsmIn *in,
806864d9
XG
548 hwaddr dsm_mem_addr)
549{
550 NvdimmFitBuffer *fit_buf = &state->fit_buf;
551 NvdimmFuncReadFITIn *read_fit;
552 NvdimmFuncReadFITOut *read_fit_out;
553 GArray *fit;
554 uint32_t read_len = 0, func_ret_status;
555 int size;
556
557 read_fit = (NvdimmFuncReadFITIn *)in->arg3;
435cc3e4 558 read_fit->offset = le32_to_cpu(read_fit->offset);
806864d9 559
806864d9
XG
560 fit = fit_buf->fit;
561
562 nvdimm_debug("Read FIT: offset %#x FIT size %#x Dirty %s.\n",
563 read_fit->offset, fit->len, fit_buf->dirty ? "Yes" : "No");
564
565 if (read_fit->offset > fit->len) {
c2fa3075 566 func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID;
806864d9
XG
567 goto exit;
568 }
569
570 /* It is the first time to read FIT. */
571 if (!read_fit->offset) {
572 fit_buf->dirty = false;
573 } else if (fit_buf->dirty) { /* FIT has been changed during RFIT. */
c2fa3075 574 func_ret_status = NVDIMM_DSM_RET_STATUS_FIT_CHANGED;
806864d9
XG
575 goto exit;
576 }
577
c2fa3075 578 func_ret_status = NVDIMM_DSM_RET_STATUS_SUCCESS;
806864d9 579 read_len = MIN(fit->len - read_fit->offset,
cb88ebd7 580 NVDIMM_DSM_MEMORY_SIZE - sizeof(NvdimmFuncReadFITOut));
806864d9
XG
581
582exit:
583 size = sizeof(NvdimmFuncReadFITOut) + read_len;
584 read_fit_out = g_malloc(size);
585
586 read_fit_out->len = cpu_to_le32(size);
587 read_fit_out->func_ret_status = cpu_to_le32(func_ret_status);
588 memcpy(read_fit_out->fit, fit->data + read_fit->offset, read_len);
589
590 cpu_physical_memory_write(dsm_mem_addr, read_fit_out, size);
591
592 g_free(read_fit_out);
806864d9
XG
593}
594
5a33db78 595static void
c1404bde 596nvdimm_dsm_handle_reserved_root_method(NVDIMMState *state,
5a33db78 597 NvdimmDsmIn *in, hwaddr dsm_mem_addr)
806864d9
XG
598{
599 switch (in->function) {
600 case 0x0:
601 nvdimm_dsm_function0(0x1 | 1 << 1 /* Read FIT */, dsm_mem_addr);
602 return;
7adbce63 603 case 0x1 /* Read FIT */:
806864d9
XG
604 nvdimm_dsm_func_read_fit(state, in, dsm_mem_addr);
605 return;
606 }
607
c2fa3075 608 nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
806864d9
XG
609}
610
189f4d56
XG
611static void nvdimm_dsm_root(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
612{
613 /*
614 * function 0 is called to inquire which functions are supported by
615 * OSPM
616 */
617 if (!in->function) {
618 nvdimm_dsm_function0(0 /* No function supported other than
619 function 0 */, dsm_mem_addr);
620 return;
621 }
622
623 /* No function except function 0 is supported yet. */
c2fa3075 624 nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
189f4d56
XG
625}
626
5797dcdc
XG
627/*
628 * the max transfer size is the max size transferred by both a
629 * 'Get Namespace Label Data' function and a 'Set Namespace Label Data'
630 * function.
631 */
632static uint32_t nvdimm_get_max_xfer_label_size(void)
633{
cb88ebd7
XG
634 uint32_t max_get_size, max_set_size, dsm_memory_size;
635
636 dsm_memory_size = NVDIMM_DSM_MEMORY_SIZE;
5797dcdc
XG
637
638 /*
639 * the max data ACPI can read one time which is transferred by
640 * the response of 'Get Namespace Label Data' function.
641 */
642 max_get_size = dsm_memory_size - sizeof(NvdimmFuncGetLabelDataOut);
643
644 /*
645 * the max data ACPI can write one time which is transferred by
646 * 'Set Namespace Label Data' function.
647 */
648 max_set_size = dsm_memory_size - offsetof(NvdimmDsmIn, arg3) -
649 sizeof(NvdimmFuncSetLabelDataIn);
650
651 return MIN(max_get_size, max_set_size);
652}
653
654/*
655 * DSM Spec Rev1 4.4 Get Namespace Label Size (Function Index 4).
656 *
657 * It gets the size of Namespace Label data area and the max data size
658 * that Get/Set Namespace Label Data functions can transfer.
659 */
660static void nvdimm_dsm_label_size(NVDIMMDevice *nvdimm, hwaddr dsm_mem_addr)
661{
662 NvdimmFuncGetLabelSizeOut label_size_out = {
663 .len = cpu_to_le32(sizeof(label_size_out)),
664 };
665 uint32_t label_size, mxfer;
666
667 label_size = nvdimm->label_size;
668 mxfer = nvdimm_get_max_xfer_label_size();
669
670 nvdimm_debug("label_size %#x, max_xfer %#x.\n", label_size, mxfer);
671
c2fa3075 672 label_size_out.func_ret_status = cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS);
5797dcdc
XG
673 label_size_out.label_size = cpu_to_le32(label_size);
674 label_size_out.max_xfer = cpu_to_le32(mxfer);
675
676 cpu_physical_memory_write(dsm_mem_addr, &label_size_out,
677 sizeof(label_size_out));
678}
679
2b9e57fc
XG
680static uint32_t nvdimm_rw_label_data_check(NVDIMMDevice *nvdimm,
681 uint32_t offset, uint32_t length)
682{
c2fa3075 683 uint32_t ret = NVDIMM_DSM_RET_STATUS_INVALID;
2b9e57fc
XG
684
685 if (offset + length < offset) {
686 nvdimm_debug("offset %#x + length %#x is overflow.\n", offset,
687 length);
688 return ret;
689 }
690
691 if (nvdimm->label_size < offset + length) {
692 nvdimm_debug("position %#x is beyond label data (len = %" PRIx64 ").\n",
693 offset + length, nvdimm->label_size);
694 return ret;
695 }
696
697 if (length > nvdimm_get_max_xfer_label_size()) {
698 nvdimm_debug("length (%#x) is larger than max_xfer (%#x).\n",
699 length, nvdimm_get_max_xfer_label_size());
700 return ret;
701 }
702
c2fa3075 703 return NVDIMM_DSM_RET_STATUS_SUCCESS;
2b9e57fc
XG
704}
705
706/*
707 * DSM Spec Rev1 4.5 Get Namespace Label Data (Function Index 5).
708 */
709static void nvdimm_dsm_get_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
710 hwaddr dsm_mem_addr)
711{
712 NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
713 NvdimmFuncGetLabelDataIn *get_label_data;
714 NvdimmFuncGetLabelDataOut *get_label_data_out;
715 uint32_t status;
716 int size;
717
718 get_label_data = (NvdimmFuncGetLabelDataIn *)in->arg3;
435cc3e4
PM
719 get_label_data->offset = le32_to_cpu(get_label_data->offset);
720 get_label_data->length = le32_to_cpu(get_label_data->length);
2b9e57fc
XG
721
722 nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
723 get_label_data->offset, get_label_data->length);
724
725 status = nvdimm_rw_label_data_check(nvdimm, get_label_data->offset,
726 get_label_data->length);
c2fa3075 727 if (status != NVDIMM_DSM_RET_STATUS_SUCCESS) {
2b9e57fc
XG
728 nvdimm_dsm_no_payload(status, dsm_mem_addr);
729 return;
730 }
731
732 size = sizeof(*get_label_data_out) + get_label_data->length;
cb88ebd7 733 assert(size <= NVDIMM_DSM_MEMORY_SIZE);
2b9e57fc
XG
734 get_label_data_out = g_malloc(size);
735
736 get_label_data_out->len = cpu_to_le32(size);
c2fa3075
XG
737 get_label_data_out->func_ret_status =
738 cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS);
2b9e57fc
XG
739 nvc->read_label_data(nvdimm, get_label_data_out->out_buf,
740 get_label_data->length, get_label_data->offset);
741
742 cpu_physical_memory_write(dsm_mem_addr, get_label_data_out, size);
743 g_free(get_label_data_out);
744}
745
14e44198
XG
746/*
747 * DSM Spec Rev1 4.6 Set Namespace Label Data (Function Index 6).
748 */
749static void nvdimm_dsm_set_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
750 hwaddr dsm_mem_addr)
751{
752 NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
753 NvdimmFuncSetLabelDataIn *set_label_data;
754 uint32_t status;
755
756 set_label_data = (NvdimmFuncSetLabelDataIn *)in->arg3;
757
435cc3e4
PM
758 set_label_data->offset = le32_to_cpu(set_label_data->offset);
759 set_label_data->length = le32_to_cpu(set_label_data->length);
14e44198
XG
760
761 nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
762 set_label_data->offset, set_label_data->length);
763
764 status = nvdimm_rw_label_data_check(nvdimm, set_label_data->offset,
765 set_label_data->length);
c2fa3075 766 if (status != NVDIMM_DSM_RET_STATUS_SUCCESS) {
14e44198
XG
767 nvdimm_dsm_no_payload(status, dsm_mem_addr);
768 return;
769 }
770
cb88ebd7
XG
771 assert(offsetof(NvdimmDsmIn, arg3) + sizeof(*set_label_data) +
772 set_label_data->length <= NVDIMM_DSM_MEMORY_SIZE);
14e44198
XG
773
774 nvc->write_label_data(nvdimm, set_label_data->in_buf,
775 set_label_data->length, set_label_data->offset);
c2fa3075 776 nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_SUCCESS, dsm_mem_addr);
14e44198
XG
777}
778
189f4d56
XG
779static void nvdimm_dsm_device(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
780{
5797dcdc
XG
781 NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(in->handle);
782
189f4d56
XG
783 /* See the comments in nvdimm_dsm_root(). */
784 if (!in->function) {
5797dcdc
XG
785 uint32_t supported_func = 0;
786
787 if (nvdimm && nvdimm->label_size) {
788 supported_func |= 0x1 /* Bit 0 indicates whether there is
789 support for any functions other
790 than function 0. */ |
2b9e57fc 791 1 << 4 /* Get Namespace Label Size */ |
14e44198
XG
792 1 << 5 /* Get Namespace Label Data */ |
793 1 << 6 /* Set Namespace Label Data */;
5797dcdc
XG
794 }
795 nvdimm_dsm_function0(supported_func, dsm_mem_addr);
189f4d56
XG
796 return;
797 }
798
5797dcdc 799 if (!nvdimm) {
c2fa3075 800 nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_NOMEMDEV,
5797dcdc
XG
801 dsm_mem_addr);
802 return;
803 }
804
805 /* Encode DSM function according to DSM Spec Rev1. */
806 switch (in->function) {
807 case 4 /* Get Namespace Label Size */:
808 if (nvdimm->label_size) {
809 nvdimm_dsm_label_size(nvdimm, dsm_mem_addr);
810 return;
811 }
812 break;
2b9e57fc
XG
813 case 5 /* Get Namespace Label Data */:
814 if (nvdimm->label_size) {
815 nvdimm_dsm_get_label_data(nvdimm, in, dsm_mem_addr);
816 return;
817 }
818 break;
14e44198
XG
819 case 0x6 /* Set Namespace Label Data */:
820 if (nvdimm->label_size) {
821 nvdimm_dsm_set_label_data(nvdimm, in, dsm_mem_addr);
822 return;
823 }
824 break;
5797dcdc
XG
825 }
826
c2fa3075 827 nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
189f4d56
XG
828}
829
5fe79386
XG
830static uint64_t
831nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
832{
f7df22de 833 nvdimm_debug("BUG: we never read _DSM IO Port.\n");
5fe79386
XG
834 return 0;
835}
836
837static void
838nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
839{
c1404bde 840 NVDIMMState *state = opaque;
f7df22de
XG
841 NvdimmDsmIn *in;
842 hwaddr dsm_mem_addr = val;
843
844 nvdimm_debug("dsm memory address %#" HWADDR_PRIx ".\n", dsm_mem_addr);
845
846 /*
847 * The DSM memory is mapped to guest address space so an evil guest
848 * can change its content while we are doing DSM emulation. Avoid
849 * this by copying DSM memory to QEMU local memory.
850 */
35c5a52d
PB
851 in = g_new(NvdimmDsmIn, 1);
852 cpu_physical_memory_read(dsm_mem_addr, in, sizeof(*in));
f7df22de 853
435cc3e4
PM
854 in->revision = le32_to_cpu(in->revision);
855 in->function = le32_to_cpu(in->function);
856 in->handle = le32_to_cpu(in->handle);
f7df22de
XG
857
858 nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
859 in->handle, in->function);
860
d15fc53f
XG
861 if (in->revision != 0x1 /* Currently we only support DSM Spec Rev1. */) {
862 nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
863 in->revision, 0x1);
c2fa3075 864 nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
d15fc53f
XG
865 goto exit;
866 }
867
806864d9 868 if (in->handle == NVDIMM_QEMU_RSVD_HANDLE_ROOT) {
5a33db78 869 nvdimm_dsm_handle_reserved_root_method(state, in, dsm_mem_addr);
806864d9
XG
870 goto exit;
871 }
872
189f4d56
XG
873 /* Handle 0 is reserved for NVDIMM Root Device. */
874 if (!in->handle) {
875 nvdimm_dsm_root(in, dsm_mem_addr);
876 goto exit;
f7df22de
XG
877 }
878
189f4d56
XG
879 nvdimm_dsm_device(in, dsm_mem_addr);
880
881exit:
f7df22de 882 g_free(in);
5fe79386
XG
883}
884
885static const MemoryRegionOps nvdimm_dsm_ops = {
886 .read = nvdimm_dsm_read,
887 .write = nvdimm_dsm_write,
888 .endianness = DEVICE_LITTLE_ENDIAN,
889 .valid = {
890 .min_access_size = 4,
891 .max_access_size = 4,
892 },
893};
894
75f27498
XG
895void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev)
896{
897 if (dev->hotplugged) {
898 acpi_send_event(DEVICE(hotplug_dev), ACPI_NVDIMM_HOTPLUG_STATUS);
899 }
900}
901
c1404bde 902void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io,
5fe79386
XG
903 FWCfgState *fw_cfg, Object *owner)
904{
905 memory_region_init_io(&state->io_mr, owner, &nvdimm_dsm_ops, state,
906 "nvdimm-acpi-io", NVDIMM_ACPI_IO_LEN);
907 memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, &state->io_mr);
908
909 state->dsm_mem = g_array_new(false, true /* clear */, 1);
35c5a52d 910 acpi_data_push(state->dsm_mem, sizeof(NvdimmDsmIn));
5fe79386
XG
911 fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data,
912 state->dsm_mem->len);
75b0713e
XG
913
914 nvdimm_init_fit_buffer(&state->fit_buf);
5fe79386
XG
915}
916
3ae66c45
XG
917#define NVDIMM_COMMON_DSM "NCAL"
918#define NVDIMM_ACPI_MEM_ADDR "MEMA"
919
920#define NVDIMM_DSM_MEMORY "NRAM"
921#define NVDIMM_DSM_IOPORT "NPIO"
922
923#define NVDIMM_DSM_NOTIFY "NTFI"
924#define NVDIMM_DSM_HANDLE "HDLE"
925#define NVDIMM_DSM_REVISION "REVS"
926#define NVDIMM_DSM_FUNCTION "FUNC"
927#define NVDIMM_DSM_ARG3 "FARG"
928
929#define NVDIMM_DSM_OUT_BUF_SIZE "RLEN"
930#define NVDIMM_DSM_OUT_BUF "ODAT"
77286395 931
806864d9
XG
932#define NVDIMM_DSM_RFIT_STATUS "RSTA"
933
934#define NVDIMM_QEMU_RSVD_UUID "648B9CF2-CDA1-4312-8AD9-49C4AF32BD62"
935
77286395
XG
936static void nvdimm_build_common_dsm(Aml *dev)
937{
806864d9 938 Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *elsectx2;
90623ebf 939 Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid;
fa1a448d 940 Aml *pckg, *pckg_index, *pckg_buf, *field, *dsm_out_buf, *dsm_out_buf_size;
77286395
XG
941 uint8_t byte_list[1];
942
732b530c 943 method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED);
90623ebf 944 uuid = aml_arg(0);
77286395 945 function = aml_arg(2);
90623ebf 946 handle = aml_arg(4);
c0b3b863 947 dsm_mem = aml_local(6);
48bee476 948 dsm_out_buf = aml_local(7);
c0b3b863
XG
949
950 aml_append(method, aml_store(aml_name(NVDIMM_ACPI_MEM_ADDR), dsm_mem));
951
952 /* map DSM memory and IO into ACPI namespace. */
3ae66c45 953 aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, AML_SYSTEM_IO,
c0b3b863 954 aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN));
3ae66c45
XG
955 aml_append(method, aml_operation_region(NVDIMM_DSM_MEMORY,
956 AML_SYSTEM_MEMORY, dsm_mem, sizeof(NvdimmDsmIn)));
c0b3b863
XG
957
958 /*
959 * DSM notifier:
3ae66c45
XG
960 * NVDIMM_DSM_NOTIFY: write the address of DSM memory and notify QEMU to
961 * emulate the access.
c0b3b863
XG
962 *
963 * It is the IO port so that accessing them will cause VM-exit, the
964 * control will be transferred to QEMU.
965 */
3ae66c45
XG
966 field = aml_field(NVDIMM_DSM_IOPORT, AML_DWORD_ACC, AML_NOLOCK,
967 AML_PRESERVE);
968 aml_append(field, aml_named_field(NVDIMM_DSM_NOTIFY,
1b8fff57 969 NVDIMM_ACPI_IO_LEN * BITS_PER_BYTE));
c0b3b863
XG
970 aml_append(method, field);
971
972 /*
973 * DSM input:
3ae66c45
XG
974 * NVDIMM_DSM_HANDLE: store device's handle, it's zero if the _DSM call
975 * happens on NVDIMM Root Device.
976 * NVDIMM_DSM_REVISION: store the Arg1 of _DSM call.
977 * NVDIMM_DSM_FUNCTION: store the Arg2 of _DSM call.
978 * NVDIMM_DSM_ARG3: store the Arg3 of _DSM call which is a Package
979 * containing function-specific arguments.
c0b3b863
XG
980 *
981 * They are RAM mapping on host so that these accesses never cause
982 * VM-EXIT.
983 */
3ae66c45
XG
984 field = aml_field(NVDIMM_DSM_MEMORY, AML_DWORD_ACC, AML_NOLOCK,
985 AML_PRESERVE);
986 aml_append(field, aml_named_field(NVDIMM_DSM_HANDLE,
c0b3b863 987 sizeof(typeof_field(NvdimmDsmIn, handle)) * BITS_PER_BYTE));
3ae66c45 988 aml_append(field, aml_named_field(NVDIMM_DSM_REVISION,
c0b3b863 989 sizeof(typeof_field(NvdimmDsmIn, revision)) * BITS_PER_BYTE));
3ae66c45 990 aml_append(field, aml_named_field(NVDIMM_DSM_FUNCTION,
c0b3b863 991 sizeof(typeof_field(NvdimmDsmIn, function)) * BITS_PER_BYTE));
3ae66c45 992 aml_append(field, aml_named_field(NVDIMM_DSM_ARG3,
c0b3b863
XG
993 (sizeof(NvdimmDsmIn) - offsetof(NvdimmDsmIn, arg3)) * BITS_PER_BYTE));
994 aml_append(method, field);
995
996 /*
997 * DSM output:
3ae66c45
XG
998 * NVDIMM_DSM_OUT_BUF_SIZE: the size of the buffer filled by QEMU.
999 * NVDIMM_DSM_OUT_BUF: the buffer QEMU uses to store the result.
c0b3b863
XG
1000 *
1001 * Since the page is reused by both input and out, the input data
1002 * will be lost after storing new result into ODAT so we should fetch
1003 * all the input data before writing the result.
1004 */
3ae66c45
XG
1005 field = aml_field(NVDIMM_DSM_MEMORY, AML_DWORD_ACC, AML_NOLOCK,
1006 AML_PRESERVE);
1007 aml_append(field, aml_named_field(NVDIMM_DSM_OUT_BUF_SIZE,
c0b3b863 1008 sizeof(typeof_field(NvdimmDsmOut, len)) * BITS_PER_BYTE));
3ae66c45 1009 aml_append(field, aml_named_field(NVDIMM_DSM_OUT_BUF,
c0b3b863
XG
1010 (sizeof(NvdimmDsmOut) - offsetof(NvdimmDsmOut, data)) * BITS_PER_BYTE));
1011 aml_append(method, field);
18c440e1
XG
1012
1013 /*
1014 * do not support any method if DSM memory address has not been
1015 * patched.
1016 */
90623ebf
XG
1017 unpatched = aml_equal(dsm_mem, aml_int(0x0));
1018
1019 expected_uuid = aml_local(0);
1020
1021 ifctx = aml_if(aml_equal(handle, aml_int(0x0)));
1022 aml_append(ifctx, aml_store(
1023 aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA")
1024 /* UUID for NVDIMM Root Device */, expected_uuid));
1025 aml_append(method, ifctx);
1026 elsectx = aml_else();
806864d9
XG
1027 ifctx = aml_if(aml_equal(handle, aml_int(NVDIMM_QEMU_RSVD_HANDLE_ROOT)));
1028 aml_append(ifctx, aml_store(aml_touuid(NVDIMM_QEMU_RSVD_UUID
1029 /* UUID for QEMU internal use */), expected_uuid));
1030 aml_append(elsectx, ifctx);
1031 elsectx2 = aml_else();
1032 aml_append(elsectx2, aml_store(
90623ebf
XG
1033 aml_touuid("4309AC30-0D11-11E4-9191-0800200C9A66")
1034 /* UUID for NVDIMM Devices */, expected_uuid));
806864d9 1035 aml_append(elsectx, elsectx2);
90623ebf
XG
1036 aml_append(method, elsectx);
1037
1038 uuid_invalid = aml_lnot(aml_equal(uuid, expected_uuid));
1039
1040 unsupport = aml_if(aml_or(unpatched, uuid_invalid, NULL));
77286395
XG
1041
1042 /*
1043 * function 0 is called to inquire what functions are supported by
1044 * OSPM
1045 */
1046 ifctx = aml_if(aml_equal(function, aml_int(0)));
1047 byte_list[0] = 0 /* No function Supported */;
1048 aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
90623ebf 1049 aml_append(unsupport, ifctx);
77286395
XG
1050
1051 /* No function is supported yet. */
c2fa3075 1052 byte_list[0] = NVDIMM_DSM_RET_STATUS_UNSUPPORT;
90623ebf
XG
1053 aml_append(unsupport, aml_return(aml_buffer(1, byte_list)));
1054 aml_append(method, unsupport);
77286395 1055
18c440e1
XG
1056 /*
1057 * The HDLE indicates the DSM function is issued from which device,
732b530c
XG
1058 * it reserves 0 for root device and is the handle for NVDIMM devices.
1059 * See the comments in nvdimm_slot_to_handle().
18c440e1 1060 */
3ae66c45
XG
1061 aml_append(method, aml_store(handle, aml_name(NVDIMM_DSM_HANDLE)));
1062 aml_append(method, aml_store(aml_arg(1), aml_name(NVDIMM_DSM_REVISION)));
ac265cac 1063 aml_append(method, aml_store(function, aml_name(NVDIMM_DSM_FUNCTION)));
18c440e1 1064
4568c948
XG
1065 /*
1066 * The fourth parameter (Arg3) of _DSM is a package which contains
1067 * a buffer, the layout of the buffer is specified by UUID (Arg0),
1068 * Revision ID (Arg1) and Function Index (Arg2) which are documented
1069 * in the DSM Spec.
1070 */
1071 pckg = aml_arg(3);
1072 ifctx = aml_if(aml_and(aml_equal(aml_object_type(pckg),
1073 aml_int(4 /* Package */)) /* It is a Package? */,
1074 aml_equal(aml_sizeof(pckg), aml_int(1)) /* 1 element? */,
1075 NULL));
1076
1077 pckg_index = aml_local(2);
1078 pckg_buf = aml_local(3);
1079 aml_append(ifctx, aml_store(aml_index(pckg, aml_int(0)), pckg_index));
1080 aml_append(ifctx, aml_store(aml_derefof(pckg_index), pckg_buf));
3ae66c45 1081 aml_append(ifctx, aml_store(pckg_buf, aml_name(NVDIMM_DSM_ARG3)));
4568c948
XG
1082 aml_append(method, ifctx);
1083
18c440e1
XG
1084 /*
1085 * tell QEMU about the real address of DSM memory, then QEMU
1086 * gets the control and fills the result in DSM memory.
1087 */
3ae66c45 1088 aml_append(method, aml_store(dsm_mem, aml_name(NVDIMM_DSM_NOTIFY)));
18c440e1 1089
fa1a448d 1090 dsm_out_buf_size = aml_local(1);
d51d1d7e 1091 /* RLEN is not included in the payload returned to guest. */
3ae66c45
XG
1092 aml_append(method, aml_subtract(aml_name(NVDIMM_DSM_OUT_BUF_SIZE),
1093 aml_int(4), dsm_out_buf_size));
fa1a448d
XG
1094 aml_append(method, aml_store(aml_shiftleft(dsm_out_buf_size, aml_int(3)),
1095 dsm_out_buf_size));
3ae66c45
XG
1096 aml_append(method, aml_create_field(aml_name(NVDIMM_DSM_OUT_BUF),
1097 aml_int(0), dsm_out_buf_size, "OBUF"));
18c440e1 1098 aml_append(method, aml_concatenate(aml_buffer(0, NULL), aml_name("OBUF"),
48bee476
XG
1099 dsm_out_buf));
1100 aml_append(method, aml_return(dsm_out_buf));
77286395
XG
1101 aml_append(dev, method);
1102}
1103
732b530c 1104static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
77286395
XG
1105{
1106 Aml *method;
1107
1108 method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
732b530c
XG
1109 aml_append(method, aml_return(aml_call5(NVDIMM_COMMON_DSM, aml_arg(0),
1110 aml_arg(1), aml_arg(2), aml_arg(3),
1111 aml_int(handle))));
77286395
XG
1112 aml_append(dev, method);
1113}
1114
806864d9
XG
1115static void nvdimm_build_fit(Aml *dev)
1116{
1117 Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
1118 Aml *whilectx, *ifcond, *ifctx, *elsectx, *fit;
1119
1120 buf = aml_local(0);
1121 buf_size = aml_local(1);
1122 fit = aml_local(2);
1123
aef056c1 1124 aml_append(dev, aml_name_decl(NVDIMM_DSM_RFIT_STATUS, aml_int(0)));
806864d9
XG
1125
1126 /* build helper function, RFIT. */
1127 method = aml_method("RFIT", 1, AML_SERIALIZED);
aef056c1 1128 aml_append(method, aml_name_decl("OFST", aml_int(0)));
806864d9
XG
1129
1130 /* prepare input package. */
1131 pkg = aml_package(1);
1132 aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
1133 aml_append(pkg, aml_name("OFST"));
1134
1135 /* call Read_FIT function. */
1136 call_result = aml_call5(NVDIMM_COMMON_DSM,
1137 aml_touuid(NVDIMM_QEMU_RSVD_UUID),
1138 aml_int(1) /* Revision 1 */,
1139 aml_int(0x1) /* Read FIT */,
1140 pkg, aml_int(NVDIMM_QEMU_RSVD_HANDLE_ROOT));
1141 aml_append(method, aml_store(call_result, buf));
1142
1143 /* handle _DSM result. */
1144 aml_append(method, aml_create_dword_field(buf,
1145 aml_int(0) /* offset at byte 0 */, "STAU"));
1146
1147 aml_append(method, aml_store(aml_name("STAU"),
1148 aml_name(NVDIMM_DSM_RFIT_STATUS)));
1149
1150 /* if something is wrong during _DSM. */
c2fa3075
XG
1151 ifcond = aml_equal(aml_int(NVDIMM_DSM_RET_STATUS_SUCCESS),
1152 aml_name("STAU"));
806864d9
XG
1153 ifctx = aml_if(aml_lnot(ifcond));
1154 aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
1155 aml_append(method, ifctx);
1156
1157 aml_append(method, aml_store(aml_sizeof(buf), buf_size));
1158 aml_append(method, aml_subtract(buf_size,
1159 aml_int(4) /* the size of "STAU" */,
1160 buf_size));
1161
1162 /* if we read the end of fit. */
1163 ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
1164 aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
1165 aml_append(method, ifctx);
1166
806864d9
XG
1167 aml_append(method, aml_create_field(buf,
1168 aml_int(4 * BITS_PER_BYTE), /* offset at byte 4.*/
880f3612 1169 aml_shiftleft(buf_size, aml_int(3)), "BUFF"));
806864d9
XG
1170 aml_append(method, aml_return(aml_name("BUFF")));
1171 aml_append(dev, method);
1172
1173 /* build _FIT. */
1174 method = aml_method("_FIT", 0, AML_SERIALIZED);
1175 offset = aml_local(3);
1176
1177 aml_append(method, aml_store(aml_buffer(0, NULL), fit));
1178 aml_append(method, aml_store(aml_int(0), offset));
1179
1180 whilectx = aml_while(aml_int(1));
1181 aml_append(whilectx, aml_store(aml_call1("RFIT", offset), buf));
1182 aml_append(whilectx, aml_store(aml_sizeof(buf), buf_size));
1183
1184 /*
1185 * if fit buffer was changed during RFIT, read from the beginning
1186 * again.
1187 */
1188 ifctx = aml_if(aml_equal(aml_name(NVDIMM_DSM_RFIT_STATUS),
c2fa3075 1189 aml_int(NVDIMM_DSM_RET_STATUS_FIT_CHANGED)));
806864d9
XG
1190 aml_append(ifctx, aml_store(aml_buffer(0, NULL), fit));
1191 aml_append(ifctx, aml_store(aml_int(0), offset));
1192 aml_append(whilectx, ifctx);
1193
1194 elsectx = aml_else();
1195
1196 /* finish fit read if no data is read out. */
1197 ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
1198 aml_append(ifctx, aml_return(fit));
1199 aml_append(elsectx, ifctx);
1200
1201 /* update the offset. */
1202 aml_append(elsectx, aml_add(offset, buf_size, offset));
1203 /* append the data we read out to the fit buffer. */
1204 aml_append(elsectx, aml_concatenate(fit, buf, fit));
1205 aml_append(whilectx, elsectx);
1206 aml_append(method, whilectx);
1207
1208 aml_append(dev, method);
1209}
1210
bdfd065b 1211static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots)
77286395 1212{
bdfd065b
XG
1213 uint32_t slot;
1214
1215 for (slot = 0; slot < ram_slots; slot++) {
77286395
XG
1216 uint32_t handle = nvdimm_slot_to_handle(slot);
1217 Aml *nvdimm_dev;
1218
1219 nvdimm_dev = aml_device("NV%02X", slot);
1220
1221 /*
1222 * ACPI 6.0: 9.20 NVDIMM Devices:
1223 *
1224 * _ADR object that is used to supply OSPM with unique address
1225 * of the NVDIMM device. This is done by returning the NFIT Device
1226 * handle that is used to identify the associated entries in ACPI
1227 * table NFIT or _FIT.
1228 */
1229 aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
1230
732b530c 1231 nvdimm_build_device_dsm(nvdimm_dev, handle);
77286395
XG
1232 aml_append(root_dev, nvdimm_dev);
1233 }
1234}
1235
bdfd065b 1236static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
b096c114 1237 BIOSLinker *linker, GArray *dsm_dma_area,
bdfd065b 1238 uint32_t ram_slots)
77286395 1239{
c0b3b863 1240 Aml *ssdt, *sb_scope, *dev;
b9951413 1241 int mem_addr_offset, nvdimm_ssdt;
77286395
XG
1242
1243 acpi_add_table(table_offsets, table_data);
1244
1245 ssdt = init_aml_allocator();
1246 acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
1247
1248 sb_scope = aml_scope("\\_SB");
1249
1250 dev = aml_device("NVDR");
1251
1252 /*
1253 * ACPI 6.0: 9.20 NVDIMM Devices:
1254 *
1255 * The ACPI Name Space device uses _HID of ACPI0012 to identify the root
1256 * NVDIMM interface device. Platform firmware is required to contain one
1257 * such device in _SB scope if NVDIMMs support is exposed by platform to
1258 * OSPM.
1259 * For each NVDIMM present or intended to be supported by platform,
1260 * platform firmware also exposes an ACPI Namespace Device under the
1261 * root device.
1262 */
1263 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
1264
1265 nvdimm_build_common_dsm(dev);
732b530c
XG
1266
1267 /* 0 is reserved for root device. */
1268 nvdimm_build_device_dsm(dev, 0);
806864d9 1269 nvdimm_build_fit(dev);
77286395 1270
bdfd065b 1271 nvdimm_build_nvdimm_devices(dev, ram_slots);
77286395
XG
1272
1273 aml_append(sb_scope, dev);
77286395 1274 aml_append(ssdt, sb_scope);
b9951413
XG
1275
1276 nvdimm_ssdt = table_data->len;
1277
77286395
XG
1278 /* copy AML table into ACPI tables blob and patch header there */
1279 g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
b9951413
XG
1280 mem_addr_offset = build_append_named_dword(table_data,
1281 NVDIMM_ACPI_MEM_ADDR);
1282
ad9671b8 1283 bios_linker_loader_alloc(linker,
b096c114 1284 NVDIMM_DSM_MEM_FILE, dsm_dma_area,
ad9671b8 1285 sizeof(NvdimmDsmIn), false /* high memory */);
4678124b
IM
1286 bios_linker_loader_add_pointer(linker,
1287 ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
1288 NVDIMM_DSM_MEM_FILE, 0);
77286395 1289 build_header(linker, table_data,
b9951413
XG
1290 (void *)(table_data->data + nvdimm_ssdt),
1291 "SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
77286395
XG
1292 free_aml_allocator();
1293}
1294
87252e1b 1295void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
c1404bde 1296 BIOSLinker *linker, NVDIMMState *state,
bdfd065b 1297 uint32_t ram_slots)
87252e1b 1298{
264813cb 1299 GSList *device_list;
bdfd065b 1300
264813cb
XG
1301 /* no nvdimm device can be plugged. */
1302 if (!ram_slots) {
1303 return;
87252e1b 1304 }
264813cb
XG
1305
1306 nvdimm_build_ssdt(table_offsets, table_data, linker, state->dsm_mem,
1307 ram_slots);
1308
cf7c0ff5 1309 device_list = nvdimm_get_device_list();
264813cb
XG
1310 /* no NVDIMM device is plugged. */
1311 if (!device_list) {
1312 return;
1313 }
1314
1315 nvdimm_build_nfit(state, table_offsets, table_data, linker);
1316 g_slist_free(device_list);
87252e1b 1317}