qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

erst.c (35129B)


      1 /*
      2  * ACPI Error Record Serialization Table, ERST, Implementation
      3  *
      4  * ACPI ERST introduced in ACPI 4.0, June 16, 2009.
      5  * ACPI Platform Error Interfaces : Error Serialization
      6  *
      7  * Copyright (c) 2021 Oracle and/or its affiliates.
      8  *
      9  * SPDX-License-Identifier: GPL-2.0-or-later
     10  */
     11 
     12 #include "qemu/osdep.h"
     13 #include "qapi/error.h"
     14 #include "hw/qdev-core.h"
     15 #include "exec/memory.h"
     16 #include "qom/object.h"
     17 #include "hw/pci/pci.h"
     18 #include "qom/object_interfaces.h"
     19 #include "qemu/error-report.h"
     20 #include "migration/vmstate.h"
     21 #include "hw/qdev-properties.h"
     22 #include "hw/acpi/acpi.h"
     23 #include "hw/acpi/acpi-defs.h"
     24 #include "hw/acpi/aml-build.h"
     25 #include "hw/acpi/bios-linker-loader.h"
     26 #include "exec/address-spaces.h"
     27 #include "sysemu/hostmem.h"
     28 #include "hw/acpi/erst.h"
     29 #include "trace.h"
     30 
     31 /* ACPI 4.0: Table 17-16 Serialization Actions */
     32 #define ACTION_BEGIN_WRITE_OPERATION         0x0
     33 #define ACTION_BEGIN_READ_OPERATION          0x1
     34 #define ACTION_BEGIN_CLEAR_OPERATION         0x2
     35 #define ACTION_END_OPERATION                 0x3
     36 #define ACTION_SET_RECORD_OFFSET             0x4
     37 #define ACTION_EXECUTE_OPERATION             0x5
     38 #define ACTION_CHECK_BUSY_STATUS             0x6
     39 #define ACTION_GET_COMMAND_STATUS            0x7
     40 #define ACTION_GET_RECORD_IDENTIFIER         0x8
     41 #define ACTION_SET_RECORD_IDENTIFIER         0x9
     42 #define ACTION_GET_RECORD_COUNT              0xA
     43 #define ACTION_BEGIN_DUMMY_WRITE_OPERATION   0xB
     44 #define ACTION_RESERVED                      0xC
     45 #define ACTION_GET_ERROR_LOG_ADDRESS_RANGE   0xD
     46 #define ACTION_GET_ERROR_LOG_ADDRESS_LENGTH  0xE
     47 #define ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0xF
     48 #define ACTION_GET_EXECUTE_OPERATION_TIMINGS 0x10 /* ACPI 6.3 */
     49 
     50 /* ACPI 4.0: Table 17-17 Command Status Definitions */
     51 #define STATUS_SUCCESS                0x00
     52 #define STATUS_NOT_ENOUGH_SPACE       0x01
     53 #define STATUS_HARDWARE_NOT_AVAILABLE 0x02
     54 #define STATUS_FAILED                 0x03
     55 #define STATUS_RECORD_STORE_EMPTY     0x04
     56 #define STATUS_RECORD_NOT_FOUND       0x05
     57 
     58 /* ACPI 4.0: Table 17-19 Serialization Instructions */
     59 #define INST_READ_REGISTER                 0x00
     60 #define INST_READ_REGISTER_VALUE           0x01
     61 #define INST_WRITE_REGISTER                0x02
     62 #define INST_WRITE_REGISTER_VALUE          0x03
     63 #define INST_NOOP                          0x04
     64 #define INST_LOAD_VAR1                     0x05
     65 #define INST_LOAD_VAR2                     0x06
     66 #define INST_STORE_VAR1                    0x07
     67 #define INST_ADD                           0x08
     68 #define INST_SUBTRACT                      0x09
     69 #define INST_ADD_VALUE                     0x0A
     70 #define INST_SUBTRACT_VALUE                0x0B
     71 #define INST_STALL                         0x0C
     72 #define INST_STALL_WHILE_TRUE              0x0D
     73 #define INST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E
     74 #define INST_GOTO                          0x0F
     75 #define INST_SET_SRC_ADDRESS_BASE          0x10
     76 #define INST_SET_DST_ADDRESS_BASE          0x11
     77 #define INST_MOVE_DATA                     0x12
     78 
     79 /* UEFI 2.1: Appendix N Common Platform Error Record */
     80 #define UEFI_CPER_RECORD_MIN_SIZE 128U
     81 #define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
     82 #define UEFI_CPER_RECORD_ID_OFFSET 96U
     83 
     84 /*
     85  * NOTE that when accessing CPER fields within a record, memcpy()
     86  * is utilized to avoid a possible misaligned access on the host.
     87  */
     88 
     89 /*
     90  * This implementation is an ACTION (cmd) and VALUE (data)
     91  * interface consisting of just two 64-bit registers.
     92  */
     93 #define ERST_REG_SIZE (16UL)
     94 #define ERST_ACTION_OFFSET (0UL) /* action (cmd) */
     95 #define ERST_VALUE_OFFSET  (8UL) /* argument/value (data) */
     96 
     97 /*
     98  * ERST_RECORD_SIZE is the buffer size for exchanging ERST
     99  * record contents. Thus, it defines the maximum record size.
    100  * As this is mapped through a PCI BAR, it must be a power of
    101  * two and larger than UEFI_CPER_RECORD_MIN_SIZE.
    102  * The backing storage is divided into fixed size "slots",
    103  * each ERST_RECORD_SIZE in length, and each "slot"
    104  * storing a single record. No attempt at optimizing storage
    105  * through compression, compaction, etc is attempted.
    106  * NOTE that slot 0 is reserved for the backing storage header.
    107  * Depending upon the size of the backing storage, additional
    108  * slots will be part of the slot 0 header in order to account
    109  * for a record_id for each available remaining slot.
    110  */
    111 /* 8KiB records, not too small, not too big */
    112 #define ERST_RECORD_SIZE (8192UL)
    113 
    114 #define ACPI_ERST_MEMDEV_PROP "memdev"
    115 #define ACPI_ERST_RECORD_SIZE_PROP "record_size"
    116 
    117 /*
    118  * From the ACPI ERST spec sections:
    119  * A record id of all 0s is used to indicate 'unspecified' record id.
    120  * A record id of all 1s is used to indicate empty or end.
    121  */
    122 #define ERST_UNSPECIFIED_RECORD_ID (0UL)
    123 #define ERST_EMPTY_END_RECORD_ID (~0UL)
    124 
    125 #define ERST_IS_VALID_RECORD_ID(rid) \
    126     ((rid != ERST_UNSPECIFIED_RECORD_ID) && \
    127      (rid != ERST_EMPTY_END_RECORD_ID))
    128 
    129 /*
    130  * Implementation-specific definitions and types.
    131  * Values are arbitrary and chosen for this implementation.
    132  * See erst.rst documentation for details.
    133  */
    134 #define ERST_EXECUTE_OPERATION_MAGIC 0x9CUL
    135 #define ERST_STORE_MAGIC 0x524F545354535245UL /* ERSTSTOR */
    136 typedef struct {
    137     uint64_t magic;
    138     uint32_t record_size;
    139     uint32_t storage_offset; /* offset to record storage beyond header */
    140     uint16_t version;
    141     uint16_t reserved;
    142     uint32_t record_count;
    143     uint64_t map[]; /* contains record_ids, and position indicates index */
    144 } __attribute__((packed)) ERSTStorageHeader;
    145 
    146 /*
    147  * Object cast macro
    148  */
    149 #define ACPIERST(obj) \
    150     OBJECT_CHECK(ERSTDeviceState, (obj), TYPE_ACPI_ERST)
    151 
    152 /*
    153  * Main ERST device state structure
    154  */
    155 typedef struct {
    156     PCIDevice parent_obj;
    157 
    158     /* Backend storage */
    159     HostMemoryBackend *hostmem;
    160     MemoryRegion *hostmem_mr;
    161     uint32_t storage_size;
    162     uint32_t default_record_size;
    163 
    164     /* Programming registers */
    165     MemoryRegion iomem_mr;
    166 
    167     /* Exchange buffer */
    168     MemoryRegion exchange_mr;
    169 
    170     /* Interface state */
    171     uint8_t operation;
    172     uint8_t busy_status;
    173     uint8_t command_status;
    174     uint32_t record_offset;
    175     uint64_t reg_action;
    176     uint64_t reg_value;
    177     uint64_t record_identifier;
    178     ERSTStorageHeader *header;
    179     unsigned first_record_index;
    180     unsigned last_record_index;
    181     unsigned next_record_index;
    182 
    183 } ERSTDeviceState;
    184 
    185 /*******************************************************************/
    186 /*******************************************************************/
    187 typedef struct {
    188     GArray *table_data;
    189     pcibus_t bar;
    190     uint8_t instruction;
    191     uint8_t flags;
    192     uint8_t register_bit_width;
    193     pcibus_t register_offset;
    194 } BuildSerializationInstructionEntry;
    195 
    196 /* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
    197 static void build_serialization_instruction(
    198     BuildSerializationInstructionEntry *e,
    199     uint8_t serialization_action,
    200     uint64_t value)
    201 {
    202     /* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
    203     struct AcpiGenericAddress gas;
    204     uint64_t mask;
    205 
    206     /* Serialization Action */
    207     build_append_int_noprefix(e->table_data, serialization_action, 1);
    208     /* Instruction */
    209     build_append_int_noprefix(e->table_data, e->instruction, 1);
    210     /* Flags */
    211     build_append_int_noprefix(e->table_data, e->flags, 1);
    212     /* Reserved */
    213     build_append_int_noprefix(e->table_data, 0, 1);
    214     /* Register Region */
    215     gas.space_id = AML_SYSTEM_MEMORY;
    216     gas.bit_width = e->register_bit_width;
    217     gas.bit_offset = 0;
    218     gas.access_width = (uint8_t)ctz32(e->register_bit_width) - 2;
    219     gas.address = (uint64_t)(e->bar + e->register_offset);
    220     build_append_gas_from_struct(e->table_data, &gas);
    221     /* Value */
    222     build_append_int_noprefix(e->table_data, value, 8);
    223     /* Mask */
    224     mask = (1ULL << (e->register_bit_width - 1) << 1) - 1;
    225     build_append_int_noprefix(e->table_data, mask, 8);
    226 }
    227 
    228 /* ACPI 4.0: 17.4.1 Serialization Action Table */
    229 void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
    230     const char *oem_id, const char *oem_table_id)
    231 {
    232     /*
    233      * Serialization Action Table
    234      * The serialization action table must be generated first
    235      * so that its size can be known in order to populate the
    236      * Instruction Entry Count field.
    237      */
    238     unsigned action;
    239     GArray *table_instruction_data = g_array_new(FALSE, FALSE, sizeof(char));
    240     pcibus_t bar0 = pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
    241     AcpiTable table = { .sig = "ERST", .rev = 1, .oem_id = oem_id,
    242                         .oem_table_id = oem_table_id };
    243     /* Contexts for the different ways ACTION and VALUE are accessed */
    244     BuildSerializationInstructionEntry rd_value_32_val = {
    245         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    246         .instruction = INST_READ_REGISTER_VALUE,
    247         .register_bit_width = 32,
    248         .register_offset = ERST_VALUE_OFFSET,
    249     };
    250     BuildSerializationInstructionEntry rd_value_32 = {
    251         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    252         .instruction = INST_READ_REGISTER,
    253         .register_bit_width = 32,
    254         .register_offset = ERST_VALUE_OFFSET,
    255     };
    256     BuildSerializationInstructionEntry rd_value_64 = {
    257         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    258         .instruction = INST_READ_REGISTER,
    259         .register_bit_width = 64,
    260         .register_offset = ERST_VALUE_OFFSET,
    261     };
    262     BuildSerializationInstructionEntry wr_value_32_val = {
    263         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    264         .instruction = INST_WRITE_REGISTER_VALUE,
    265         .register_bit_width = 32,
    266         .register_offset = ERST_VALUE_OFFSET,
    267     };
    268     BuildSerializationInstructionEntry wr_value_32 = {
    269         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    270         .instruction = INST_WRITE_REGISTER,
    271         .register_bit_width = 32,
    272         .register_offset = ERST_VALUE_OFFSET,
    273     };
    274     BuildSerializationInstructionEntry wr_value_64 = {
    275         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    276         .instruction = INST_WRITE_REGISTER,
    277         .register_bit_width = 64,
    278         .register_offset = ERST_VALUE_OFFSET,
    279     };
    280     BuildSerializationInstructionEntry wr_action = {
    281         .table_data = table_instruction_data, .bar = bar0, .flags = 0,
    282         .instruction = INST_WRITE_REGISTER_VALUE,
    283         .register_bit_width = 32,
    284         .register_offset = ERST_ACTION_OFFSET,
    285     };
    286 
    287     trace_acpi_erst_pci_bar_0(bar0);
    288 
    289     /* Serialization Instruction Entries */
    290     action = ACTION_BEGIN_WRITE_OPERATION;
    291     build_serialization_instruction(&wr_action, action, action);
    292 
    293     action = ACTION_BEGIN_READ_OPERATION;
    294     build_serialization_instruction(&wr_action, action, action);
    295 
    296     action = ACTION_BEGIN_CLEAR_OPERATION;
    297     build_serialization_instruction(&wr_action, action, action);
    298 
    299     action = ACTION_END_OPERATION;
    300     build_serialization_instruction(&wr_action, action, action);
    301 
    302     action = ACTION_SET_RECORD_OFFSET;
    303     build_serialization_instruction(&wr_value_32, action, 0);
    304     build_serialization_instruction(&wr_action, action, action);
    305 
    306     action = ACTION_EXECUTE_OPERATION;
    307     build_serialization_instruction(&wr_value_32_val, action,
    308         ERST_EXECUTE_OPERATION_MAGIC);
    309     build_serialization_instruction(&wr_action, action, action);
    310 
    311     action = ACTION_CHECK_BUSY_STATUS;
    312     build_serialization_instruction(&wr_action, action, action);
    313     build_serialization_instruction(&rd_value_32_val, action, 0x01);
    314 
    315     action = ACTION_GET_COMMAND_STATUS;
    316     build_serialization_instruction(&wr_action, action, action);
    317     build_serialization_instruction(&rd_value_32, action, 0);
    318 
    319     action = ACTION_GET_RECORD_IDENTIFIER;
    320     build_serialization_instruction(&wr_action, action, action);
    321     build_serialization_instruction(&rd_value_64, action, 0);
    322 
    323     action = ACTION_SET_RECORD_IDENTIFIER;
    324     build_serialization_instruction(&wr_value_64, action, 0);
    325     build_serialization_instruction(&wr_action, action, action);
    326 
    327     action = ACTION_GET_RECORD_COUNT;
    328     build_serialization_instruction(&wr_action, action, action);
    329     build_serialization_instruction(&rd_value_32, action, 0);
    330 
    331     action = ACTION_BEGIN_DUMMY_WRITE_OPERATION;
    332     build_serialization_instruction(&wr_action, action, action);
    333 
    334     action = ACTION_GET_ERROR_LOG_ADDRESS_RANGE;
    335     build_serialization_instruction(&wr_action, action, action);
    336     build_serialization_instruction(&rd_value_64, action, 0);
    337 
    338     action = ACTION_GET_ERROR_LOG_ADDRESS_LENGTH;
    339     build_serialization_instruction(&wr_action, action, action);
    340     build_serialization_instruction(&rd_value_64, action, 0);
    341 
    342     action = ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES;
    343     build_serialization_instruction(&wr_action, action, action);
    344     build_serialization_instruction(&rd_value_32, action, 0);
    345 
    346     action = ACTION_GET_EXECUTE_OPERATION_TIMINGS;
    347     build_serialization_instruction(&wr_action, action, action);
    348     build_serialization_instruction(&rd_value_64, action, 0);
    349 
    350     /* Serialization Header */
    351     acpi_table_begin(&table, table_data);
    352 
    353     /* Serialization Header Size */
    354     build_append_int_noprefix(table_data, 48, 4);
    355 
    356     /* Reserved */
    357     build_append_int_noprefix(table_data,  0, 4);
    358 
    359     /*
    360      * Instruction Entry Count
    361      * Each instruction entry is 32 bytes
    362      */
    363     g_assert((table_instruction_data->len) % 32 == 0);
    364     build_append_int_noprefix(table_data,
    365         (table_instruction_data->len / 32), 4);
    366 
    367     /* Serialization Instruction Entries */
    368     g_array_append_vals(table_data, table_instruction_data->data,
    369         table_instruction_data->len);
    370     g_array_free(table_instruction_data, TRUE);
    371 
    372     acpi_table_end(linker, &table);
    373 }
    374 
    375 /*******************************************************************/
    376 /*******************************************************************/
    377 static uint8_t *get_nvram_ptr_by_index(ERSTDeviceState *s, unsigned index)
    378 {
    379     uint8_t *rc = NULL;
    380     off_t offset = (index * le32_to_cpu(s->header->record_size));
    381 
    382     g_assert(offset < s->storage_size);
    383 
    384     rc = memory_region_get_ram_ptr(s->hostmem_mr);
    385     rc += offset;
    386 
    387     return rc;
    388 }
    389 
    390 static void make_erst_storage_header(ERSTDeviceState *s)
    391 {
    392     ERSTStorageHeader *header = s->header;
    393     unsigned mapsz, headersz;
    394 
    395     header->magic = cpu_to_le64(ERST_STORE_MAGIC);
    396     header->record_size = cpu_to_le32(s->default_record_size);
    397     header->version = cpu_to_le16(0x0100);
    398     header->reserved = cpu_to_le16(0x0000);
    399 
    400     /* Compute mapsize */
    401     mapsz = s->storage_size / s->default_record_size;
    402     mapsz *= sizeof(uint64_t);
    403     /* Compute header+map size */
    404     headersz = sizeof(ERSTStorageHeader) + mapsz;
    405     /* Round up to nearest integer multiple of ERST_RECORD_SIZE */
    406     headersz = QEMU_ALIGN_UP(headersz, s->default_record_size);
    407     header->storage_offset = cpu_to_le32(headersz);
    408 
    409     /*
    410      * The HostMemoryBackend initializes contents to zero,
    411      * so all record_ids stashed in the map are zero'd.
    412      * As well the record_count is zero. Properly initialized.
    413      */
    414 }
    415 
    416 static void check_erst_backend_storage(ERSTDeviceState *s, Error **errp)
    417 {
    418     ERSTStorageHeader *header;
    419     uint32_t record_size;
    420 
    421     header = memory_region_get_ram_ptr(s->hostmem_mr);
    422     s->header = header;
    423 
    424     /* Ensure pointer to header is 64-bit aligned */
    425     g_assert(QEMU_PTR_IS_ALIGNED(header, sizeof(uint64_t)));
    426 
    427     /*
    428      * Check if header is uninitialized; HostMemoryBackend inits to 0
    429      */
    430     if (le64_to_cpu(header->magic) == 0UL) {
    431         make_erst_storage_header(s);
    432     }
    433 
    434     /* Validity check record_size */
    435     record_size = le32_to_cpu(header->record_size);
    436     if (!(
    437         (record_size) && /* non zero */
    438         (record_size >= UEFI_CPER_RECORD_MIN_SIZE) &&
    439         (((record_size - 1) & record_size) == 0) && /* is power of 2 */
    440         (record_size >= 4096) /* PAGE_SIZE */
    441         )) {
    442         error_setg(errp, "ERST record_size %u is invalid", record_size);
    443         return;
    444     }
    445 
    446     /* Validity check header */
    447     if (!(
    448         (le64_to_cpu(header->magic) == ERST_STORE_MAGIC) &&
    449         ((le32_to_cpu(header->storage_offset) % record_size) == 0) &&
    450         (le16_to_cpu(header->version) == 0x0100) &&
    451         (le16_to_cpu(header->reserved) == 0)
    452         )) {
    453         error_setg(errp, "ERST backend storage header is invalid");
    454         return;
    455     }
    456 
    457     /* Check storage_size against record_size */
    458     if (((s->storage_size % record_size) != 0) ||
    459          (record_size > s->storage_size)) {
    460         error_setg(errp, "ACPI ERST requires storage size be multiple of "
    461             "record size (%uKiB)", record_size);
    462         return;
    463     }
    464 
    465     /* Compute offset of first and last record storage slot */
    466     s->first_record_index = le32_to_cpu(header->storage_offset)
    467         / record_size;
    468     s->last_record_index = (s->storage_size / record_size);
    469 }
    470 
    471 static void update_map_entry(ERSTDeviceState *s, unsigned index,
    472     uint64_t record_id)
    473 {
    474     if (index < s->last_record_index) {
    475         s->header->map[index] = cpu_to_le64(record_id);
    476     }
    477 }
    478 
    479 static unsigned find_next_empty_record_index(ERSTDeviceState *s)
    480 {
    481     unsigned rc = 0; /* 0 not a valid index */
    482     unsigned index = s->first_record_index;
    483 
    484     for (; index < s->last_record_index; ++index) {
    485         if (le64_to_cpu(s->header->map[index]) == ERST_UNSPECIFIED_RECORD_ID) {
    486             rc = index;
    487             break;
    488         }
    489     }
    490 
    491     return rc;
    492 }
    493 
    494 static unsigned lookup_erst_record(ERSTDeviceState *s,
    495     uint64_t record_identifier)
    496 {
    497     unsigned rc = 0; /* 0 not a valid index */
    498 
    499     /* Find the record_identifier in the map */
    500     if (record_identifier != ERST_UNSPECIFIED_RECORD_ID) {
    501         /*
    502          * Count number of valid records encountered, and
    503          * short-circuit the loop if identifier not found
    504          */
    505         uint32_t record_count = le32_to_cpu(s->header->record_count);
    506         unsigned count = 0;
    507         unsigned index;
    508         for (index = s->first_record_index; index < s->last_record_index &&
    509                 count < record_count; ++index) {
    510             if (le64_to_cpu(s->header->map[index]) == record_identifier) {
    511                 rc = index;
    512                 break;
    513             }
    514             if (le64_to_cpu(s->header->map[index]) !=
    515                 ERST_UNSPECIFIED_RECORD_ID) {
    516                 ++count;
    517             }
    518         }
    519     }
    520 
    521     return rc;
    522 }
    523 
    524 /*
    525  * ACPI 4.0: 17.4.1.1 Serialization Actions, also see
    526  * ACPI 4.0: 17.4.2.2 Operations - Reading 6.c and 2.c
    527  */
    528 static unsigned get_next_record_identifier(ERSTDeviceState *s,
    529     uint64_t *record_identifier, bool first)
    530 {
    531     unsigned found = 0;
    532     unsigned index;
    533 
    534     /* For operations needing to return 'first' record identifier */
    535     if (first) {
    536         /* Reset initial index to beginning */
    537         s->next_record_index = s->first_record_index;
    538     }
    539     index = s->next_record_index;
    540 
    541     *record_identifier = ERST_EMPTY_END_RECORD_ID;
    542 
    543     if (le32_to_cpu(s->header->record_count)) {
    544         for (; index < s->last_record_index; ++index) {
    545             if (le64_to_cpu(s->header->map[index]) !=
    546                     ERST_UNSPECIFIED_RECORD_ID) {
    547                     /* where to start next time */
    548                     s->next_record_index = index + 1;
    549                     *record_identifier = le64_to_cpu(s->header->map[index]);
    550                     found = 1;
    551                     break;
    552             }
    553         }
    554     }
    555     if (!found) {
    556         /* at end (ie scan complete), reset */
    557         s->next_record_index = s->first_record_index;
    558     }
    559 
    560     return STATUS_SUCCESS;
    561 }
    562 
    563 /* ACPI 4.0: 17.4.2.3 Operations - Clearing */
    564 static unsigned clear_erst_record(ERSTDeviceState *s)
    565 {
    566     unsigned rc = STATUS_RECORD_NOT_FOUND;
    567     unsigned index;
    568 
    569     /* Check for valid record identifier */
    570     if (!ERST_IS_VALID_RECORD_ID(s->record_identifier)) {
    571         return STATUS_FAILED;
    572     }
    573 
    574     index = lookup_erst_record(s, s->record_identifier);
    575     if (index) {
    576         /* No need to wipe record, just invalidate its map entry */
    577         uint32_t record_count;
    578         update_map_entry(s, index, ERST_UNSPECIFIED_RECORD_ID);
    579         record_count = le32_to_cpu(s->header->record_count);
    580         record_count -= 1;
    581         s->header->record_count = cpu_to_le32(record_count);
    582         rc = STATUS_SUCCESS;
    583     }
    584 
    585     return rc;
    586 }
    587 
    588 /* ACPI 4.0: 17.4.2.2 Operations - Reading */
    589 static unsigned read_erst_record(ERSTDeviceState *s)
    590 {
    591     unsigned rc = STATUS_RECORD_NOT_FOUND;
    592     unsigned exchange_length;
    593     unsigned index;
    594 
    595     /* Check if backend storage is empty */
    596     if (le32_to_cpu(s->header->record_count) == 0) {
    597         return STATUS_RECORD_STORE_EMPTY;
    598     }
    599 
    600     exchange_length = memory_region_size(&s->exchange_mr);
    601 
    602     /* Check for record identifier of all 0s */
    603     if (s->record_identifier == ERST_UNSPECIFIED_RECORD_ID) {
    604         /* Set to 'first' record in storage */
    605         get_next_record_identifier(s, &s->record_identifier, true);
    606         /* record_identifier is now a valid id, or all 1s */
    607     }
    608 
    609     /* Check for record identifier of all 1s */
    610     if (s->record_identifier == ERST_EMPTY_END_RECORD_ID) {
    611         return STATUS_FAILED;
    612     }
    613 
    614     /* Validate record_offset */
    615     if (s->record_offset > (exchange_length - UEFI_CPER_RECORD_MIN_SIZE)) {
    616         return STATUS_FAILED;
    617     }
    618 
    619     index = lookup_erst_record(s, s->record_identifier);
    620     if (index) {
    621         uint8_t *nvram;
    622         uint8_t *exchange;
    623         uint32_t record_length;
    624 
    625         /* Obtain pointer to the exchange buffer */
    626         exchange = memory_region_get_ram_ptr(&s->exchange_mr);
    627         exchange += s->record_offset;
    628         /* Obtain pointer to slot in storage */
    629         nvram = get_nvram_ptr_by_index(s, index);
    630         /* Validate CPER record_length */
    631         memcpy((uint8_t *)&record_length,
    632             &nvram[UEFI_CPER_RECORD_LENGTH_OFFSET],
    633             sizeof(uint32_t));
    634         record_length = le32_to_cpu(record_length);
    635         if (record_length < UEFI_CPER_RECORD_MIN_SIZE) {
    636             rc = STATUS_FAILED;
    637         }
    638         if (record_length > exchange_length - s->record_offset) {
    639             rc = STATUS_FAILED;
    640         }
    641         /* If all is ok, copy the record to the exchange buffer */
    642         if (rc != STATUS_FAILED) {
    643             memcpy(exchange, nvram, record_length);
    644             rc = STATUS_SUCCESS;
    645         }
    646     } else {
    647         /*
    648          * See "Reading : 'The steps performed by the platform ...' 2.c"
    649          * Set to 'first' record in storage
    650          */
    651         get_next_record_identifier(s, &s->record_identifier, true);
    652     }
    653 
    654     return rc;
    655 }
    656 
    657 /* ACPI 4.0: 17.4.2.1 Operations - Writing */
    658 static unsigned write_erst_record(ERSTDeviceState *s)
    659 {
    660     unsigned rc = STATUS_FAILED;
    661     unsigned exchange_length;
    662     unsigned index;
    663     uint64_t record_identifier;
    664     uint32_t record_length;
    665     uint8_t *exchange;
    666     uint8_t *nvram = NULL;
    667     bool record_found = false;
    668 
    669     exchange_length = memory_region_size(&s->exchange_mr);
    670 
    671     /* Validate record_offset */
    672     if (s->record_offset > (exchange_length - UEFI_CPER_RECORD_MIN_SIZE)) {
    673         return STATUS_FAILED;
    674     }
    675 
    676     /* Obtain pointer to record in the exchange buffer */
    677     exchange = memory_region_get_ram_ptr(&s->exchange_mr);
    678     exchange += s->record_offset;
    679 
    680     /* Validate CPER record_length */
    681     memcpy((uint8_t *)&record_length, &exchange[UEFI_CPER_RECORD_LENGTH_OFFSET],
    682         sizeof(uint32_t));
    683     record_length = le32_to_cpu(record_length);
    684     if (record_length < UEFI_CPER_RECORD_MIN_SIZE) {
    685         return STATUS_FAILED;
    686     }
    687     if (record_length > exchange_length - s->record_offset) {
    688         return STATUS_FAILED;
    689     }
    690 
    691     /* Extract record identifier */
    692     memcpy((uint8_t *)&record_identifier, &exchange[UEFI_CPER_RECORD_ID_OFFSET],
    693         sizeof(uint64_t));
    694     record_identifier = le64_to_cpu(record_identifier);
    695 
    696     /* Check for valid record identifier */
    697     if (!ERST_IS_VALID_RECORD_ID(record_identifier)) {
    698         return STATUS_FAILED;
    699     }
    700 
    701     index = lookup_erst_record(s, record_identifier);
    702     if (index) {
    703         /* Record found, overwrite existing record */
    704         nvram = get_nvram_ptr_by_index(s, index);
    705         record_found = true;
    706     } else {
    707         /* Record not found, not an overwrite, allocate for write */
    708         index = find_next_empty_record_index(s);
    709         if (index) {
    710             nvram = get_nvram_ptr_by_index(s, index);
    711         } else {
    712             /* All slots are occupied */
    713             rc = STATUS_NOT_ENOUGH_SPACE;
    714         }
    715     }
    716     if (nvram) {
    717         /* Write the record into the slot */
    718         memcpy(nvram, exchange, record_length);
    719         memset(nvram + record_length, 0xFF, exchange_length - record_length);
    720         /* If a new record, increment the record_count */
    721         if (!record_found) {
    722             uint32_t record_count;
    723             record_count = le32_to_cpu(s->header->record_count);
    724             record_count += 1; /* writing new record */
    725             s->header->record_count = cpu_to_le32(record_count);
    726         }
    727         update_map_entry(s, index, record_identifier);
    728         rc = STATUS_SUCCESS;
    729     }
    730 
    731     return rc;
    732 }
    733 
    734 /*******************************************************************/
    735 
    736 static uint64_t erst_rd_reg64(hwaddr addr,
    737     uint64_t reg, unsigned size)
    738 {
    739     uint64_t rdval;
    740     uint64_t mask;
    741     unsigned shift;
    742 
    743     if (size == sizeof(uint64_t)) {
    744         /* 64b access */
    745         mask = 0xFFFFFFFFFFFFFFFFUL;
    746         shift = 0;
    747     } else {
    748         /* 32b access */
    749         mask = 0x00000000FFFFFFFFUL;
    750         shift = ((addr & 0x4) == 0x4) ? 32 : 0;
    751     }
    752 
    753     rdval = reg;
    754     rdval >>= shift;
    755     rdval &= mask;
    756 
    757     return rdval;
    758 }
    759 
    760 static uint64_t erst_wr_reg64(hwaddr addr,
    761     uint64_t reg, uint64_t val, unsigned size)
    762 {
    763     uint64_t wrval;
    764     uint64_t mask;
    765     unsigned shift;
    766 
    767     if (size == sizeof(uint64_t)) {
    768         /* 64b access */
    769         mask = 0xFFFFFFFFFFFFFFFFUL;
    770         shift = 0;
    771     } else {
    772         /* 32b access */
    773         mask = 0x00000000FFFFFFFFUL;
    774         shift = ((addr & 0x4) == 0x4) ? 32 : 0;
    775     }
    776 
    777     val &= mask;
    778     val <<= shift;
    779     mask <<= shift;
    780     wrval = reg;
    781     wrval &= ~mask;
    782     wrval |= val;
    783 
    784     return wrval;
    785 }
    786 
    787 static void erst_reg_write(void *opaque, hwaddr addr,
    788     uint64_t val, unsigned size)
    789 {
    790     ERSTDeviceState *s = (ERSTDeviceState *)opaque;
    791 
    792     /*
    793      * NOTE: All actions/operations/side effects happen on the WRITE,
    794      * by this implementation's design. The READs simply return the
    795      * reg_value contents.
    796      */
    797     trace_acpi_erst_reg_write(addr, val, size);
    798 
    799     switch (addr) {
    800     case ERST_VALUE_OFFSET + 0:
    801     case ERST_VALUE_OFFSET + 4:
    802         s->reg_value = erst_wr_reg64(addr, s->reg_value, val, size);
    803         break;
    804     case ERST_ACTION_OFFSET + 0:
    805         /*
    806          * NOTE: all valid values written to this register are of the
    807          * ACTION_* variety. Thus there is no need to make this a 64-bit
    808          * register, 32-bits is appropriate. As such ERST_ACTION_OFFSET+4
    809          * is not needed.
    810          */
    811         switch (val) {
    812         case ACTION_BEGIN_WRITE_OPERATION:
    813         case ACTION_BEGIN_READ_OPERATION:
    814         case ACTION_BEGIN_CLEAR_OPERATION:
    815         case ACTION_BEGIN_DUMMY_WRITE_OPERATION:
    816         case ACTION_END_OPERATION:
    817             s->operation = val;
    818             break;
    819         case ACTION_SET_RECORD_OFFSET:
    820             s->record_offset = s->reg_value;
    821             break;
    822         case ACTION_EXECUTE_OPERATION:
    823             if ((uint8_t)s->reg_value == ERST_EXECUTE_OPERATION_MAGIC) {
    824                 s->busy_status = 1;
    825                 switch (s->operation) {
    826                 case ACTION_BEGIN_WRITE_OPERATION:
    827                     s->command_status = write_erst_record(s);
    828                     break;
    829                 case ACTION_BEGIN_READ_OPERATION:
    830                     s->command_status = read_erst_record(s);
    831                     break;
    832                 case ACTION_BEGIN_CLEAR_OPERATION:
    833                     s->command_status = clear_erst_record(s);
    834                     break;
    835                 case ACTION_BEGIN_DUMMY_WRITE_OPERATION:
    836                     s->command_status = STATUS_SUCCESS;
    837                     break;
    838                 case ACTION_END_OPERATION:
    839                     s->command_status = STATUS_SUCCESS;
    840                     break;
    841                 default:
    842                     s->command_status = STATUS_FAILED;
    843                     break;
    844                 }
    845                 s->busy_status = 0;
    846             }
    847             break;
    848         case ACTION_CHECK_BUSY_STATUS:
    849             s->reg_value = s->busy_status;
    850             break;
    851         case ACTION_GET_COMMAND_STATUS:
    852             s->reg_value = s->command_status;
    853             break;
    854         case ACTION_GET_RECORD_IDENTIFIER:
    855             s->command_status = get_next_record_identifier(s,
    856                                     &s->reg_value, false);
    857             break;
    858         case ACTION_SET_RECORD_IDENTIFIER:
    859             s->record_identifier = s->reg_value;
    860             break;
    861         case ACTION_GET_RECORD_COUNT:
    862             s->reg_value = le32_to_cpu(s->header->record_count);
    863             break;
    864         case ACTION_GET_ERROR_LOG_ADDRESS_RANGE:
    865             s->reg_value = (hwaddr)pci_get_bar_addr(PCI_DEVICE(s), 1);
    866             break;
    867         case ACTION_GET_ERROR_LOG_ADDRESS_LENGTH:
    868             s->reg_value = le32_to_cpu(s->header->record_size);
    869             break;
    870         case ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES:
    871             s->reg_value = 0x0; /* intentional, not NVRAM mode */
    872             break;
    873         case ACTION_GET_EXECUTE_OPERATION_TIMINGS:
    874             s->reg_value =
    875                 (100ULL << 32) | /* 100us max time */
    876                 (10ULL  <<  0) ; /*  10us min time */
    877             break;
    878         default:
    879             /* Unknown action/command, NOP */
    880             break;
    881         }
    882         break;
    883     default:
    884         /* This should not happen, but if it does, NOP */
    885         break;
    886     }
    887 }
    888 
    889 static uint64_t erst_reg_read(void *opaque, hwaddr addr,
    890                                 unsigned size)
    891 {
    892     ERSTDeviceState *s = (ERSTDeviceState *)opaque;
    893     uint64_t val = 0;
    894 
    895     switch (addr) {
    896     case ERST_ACTION_OFFSET + 0:
    897     case ERST_ACTION_OFFSET + 4:
    898         val = erst_rd_reg64(addr, s->reg_action, size);
    899         break;
    900     case ERST_VALUE_OFFSET + 0:
    901     case ERST_VALUE_OFFSET + 4:
    902         val = erst_rd_reg64(addr, s->reg_value, size);
    903         break;
    904     default:
    905         break;
    906     }
    907     trace_acpi_erst_reg_read(addr, val, size);
    908     return val;
    909 }
    910 
    911 static const MemoryRegionOps erst_reg_ops = {
    912     .read = erst_reg_read,
    913     .write = erst_reg_write,
    914     .endianness = DEVICE_NATIVE_ENDIAN,
    915 };
    916 
    917 /*******************************************************************/
    918 /*******************************************************************/
    919 static int erst_post_load(void *opaque, int version_id)
    920 {
    921     ERSTDeviceState *s = opaque;
    922 
    923     /* Recompute pointer to header */
    924     s->header = (ERSTStorageHeader *)get_nvram_ptr_by_index(s, 0);
    925     trace_acpi_erst_post_load(s->header, le32_to_cpu(s->header->record_size));
    926 
    927     return 0;
    928 }
    929 
    930 static const VMStateDescription erst_vmstate  = {
    931     .name = "acpi-erst",
    932     .version_id = 1,
    933     .minimum_version_id = 1,
    934     .post_load = erst_post_load,
    935     .fields = (VMStateField[]) {
    936         VMSTATE_UINT8(operation, ERSTDeviceState),
    937         VMSTATE_UINT8(busy_status, ERSTDeviceState),
    938         VMSTATE_UINT8(command_status, ERSTDeviceState),
    939         VMSTATE_UINT32(record_offset, ERSTDeviceState),
    940         VMSTATE_UINT64(reg_action, ERSTDeviceState),
    941         VMSTATE_UINT64(reg_value, ERSTDeviceState),
    942         VMSTATE_UINT64(record_identifier, ERSTDeviceState),
    943         VMSTATE_UINT32(next_record_index, ERSTDeviceState),
    944         VMSTATE_END_OF_LIST()
    945     }
    946 };
    947 
    948 static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
    949 {
    950     ERSTDeviceState *s = ACPIERST(pci_dev);
    951 
    952     trace_acpi_erst_realizefn_in();
    953 
    954     if (!s->hostmem) {
    955         error_setg(errp, "'" ACPI_ERST_MEMDEV_PROP "' property is not set");
    956         return;
    957     } else if (host_memory_backend_is_mapped(s->hostmem)) {
    958         error_setg(errp, "can't use already busy memdev: %s",
    959                    object_get_canonical_path_component(OBJECT(s->hostmem)));
    960         return;
    961     }
    962 
    963     s->hostmem_mr = host_memory_backend_get_memory(s->hostmem);
    964 
    965     /* HostMemoryBackend size will be multiple of PAGE_SIZE */
    966     s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp);
    967 
    968     /* Initialize backend storage and record_count */
    969     check_erst_backend_storage(s, errp);
    970 
    971     /* BAR 0: Programming registers */
    972     memory_region_init_io(&s->iomem_mr, OBJECT(pci_dev), &erst_reg_ops, s,
    973                           TYPE_ACPI_ERST, ERST_REG_SIZE);
    974     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->iomem_mr);
    975 
    976     /* BAR 1: Exchange buffer memory */
    977     memory_region_init_ram(&s->exchange_mr, OBJECT(pci_dev),
    978                             "erst.exchange",
    979                             le32_to_cpu(s->header->record_size), errp);
    980     pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
    981                         &s->exchange_mr);
    982 
    983     /* Include the backend storage in the migration stream */
    984     vmstate_register_ram_global(s->hostmem_mr);
    985 
    986     trace_acpi_erst_realizefn_out(s->storage_size);
    987 }
    988 
    989 static void erst_reset(DeviceState *dev)
    990 {
    991     ERSTDeviceState *s = ACPIERST(dev);
    992 
    993     trace_acpi_erst_reset_in(le32_to_cpu(s->header->record_count));
    994     s->operation = 0;
    995     s->busy_status = 0;
    996     s->command_status = STATUS_SUCCESS;
    997     s->record_identifier = ERST_UNSPECIFIED_RECORD_ID;
    998     s->record_offset = 0;
    999     s->next_record_index = s->first_record_index;
   1000     /* NOTE: first/last_record_index are computed only once */
   1001     trace_acpi_erst_reset_out(le32_to_cpu(s->header->record_count));
   1002 }
   1003 
   1004 static Property erst_properties[] = {
   1005     DEFINE_PROP_LINK(ACPI_ERST_MEMDEV_PROP, ERSTDeviceState, hostmem,
   1006                      TYPE_MEMORY_BACKEND, HostMemoryBackend *),
   1007     DEFINE_PROP_UINT32(ACPI_ERST_RECORD_SIZE_PROP, ERSTDeviceState,
   1008                      default_record_size, ERST_RECORD_SIZE),
   1009     DEFINE_PROP_END_OF_LIST(),
   1010 };
   1011 
   1012 static void erst_class_init(ObjectClass *klass, void *data)
   1013 {
   1014     DeviceClass *dc = DEVICE_CLASS(klass);
   1015     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
   1016 
   1017     trace_acpi_erst_class_init_in();
   1018     k->realize = erst_realizefn;
   1019     k->vendor_id = PCI_VENDOR_ID_REDHAT;
   1020     k->device_id = PCI_DEVICE_ID_REDHAT_ACPI_ERST;
   1021     k->revision = 0x00;
   1022     k->class_id = PCI_CLASS_OTHERS;
   1023     dc->reset = erst_reset;
   1024     dc->vmsd = &erst_vmstate;
   1025     dc->user_creatable = true;
   1026     dc->hotpluggable = false;
   1027     device_class_set_props(dc, erst_properties);
   1028     dc->desc = "ACPI Error Record Serialization Table (ERST) device";
   1029     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
   1030     trace_acpi_erst_class_init_out();
   1031 }
   1032 
   1033 static const TypeInfo erst_type_info = {
   1034     .name          = TYPE_ACPI_ERST,
   1035     .parent        = TYPE_PCI_DEVICE,
   1036     .class_init    = erst_class_init,
   1037     .instance_size = sizeof(ERSTDeviceState),
   1038     .interfaces = (InterfaceInfo[]) {
   1039         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
   1040         { }
   1041     }
   1042 };
   1043 
   1044 static void erst_register_types(void)
   1045 {
   1046     type_register_static(&erst_type_info);
   1047 }
   1048 
   1049 type_init(erst_register_types)