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_int(OBJECT(dev), PC_DIMM_ADDR_PROP,
 240                                            NULL);
 241    uint64_t size = object_property_get_int(OBJECT(dev), PC_DIMM_SIZE_PROP,
 242                                            NULL);
 243    uint32_t node = object_property_get_int(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_int(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(0x201 /* Format Interface Code. See Chapter
 342                                         2: NVDIMM Device Specific Method
 343                                         (DSM) in DSM Spec Rev1.*/);
 344}
 345
 346static GArray *nvdimm_build_device_structure(void)
 347{
 348    GSList *device_list = nvdimm_get_device_list();
 349    GArray *structures = g_array_new(false, true /* clear */, 1);
 350
 351    for (; device_list; device_list = device_list->next) {
 352        DeviceState *dev = device_list->data;
 353
 354        /* build System Physical Address Range Structure. */
 355        nvdimm_build_structure_spa(structures, dev);
 356
 357        /*
 358         * build Memory Device to System Physical Address Range Mapping
 359         * Structure.
 360         */
 361        nvdimm_build_structure_memdev(structures, dev);
 362
 363        /* build NVDIMM Control Region Structure. */
 364        nvdimm_build_structure_dcr(structures, dev);
 365    }
 366    g_slist_free(device_list);
 367
 368    return structures;
 369}
 370
 371static void nvdimm_init_fit_buffer(NvdimmFitBuffer *fit_buf)
 372{
 373    fit_buf->fit = g_array_new(false, true /* clear */, 1);
 374}
 375
 376static void nvdimm_build_fit_buffer(NvdimmFitBuffer *fit_buf)
 377{
 378    g_array_free(fit_buf->fit, true);
 379    fit_buf->fit = nvdimm_build_device_structure();
 380    fit_buf->dirty = true;
 381}
 382
 383void nvdimm_plug(AcpiNVDIMMState *state)
 384{
 385    nvdimm_build_fit_buffer(&state->fit_buf);
 386}
 387
 388static void nvdimm_build_nfit(AcpiNVDIMMState *state, GArray *table_offsets,
 389                              GArray *table_data, BIOSLinker *linker)
 390{
 391    NvdimmFitBuffer *fit_buf = &state->fit_buf;
 392    unsigned int header;
 393
 394    acpi_add_table(table_offsets, table_data);
 395
 396    /* NFIT header. */
 397    header = table_data->len;
 398    acpi_data_push(table_data, sizeof(NvdimmNfitHeader));
 399    /* NVDIMM device structures. */
 400    g_array_append_vals(table_data, fit_buf->fit->data, fit_buf->fit->len);
 401
 402    build_header(linker, table_data,
 403                 (void *)(table_data->data + header), "NFIT",
 404                 sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, NULL, NULL);
 405}
 406
 407#define NVDIMM_DSM_MEMORY_SIZE      4096
 408
 409struct NvdimmDsmIn {
 410    uint32_t handle;
 411    uint32_t revision;
 412    uint32_t function;
 413    /* the remaining size in the page is used by arg3. */
 414    union {
 415        uint8_t arg3[4084];
 416    };
 417} QEMU_PACKED;
 418typedef struct NvdimmDsmIn NvdimmDsmIn;
 419QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmIn) != NVDIMM_DSM_MEMORY_SIZE);
 420
 421struct NvdimmDsmOut {
 422    /* the size of buffer filled by QEMU. */
 423    uint32_t len;
 424    uint8_t data[4092];
 425} QEMU_PACKED;
 426typedef struct NvdimmDsmOut NvdimmDsmOut;
 427QEMU_BUILD_BUG_ON(sizeof(NvdimmDsmOut) != NVDIMM_DSM_MEMORY_SIZE);
 428
 429struct NvdimmDsmFunc0Out {
 430    /* the size of buffer filled by QEMU. */
 431     uint32_t len;
 432     uint32_t supported_func;
 433} QEMU_PACKED;
 434typedef struct NvdimmDsmFunc0Out NvdimmDsmFunc0Out;
 435
 436struct NvdimmDsmFuncNoPayloadOut {
 437    /* the size of buffer filled by QEMU. */
 438     uint32_t len;
 439     uint32_t func_ret_status;
 440} QEMU_PACKED;
 441typedef struct NvdimmDsmFuncNoPayloadOut NvdimmDsmFuncNoPayloadOut;
 442
 443struct NvdimmFuncGetLabelSizeOut {
 444    /* the size of buffer filled by QEMU. */
 445    uint32_t len;
 446    uint32_t func_ret_status; /* return status code. */
 447    uint32_t label_size; /* the size of label data area. */
 448    /*
 449     * Maximum size of the namespace label data length supported by
 450     * the platform in Get/Set Namespace Label Data functions.
 451     */
 452    uint32_t max_xfer;
 453} QEMU_PACKED;
 454typedef struct NvdimmFuncGetLabelSizeOut NvdimmFuncGetLabelSizeOut;
 455QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelSizeOut) > NVDIMM_DSM_MEMORY_SIZE);
 456
 457struct NvdimmFuncGetLabelDataIn {
 458    uint32_t offset; /* the offset in the namespace label data area. */
 459    uint32_t length; /* the size of data is to be read via the function. */
 460} QEMU_PACKED;
 461typedef struct NvdimmFuncGetLabelDataIn NvdimmFuncGetLabelDataIn;
 462QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataIn) +
 463                  offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
 464
 465struct NvdimmFuncGetLabelDataOut {
 466    /* the size of buffer filled by QEMU. */
 467    uint32_t len;
 468    uint32_t func_ret_status; /* return status code. */
 469    uint8_t out_buf[0]; /* the data got via Get Namesapce Label function. */
 470} QEMU_PACKED;
 471typedef struct NvdimmFuncGetLabelDataOut NvdimmFuncGetLabelDataOut;
 472QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncGetLabelDataOut) > NVDIMM_DSM_MEMORY_SIZE);
 473
 474struct NvdimmFuncSetLabelDataIn {
 475    uint32_t offset; /* the offset in the namespace label data area. */
 476    uint32_t length; /* the size of data is to be written via the function. */
 477    uint8_t in_buf[0]; /* the data written to label data area. */
 478} QEMU_PACKED;
 479typedef struct NvdimmFuncSetLabelDataIn NvdimmFuncSetLabelDataIn;
 480QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncSetLabelDataIn) +
 481                  offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
 482
 483struct NvdimmFuncReadFITIn {
 484    uint32_t offset; /* the offset into FIT buffer. */
 485} QEMU_PACKED;
 486typedef struct NvdimmFuncReadFITIn NvdimmFuncReadFITIn;
 487QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITIn) +
 488                  offsetof(NvdimmDsmIn, arg3) > NVDIMM_DSM_MEMORY_SIZE);
 489
 490struct NvdimmFuncReadFITOut {
 491    /* the size of buffer filled by QEMU. */
 492    uint32_t len;
 493    uint32_t func_ret_status; /* return status code. */
 494    uint8_t fit[0]; /* the FIT data. */
 495} QEMU_PACKED;
 496typedef struct NvdimmFuncReadFITOut NvdimmFuncReadFITOut;
 497QEMU_BUILD_BUG_ON(sizeof(NvdimmFuncReadFITOut) > NVDIMM_DSM_MEMORY_SIZE);
 498
 499static void
 500nvdimm_dsm_function0(uint32_t supported_func, hwaddr dsm_mem_addr)
 501{
 502    NvdimmDsmFunc0Out func0 = {
 503        .len = cpu_to_le32(sizeof(func0)),
 504        .supported_func = cpu_to_le32(supported_func),
 505    };
 506    cpu_physical_memory_write(dsm_mem_addr, &func0, sizeof(func0));
 507}
 508
 509static void
 510nvdimm_dsm_no_payload(uint32_t func_ret_status, hwaddr dsm_mem_addr)
 511{
 512    NvdimmDsmFuncNoPayloadOut out = {
 513        .len = cpu_to_le32(sizeof(out)),
 514        .func_ret_status = cpu_to_le32(func_ret_status),
 515    };
 516    cpu_physical_memory_write(dsm_mem_addr, &out, sizeof(out));
 517}
 518
 519#define NVDIMM_DSM_RET_STATUS_SUCCESS        0 /* Success */
 520#define NVDIMM_DSM_RET_STATUS_UNSUPPORT      1 /* Not Supported */
 521#define NVDIMM_DSM_RET_STATUS_NOMEMDEV       2 /* Non-Existing Memory Device */
 522#define NVDIMM_DSM_RET_STATUS_INVALID        3 /* Invalid Input Parameters */
 523#define NVDIMM_DSM_RET_STATUS_FIT_CHANGED    0x100 /* FIT Changed */
 524
 525#define NVDIMM_QEMU_RSVD_HANDLE_ROOT         0x10000
 526
 527/* Read FIT data, defined in docs/specs/acpi_nvdimm.txt. */
 528static void nvdimm_dsm_func_read_fit(AcpiNVDIMMState *state, NvdimmDsmIn *in,
 529                                     hwaddr dsm_mem_addr)
 530{
 531    NvdimmFitBuffer *fit_buf = &state->fit_buf;
 532    NvdimmFuncReadFITIn *read_fit;
 533    NvdimmFuncReadFITOut *read_fit_out;
 534    GArray *fit;
 535    uint32_t read_len = 0, func_ret_status;
 536    int size;
 537
 538    read_fit = (NvdimmFuncReadFITIn *)in->arg3;
 539    le32_to_cpus(&read_fit->offset);
 540
 541    fit = fit_buf->fit;
 542
 543    nvdimm_debug("Read FIT: offset %#x FIT size %#x Dirty %s.\n",
 544                 read_fit->offset, fit->len, fit_buf->dirty ? "Yes" : "No");
 545
 546    if (read_fit->offset > fit->len) {
 547        func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID;
 548        goto exit;
 549    }
 550
 551    /* It is the first time to read FIT. */
 552    if (!read_fit->offset) {
 553        fit_buf->dirty = false;
 554    } else if (fit_buf->dirty) { /* FIT has been changed during RFIT. */
 555        func_ret_status = NVDIMM_DSM_RET_STATUS_FIT_CHANGED;
 556        goto exit;
 557    }
 558
 559    func_ret_status = NVDIMM_DSM_RET_STATUS_SUCCESS;
 560    read_len = MIN(fit->len - read_fit->offset,
 561                   NVDIMM_DSM_MEMORY_SIZE - sizeof(NvdimmFuncReadFITOut));
 562
 563exit:
 564    size = sizeof(NvdimmFuncReadFITOut) + read_len;
 565    read_fit_out = g_malloc(size);
 566
 567    read_fit_out->len = cpu_to_le32(size);
 568    read_fit_out->func_ret_status = cpu_to_le32(func_ret_status);
 569    memcpy(read_fit_out->fit, fit->data + read_fit->offset, read_len);
 570
 571    cpu_physical_memory_write(dsm_mem_addr, read_fit_out, size);
 572
 573    g_free(read_fit_out);
 574}
 575
 576static void
 577nvdimm_dsm_handle_reserved_root_method(AcpiNVDIMMState *state,
 578                                       NvdimmDsmIn *in, hwaddr dsm_mem_addr)
 579{
 580    switch (in->function) {
 581    case 0x0:
 582        nvdimm_dsm_function0(0x1 | 1 << 1 /* Read FIT */, dsm_mem_addr);
 583        return;
 584    case 0x1 /* Read FIT */:
 585        nvdimm_dsm_func_read_fit(state, in, dsm_mem_addr);
 586        return;
 587    }
 588
 589    nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
 590}
 591
 592static void nvdimm_dsm_root(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
 593{
 594    /*
 595     * function 0 is called to inquire which functions are supported by
 596     * OSPM
 597     */
 598    if (!in->function) {
 599        nvdimm_dsm_function0(0 /* No function supported other than
 600                                  function 0 */, dsm_mem_addr);
 601        return;
 602    }
 603
 604    /* No function except function 0 is supported yet. */
 605    nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
 606}
 607
 608/*
 609 * the max transfer size is the max size transferred by both a
 610 * 'Get Namespace Label Data' function and a 'Set Namespace Label Data'
 611 * function.
 612 */
 613static uint32_t nvdimm_get_max_xfer_label_size(void)
 614{
 615    uint32_t max_get_size, max_set_size, dsm_memory_size;
 616
 617    dsm_memory_size = NVDIMM_DSM_MEMORY_SIZE;
 618
 619    /*
 620     * the max data ACPI can read one time which is transferred by
 621     * the response of 'Get Namespace Label Data' function.
 622     */
 623    max_get_size = dsm_memory_size - sizeof(NvdimmFuncGetLabelDataOut);
 624
 625    /*
 626     * the max data ACPI can write one time which is transferred by
 627     * 'Set Namespace Label Data' function.
 628     */
 629    max_set_size = dsm_memory_size - offsetof(NvdimmDsmIn, arg3) -
 630                   sizeof(NvdimmFuncSetLabelDataIn);
 631
 632    return MIN(max_get_size, max_set_size);
 633}
 634
 635/*
 636 * DSM Spec Rev1 4.4 Get Namespace Label Size (Function Index 4).
 637 *
 638 * It gets the size of Namespace Label data area and the max data size
 639 * that Get/Set Namespace Label Data functions can transfer.
 640 */
 641static void nvdimm_dsm_label_size(NVDIMMDevice *nvdimm, hwaddr dsm_mem_addr)
 642{
 643    NvdimmFuncGetLabelSizeOut label_size_out = {
 644        .len = cpu_to_le32(sizeof(label_size_out)),
 645    };
 646    uint32_t label_size, mxfer;
 647
 648    label_size = nvdimm->label_size;
 649    mxfer = nvdimm_get_max_xfer_label_size();
 650
 651    nvdimm_debug("label_size %#x, max_xfer %#x.\n", label_size, mxfer);
 652
 653    label_size_out.func_ret_status = cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS);
 654    label_size_out.label_size = cpu_to_le32(label_size);
 655    label_size_out.max_xfer = cpu_to_le32(mxfer);
 656
 657    cpu_physical_memory_write(dsm_mem_addr, &label_size_out,
 658                              sizeof(label_size_out));
 659}
 660
 661static uint32_t nvdimm_rw_label_data_check(NVDIMMDevice *nvdimm,
 662                                           uint32_t offset, uint32_t length)
 663{
 664    uint32_t ret = NVDIMM_DSM_RET_STATUS_INVALID;
 665
 666    if (offset + length < offset) {
 667        nvdimm_debug("offset %#x + length %#x is overflow.\n", offset,
 668                     length);
 669        return ret;
 670    }
 671
 672    if (nvdimm->label_size < offset + length) {
 673        nvdimm_debug("position %#x is beyond label data (len = %" PRIx64 ").\n",
 674                     offset + length, nvdimm->label_size);
 675        return ret;
 676    }
 677
 678    if (length > nvdimm_get_max_xfer_label_size()) {
 679        nvdimm_debug("length (%#x) is larger than max_xfer (%#x).\n",
 680                     length, nvdimm_get_max_xfer_label_size());
 681        return ret;
 682    }
 683
 684    return NVDIMM_DSM_RET_STATUS_SUCCESS;
 685}
 686
 687/*
 688 * DSM Spec Rev1 4.5 Get Namespace Label Data (Function Index 5).
 689 */
 690static void nvdimm_dsm_get_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
 691                                      hwaddr dsm_mem_addr)
 692{
 693    NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
 694    NvdimmFuncGetLabelDataIn *get_label_data;
 695    NvdimmFuncGetLabelDataOut *get_label_data_out;
 696    uint32_t status;
 697    int size;
 698
 699    get_label_data = (NvdimmFuncGetLabelDataIn *)in->arg3;
 700    le32_to_cpus(&get_label_data->offset);
 701    le32_to_cpus(&get_label_data->length);
 702
 703    nvdimm_debug("Read Label Data: offset %#x length %#x.\n",
 704                 get_label_data->offset, get_label_data->length);
 705
 706    status = nvdimm_rw_label_data_check(nvdimm, get_label_data->offset,
 707                                        get_label_data->length);
 708    if (status != NVDIMM_DSM_RET_STATUS_SUCCESS) {
 709        nvdimm_dsm_no_payload(status, dsm_mem_addr);
 710        return;
 711    }
 712
 713    size = sizeof(*get_label_data_out) + get_label_data->length;
 714    assert(size <= NVDIMM_DSM_MEMORY_SIZE);
 715    get_label_data_out = g_malloc(size);
 716
 717    get_label_data_out->len = cpu_to_le32(size);
 718    get_label_data_out->func_ret_status =
 719                            cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS);
 720    nvc->read_label_data(nvdimm, get_label_data_out->out_buf,
 721                         get_label_data->length, get_label_data->offset);
 722
 723    cpu_physical_memory_write(dsm_mem_addr, get_label_data_out, size);
 724    g_free(get_label_data_out);
 725}
 726
 727/*
 728 * DSM Spec Rev1 4.6 Set Namespace Label Data (Function Index 6).
 729 */
 730static void nvdimm_dsm_set_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in,
 731                                      hwaddr dsm_mem_addr)
 732{
 733    NVDIMMClass *nvc = NVDIMM_GET_CLASS(nvdimm);
 734    NvdimmFuncSetLabelDataIn *set_label_data;
 735    uint32_t status;
 736
 737    set_label_data = (NvdimmFuncSetLabelDataIn *)in->arg3;
 738
 739    le32_to_cpus(&set_label_data->offset);
 740    le32_to_cpus(&set_label_data->length);
 741
 742    nvdimm_debug("Write Label Data: offset %#x length %#x.\n",
 743                 set_label_data->offset, set_label_data->length);
 744
 745    status = nvdimm_rw_label_data_check(nvdimm, set_label_data->offset,
 746                                        set_label_data->length);
 747    if (status != NVDIMM_DSM_RET_STATUS_SUCCESS) {
 748        nvdimm_dsm_no_payload(status, dsm_mem_addr);
 749        return;
 750    }
 751
 752    assert(offsetof(NvdimmDsmIn, arg3) + sizeof(*set_label_data) +
 753                    set_label_data->length <= NVDIMM_DSM_MEMORY_SIZE);
 754
 755    nvc->write_label_data(nvdimm, set_label_data->in_buf,
 756                          set_label_data->length, set_label_data->offset);
 757    nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_SUCCESS, dsm_mem_addr);
 758}
 759
 760static void nvdimm_dsm_device(NvdimmDsmIn *in, hwaddr dsm_mem_addr)
 761{
 762    NVDIMMDevice *nvdimm = nvdimm_get_device_by_handle(in->handle);
 763
 764    /* See the comments in nvdimm_dsm_root(). */
 765    if (!in->function) {
 766        uint32_t supported_func = 0;
 767
 768        if (nvdimm && nvdimm->label_size) {
 769            supported_func |= 0x1 /* Bit 0 indicates whether there is
 770                                     support for any functions other
 771                                     than function 0. */ |
 772                              1 << 4 /* Get Namespace Label Size */ |
 773                              1 << 5 /* Get Namespace Label Data */ |
 774                              1 << 6 /* Set Namespace Label Data */;
 775        }
 776        nvdimm_dsm_function0(supported_func, dsm_mem_addr);
 777        return;
 778    }
 779
 780    if (!nvdimm) {
 781        nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_NOMEMDEV,
 782                              dsm_mem_addr);
 783        return;
 784    }
 785
 786    /* Encode DSM function according to DSM Spec Rev1. */
 787    switch (in->function) {
 788    case 4 /* Get Namespace Label Size */:
 789        if (nvdimm->label_size) {
 790            nvdimm_dsm_label_size(nvdimm, dsm_mem_addr);
 791            return;
 792        }
 793        break;
 794    case 5 /* Get Namespace Label Data */:
 795        if (nvdimm->label_size) {
 796            nvdimm_dsm_get_label_data(nvdimm, in, dsm_mem_addr);
 797            return;
 798        }
 799        break;
 800    case 0x6 /* Set Namespace Label Data */:
 801        if (nvdimm->label_size) {
 802            nvdimm_dsm_set_label_data(nvdimm, in, dsm_mem_addr);
 803            return;
 804        }
 805        break;
 806    }
 807
 808    nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
 809}
 810
 811static uint64_t
 812nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 813{
 814    nvdimm_debug("BUG: we never read _DSM IO Port.\n");
 815    return 0;
 816}
 817
 818static void
 819nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 820{
 821    AcpiNVDIMMState *state = opaque;
 822    NvdimmDsmIn *in;
 823    hwaddr dsm_mem_addr = val;
 824
 825    nvdimm_debug("dsm memory address %#" HWADDR_PRIx ".\n", dsm_mem_addr);
 826
 827    /*
 828     * The DSM memory is mapped to guest address space so an evil guest
 829     * can change its content while we are doing DSM emulation. Avoid
 830     * this by copying DSM memory to QEMU local memory.
 831     */
 832    in = g_new(NvdimmDsmIn, 1);
 833    cpu_physical_memory_read(dsm_mem_addr, in, sizeof(*in));
 834
 835    le32_to_cpus(&in->revision);
 836    le32_to_cpus(&in->function);
 837    le32_to_cpus(&in->handle);
 838
 839    nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
 840                 in->handle, in->function);
 841
 842    if (in->revision != 0x1 /* Currently we only support DSM Spec Rev1. */) {
 843        nvdimm_debug("Revision %#x is not supported, expect %#x.\n",
 844                     in->revision, 0x1);
 845        nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr);
 846        goto exit;
 847    }
 848
 849    if (in->handle == NVDIMM_QEMU_RSVD_HANDLE_ROOT) {
 850        nvdimm_dsm_handle_reserved_root_method(state, in, dsm_mem_addr);
 851        goto exit;
 852    }
 853
 854     /* Handle 0 is reserved for NVDIMM Root Device. */
 855    if (!in->handle) {
 856        nvdimm_dsm_root(in, dsm_mem_addr);
 857        goto exit;
 858    }
 859
 860    nvdimm_dsm_device(in, dsm_mem_addr);
 861
 862exit:
 863    g_free(in);
 864}
 865
 866static const MemoryRegionOps nvdimm_dsm_ops = {
 867    .read = nvdimm_dsm_read,
 868    .write = nvdimm_dsm_write,
 869    .endianness = DEVICE_LITTLE_ENDIAN,
 870    .valid = {
 871        .min_access_size = 4,
 872        .max_access_size = 4,
 873    },
 874};
 875
 876void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev)
 877{
 878    if (dev->hotplugged) {
 879        acpi_send_event(DEVICE(hotplug_dev), ACPI_NVDIMM_HOTPLUG_STATUS);
 880    }
 881}
 882
 883void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
 884                            FWCfgState *fw_cfg, Object *owner)
 885{
 886    memory_region_init_io(&state->io_mr, owner, &nvdimm_dsm_ops, state,
 887                          "nvdimm-acpi-io", NVDIMM_ACPI_IO_LEN);
 888    memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, &state->io_mr);
 889
 890    state->dsm_mem = g_array_new(false, true /* clear */, 1);
 891    acpi_data_push(state->dsm_mem, sizeof(NvdimmDsmIn));
 892    fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data,
 893                    state->dsm_mem->len);
 894
 895    nvdimm_init_fit_buffer(&state->fit_buf);
 896}
 897
 898#define NVDIMM_COMMON_DSM       "NCAL"
 899#define NVDIMM_ACPI_MEM_ADDR    "MEMA"
 900
 901#define NVDIMM_DSM_MEMORY       "NRAM"
 902#define NVDIMM_DSM_IOPORT       "NPIO"
 903
 904#define NVDIMM_DSM_NOTIFY       "NTFI"
 905#define NVDIMM_DSM_HANDLE       "HDLE"
 906#define NVDIMM_DSM_REVISION     "REVS"
 907#define NVDIMM_DSM_FUNCTION     "FUNC"
 908#define NVDIMM_DSM_ARG3         "FARG"
 909
 910#define NVDIMM_DSM_OUT_BUF_SIZE "RLEN"
 911#define NVDIMM_DSM_OUT_BUF      "ODAT"
 912
 913#define NVDIMM_DSM_RFIT_STATUS  "RSTA"
 914
 915#define NVDIMM_QEMU_RSVD_UUID   "648B9CF2-CDA1-4312-8AD9-49C4AF32BD62"
 916
 917static void nvdimm_build_common_dsm(Aml *dev)
 918{
 919    Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *elsectx2;
 920    Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid;
 921    Aml *pckg, *pckg_index, *pckg_buf, *field, *dsm_out_buf, *dsm_out_buf_size;
 922    uint8_t byte_list[1];
 923
 924    method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED);
 925    uuid = aml_arg(0);
 926    function = aml_arg(2);
 927    handle = aml_arg(4);
 928    dsm_mem = aml_local(6);
 929    dsm_out_buf = aml_local(7);
 930
 931    aml_append(method, aml_store(aml_name(NVDIMM_ACPI_MEM_ADDR), dsm_mem));
 932
 933    /* map DSM memory and IO into ACPI namespace. */
 934    aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, AML_SYSTEM_IO,
 935               aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN));
 936    aml_append(method, aml_operation_region(NVDIMM_DSM_MEMORY,
 937               AML_SYSTEM_MEMORY, dsm_mem, sizeof(NvdimmDsmIn)));
 938
 939    /*
 940     * DSM notifier:
 941     * NVDIMM_DSM_NOTIFY: write the address of DSM memory and notify QEMU to
 942     *                    emulate the access.
 943     *
 944     * It is the IO port so that accessing them will cause VM-exit, the
 945     * control will be transferred to QEMU.
 946     */
 947    field = aml_field(NVDIMM_DSM_IOPORT, AML_DWORD_ACC, AML_NOLOCK,
 948                      AML_PRESERVE);
 949    aml_append(field, aml_named_field(NVDIMM_DSM_NOTIFY,
 950               sizeof(uint32_t) * BITS_PER_BYTE));
 951    aml_append(method, field);
 952
 953    /*
 954     * DSM input:
 955     * NVDIMM_DSM_HANDLE: store device's handle, it's zero if the _DSM call
 956     *                    happens on NVDIMM Root Device.
 957     * NVDIMM_DSM_REVISION: store the Arg1 of _DSM call.
 958     * NVDIMM_DSM_FUNCTION: store the Arg2 of _DSM call.
 959     * NVDIMM_DSM_ARG3: store the Arg3 of _DSM call which is a Package
 960     *                  containing function-specific arguments.
 961     *
 962     * They are RAM mapping on host so that these accesses never cause
 963     * VM-EXIT.
 964     */
 965    field = aml_field(NVDIMM_DSM_MEMORY, AML_DWORD_ACC, AML_NOLOCK,
 966                      AML_PRESERVE);
 967    aml_append(field, aml_named_field(NVDIMM_DSM_HANDLE,
 968               sizeof(typeof_field(NvdimmDsmIn, handle)) * BITS_PER_BYTE));
 969    aml_append(field, aml_named_field(NVDIMM_DSM_REVISION,
 970               sizeof(typeof_field(NvdimmDsmIn, revision)) * BITS_PER_BYTE));
 971    aml_append(field, aml_named_field(NVDIMM_DSM_FUNCTION,
 972               sizeof(typeof_field(NvdimmDsmIn, function)) * BITS_PER_BYTE));
 973    aml_append(field, aml_named_field(NVDIMM_DSM_ARG3,
 974         (sizeof(NvdimmDsmIn) - offsetof(NvdimmDsmIn, arg3)) * BITS_PER_BYTE));
 975    aml_append(method, field);
 976
 977    /*
 978     * DSM output:
 979     * NVDIMM_DSM_OUT_BUF_SIZE: the size of the buffer filled by QEMU.
 980     * NVDIMM_DSM_OUT_BUF: the buffer QEMU uses to store the result.
 981     *
 982     * Since the page is reused by both input and out, the input data
 983     * will be lost after storing new result into ODAT so we should fetch
 984     * all the input data before writing the result.
 985     */
 986    field = aml_field(NVDIMM_DSM_MEMORY, AML_DWORD_ACC, AML_NOLOCK,
 987                      AML_PRESERVE);
 988    aml_append(field, aml_named_field(NVDIMM_DSM_OUT_BUF_SIZE,
 989               sizeof(typeof_field(NvdimmDsmOut, len)) * BITS_PER_BYTE));
 990    aml_append(field, aml_named_field(NVDIMM_DSM_OUT_BUF,
 991       (sizeof(NvdimmDsmOut) - offsetof(NvdimmDsmOut, data)) * BITS_PER_BYTE));
 992    aml_append(method, field);
 993
 994    /*
 995     * do not support any method if DSM memory address has not been
 996     * patched.
 997     */
 998    unpatched = aml_equal(dsm_mem, aml_int(0x0));
 999
