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