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