1000    expected_uuid = aml_local(0);
1001
1002    ifctx = aml_if(aml_equal(handle, aml_int(0x0)));
1003    aml_append(ifctx, aml_store(
1004               aml_touuid("2F10E7A4-9E91-11E4-89D3-123B93F75CBA")
1005               /* UUID for NVDIMM Root Device */, expected_uuid));
1006    aml_append(method, ifctx);
1007    elsectx = aml_else();
1008    ifctx = aml_if(aml_equal(handle, aml_int(NVDIMM_QEMU_RSVD_HANDLE_ROOT)));
1009    aml_append(ifctx, aml_store(aml_touuid(NVDIMM_QEMU_RSVD_UUID
1010               /* UUID for QEMU internal use */), expected_uuid));
1011    aml_append(elsectx, ifctx);
1012    elsectx2 = aml_else();
1013    aml_append(elsectx2, aml_store(
1014               aml_touuid("4309AC30-0D11-11E4-9191-0800200C9A66")
1015               /* UUID for NVDIMM Devices */, expected_uuid));
1016    aml_append(elsectx, elsectx2);
1017    aml_append(method, elsectx);
1018
1019    uuid_invalid = aml_lnot(aml_equal(uuid, expected_uuid));
1020
1021    unsupport = aml_if(aml_or(unpatched, uuid_invalid, NULL));
1022
1023    /*
1024     * function 0 is called to inquire what functions are supported by
1025     * OSPM
1026     */
1027    ifctx = aml_if(aml_equal(function, aml_int(0)));
1028    byte_list[0] = 0 /* No function Supported */;
1029    aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
1030    aml_append(unsupport, ifctx);
1031
1032    /* No function is supported yet. */
1033    byte_list[0] = NVDIMM_DSM_RET_STATUS_UNSUPPORT;
1034    aml_append(unsupport, aml_return(aml_buffer(1, byte_list)));
1035    aml_append(method, unsupport);
1036
1037    /*
1038     * The HDLE indicates the DSM function is issued from which device,
1039     * it reserves 0 for root device and is the handle for NVDIMM devices.
1040     * See the comments in nvdimm_slot_to_handle().
1041     */
1042    aml_append(method, aml_store(handle, aml_name(NVDIMM_DSM_HANDLE)));
1043    aml_append(method, aml_store(aml_arg(1), aml_name(NVDIMM_DSM_REVISION)));
1044    aml_append(method, aml_store(aml_arg(2), aml_name(NVDIMM_DSM_FUNCTION)));
1045
1046    /*
1047     * The fourth parameter (Arg3) of _DSM is a package which contains
1048     * a buffer, the layout of the buffer is specified by UUID (Arg0),
1049     * Revision ID (Arg1) and Function Index (Arg2) which are documented
1050     * in the DSM Spec.
1051     */
1052    pckg = aml_arg(3);
1053    ifctx = aml_if(aml_and(aml_equal(aml_object_type(pckg),
1054                   aml_int(4 /* Package */)) /* It is a Package? */,
1055                   aml_equal(aml_sizeof(pckg), aml_int(1)) /* 1 element? */,
1056                   NULL));
1057
1058    pckg_index = aml_local(2);
1059    pckg_buf = aml_local(3);
1060    aml_append(ifctx, aml_store(aml_index(pckg, aml_int(0)), pckg_index));
1061    aml_append(ifctx, aml_store(aml_derefof(pckg_index), pckg_buf));
1062    aml_append(ifctx, aml_store(pckg_buf, aml_name(NVDIMM_DSM_ARG3)));
1063    aml_append(method, ifctx);
1064
1065    /*
1066     * tell QEMU about the real address of DSM memory, then QEMU
1067     * gets the control and fills the result in DSM memory.
1068     */
1069    aml_append(method, aml_store(dsm_mem, aml_name(NVDIMM_DSM_NOTIFY)));
1070
1071    dsm_out_buf_size = aml_local(1);
1072    /* RLEN is not included in the payload returned to guest. */
1073    aml_append(method, aml_subtract(aml_name(NVDIMM_DSM_OUT_BUF_SIZE),
1074               aml_int(4), dsm_out_buf_size));
1075    aml_append(method, aml_store(aml_shiftleft(dsm_out_buf_size, aml_int(3)),
1076                                 dsm_out_buf_size));
1077    aml_append(method, aml_create_field(aml_name(NVDIMM_DSM_OUT_BUF),
1078               aml_int(0), dsm_out_buf_size, "OBUF"));
1079    aml_append(method, aml_concatenate(aml_buffer(0, NULL), aml_name("OBUF"),
1080                                       dsm_out_buf));
1081    aml_append(method, aml_return(dsm_out_buf));
1082    aml_append(dev, method);
1083}
1084
1085static void nvdimm_build_device_dsm(Aml *dev, uint32_t handle)
1086{
1087    Aml *method;
1088
1089    method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
1090    aml_append(method, aml_return(aml_call5(NVDIMM_COMMON_DSM, aml_arg(0),
1091                                  aml_arg(1), aml_arg(2), aml_arg(3),
1092                                  aml_int(handle))));
1093    aml_append(dev, method);
1094}
1095
1096static void nvdimm_build_fit(Aml *dev)
1097{
1098    Aml *method, *pkg, *buf, *buf_size, *offset, *call_result;
1099    Aml *whilectx, *ifcond, *ifctx, *elsectx, *fit;
1100
1101    buf = aml_local(0);
1102    buf_size = aml_local(1);
1103    fit = aml_local(2);
1104
1105    aml_append(dev, aml_name_decl(NVDIMM_DSM_RFIT_STATUS, aml_int(0)));
1106
1107    /* build helper function, RFIT. */
1108    method = aml_method("RFIT", 1, AML_SERIALIZED);
1109    aml_append(method, aml_name_decl("OFST", aml_int(0)));
1110
1111    /* prepare input package. */
1112    pkg = aml_package(1);
1113    aml_append(method, aml_store(aml_arg(0), aml_name("OFST")));
1114    aml_append(pkg, aml_name("OFST"));
1115
1116    /* call Read_FIT function. */
1117    call_result = aml_call5(NVDIMM_COMMON_DSM,
1118                            aml_touuid(NVDIMM_QEMU_RSVD_UUID),
1119                            aml_int(1) /* Revision 1 */,
1120                            aml_int(0x1) /* Read FIT */,
1121                            pkg, aml_int(NVDIMM_QEMU_RSVD_HANDLE_ROOT));
1122    aml_append(method, aml_store(call_result, buf));
1123
1124    /* handle _DSM result. */
1125    aml_append(method, aml_create_dword_field(buf,
1126               aml_int(0) /* offset at byte 0 */, "STAU"));
1127
1128    aml_append(method, aml_store(aml_name("STAU"),
1129                                 aml_name(NVDIMM_DSM_RFIT_STATUS)));
1130
1131     /* if something is wrong during _DSM. */
1132    ifcond = aml_equal(aml_int(NVDIMM_DSM_RET_STATUS_SUCCESS),
1133                       aml_name("STAU"));
1134    ifctx = aml_if(aml_lnot(ifcond));
1135    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
1136    aml_append(method, ifctx);
1137
1138    aml_append(method, aml_store(aml_sizeof(buf), buf_size));
1139    aml_append(method, aml_subtract(buf_size,
1140                                    aml_int(4) /* the size of "STAU" */,
1141                                    buf_size));
1142
1143    /* if we read the end of fit. */
1144    ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
1145    aml_append(ifctx, aml_return(aml_buffer(0, NULL)));
1146    aml_append(method, ifctx);
1147
1148    aml_append(method, aml_create_field(buf,
1149                            aml_int(4 * BITS_PER_BYTE), /* offset at byte 4.*/
1150                            aml_shiftleft(buf_size, aml_int(3)), "BUFF"));
1151    aml_append(method, aml_return(aml_name("BUFF")));
1152    aml_append(dev, method);
1153
1154    /* build _FIT. */
1155    method = aml_method("_FIT", 0, AML_SERIALIZED);
1156    offset = aml_local(3);
1157
1158    aml_append(method, aml_store(aml_buffer(0, NULL), fit));
1159    aml_append(method, aml_store(aml_int(0), offset));
1160
1161    whilectx = aml_while(aml_int(1));
1162    aml_append(whilectx, aml_store(aml_call1("RFIT", offset), buf));
1163    aml_append(whilectx, aml_store(aml_sizeof(buf), buf_size));
1164
1165    /*
1166     * if fit buffer was changed during RFIT, read from the beginning
1167     * again.
1168     */
1169    ifctx = aml_if(aml_equal(aml_name(NVDIMM_DSM_RFIT_STATUS),
1170                             aml_int(NVDIMM_DSM_RET_STATUS_FIT_CHANGED)));
1171    aml_append(ifctx, aml_store(aml_buffer(0, NULL), fit));
1172    aml_append(ifctx, aml_store(aml_int(0), offset));
1173    aml_append(whilectx, ifctx);
1174
1175    elsectx = aml_else();
1176
1177    /* finish fit read if no data is read out. */
1178    ifctx = aml_if(aml_equal(buf_size, aml_int(0)));
1179    aml_append(ifctx, aml_return(fit));
1180    aml_append(elsectx, ifctx);
1181
1182    /* update the offset. */
1183    aml_append(elsectx, aml_add(offset, buf_size, offset));
1184    /* append the data we read out to the fit buffer. */
1185    aml_append(elsectx, aml_concatenate(fit, buf, fit));
1186    aml_append(whilectx, elsectx);
1187    aml_append(method, whilectx);
1188
1189    aml_append(dev, method);
1190}
1191
1192static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots)
1193{
1194    uint32_t slot;
1195
1196    for (slot = 0; slot < ram_slots; slot++) {
1197        uint32_t handle = nvdimm_slot_to_handle(slot);
1198        Aml *nvdimm_dev;
1199
1200        nvdimm_dev = aml_device("NV%02X", slot);
1201
1202        /*
1203         * ACPI 6.0: 9.20 NVDIMM Devices:
1204         *
1205         * _ADR object that is used to supply OSPM with unique address
1206         * of the NVDIMM device. This is done by returning the NFIT Device
1207         * handle that is used to identify the associated entries in ACPI
1208         * table NFIT or _FIT.
1209         */
1210        aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle)));
1211
1212        nvdimm_build_device_dsm(nvdimm_dev, handle);
1213        aml_append(root_dev, nvdimm_dev);
1214    }
1215}
1216
1217static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
1218                              BIOSLinker *linker, GArray *dsm_dma_arrea,
1219                              uint32_t ram_slots)
1220{
1221    Aml *ssdt, *sb_scope, *dev;
1222    int mem_addr_offset, nvdimm_ssdt;
1223
1224    acpi_add_table(table_offsets, table_data);
1225
1226    ssdt = init_aml_allocator();
1227    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
1228
1229    sb_scope = aml_scope("\\_SB");
1230
1231    dev = aml_device("NVDR");
1232
1233    /*
1234     * ACPI 6.0: 9.20 NVDIMM Devices:
1235     *
1236     * The ACPI Name Space device uses _HID of ACPI0012 to identify the root
1237     * NVDIMM interface device. Platform firmware is required to contain one
1238     * such device in _SB scope if NVDIMMs support is exposed by platform to
1239     * OSPM.
1240     * For each NVDIMM present or intended to be supported by platform,
1241     * platform firmware also exposes an ACPI Namespace Device under the
1242     * root device.
1243     */
1244    aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
1245
1246    nvdimm_build_common_dsm(dev);
1247
1248    /* 0 is reserved for root device. */
1249    nvdimm_build_device_dsm(dev, 0);
1250    nvdimm_build_fit(dev);
1251
1252    nvdimm_build_nvdimm_devices(dev, ram_slots);
1253
1254    aml_append(sb_scope, dev);
1255    aml_append(ssdt, sb_scope);
1256
1257    nvdimm_ssdt = table_data->len;
1258
1259    /* copy AML table into ACPI tables blob and patch header there */
1260    g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
1261    mem_addr_offset = build_append_named_dword(table_data,
1262                                               NVDIMM_ACPI_MEM_ADDR);
1263
1264    bios_linker_loader_alloc(linker,
1265                             NVDIMM_DSM_MEM_FILE, dsm_dma_arrea,
1266                             sizeof(NvdimmDsmIn), false /* high memory */);
1267    bios_linker_loader_add_pointer(linker,
1268        ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
1269        NVDIMM_DSM_MEM_FILE, 0);
1270    build_header(linker, table_data,
1271        (void *)(table_data->data + nvdimm_ssdt),
1272        "SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
1273    free_aml_allocator();
1274}
1275
1276void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
1277                       BIOSLinker *linker, AcpiNVDIMMState *state,
1278                       uint32_t ram_slots)
1279{
1280    GSList *device_list;
1281
1282    /* no nvdimm device can be plugged. */
1283    if (!ram_slots) {
1284        return;
1285    }
1286
1287    nvdimm_build_ssdt(table_offsets, table_data, linker, state->dsm_mem,
1288                      ram_slots);
1289
1290    device_list = nvdimm_get_device_list();
1291    /* no NVDIMM device is plugged. */
1292    if (!device_list) {
1293        return;
1294    }
1295
1296    nvdimm_build_nfit(state, table_offsets, table_data, linker);
1297    g_slist_free(device_list);
1298}
1299