diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index 6e9bd2e..1f1dbbc 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -555,6 +555,220 @@ static const MemoryRegionOps erst_mem_ops = {
 /*******************************************************************/
 /*******************************************************************/
 
+/* ACPI 4.0: 17.4.1.2 Serialization Instruction Entries */
+static void build_serialization_instruction_entry(GArray *table_data,
+    uint8_t serialization_action,
+    uint8_t instruction,
+    uint8_t flags,
+    uint8_t register_bit_width,
+    uint64_t register_address,
+    uint64_t value,
+    uint64_t mask)
+{
+    /* ACPI 4.0: Table 17-18 Serialization Instruction Entry */
+    struct AcpiGenericAddress gas;
+
+    /* Serialization Action */
+    build_append_int_noprefix(table_data, serialization_action, 1);
+    /* Instruction */
+    build_append_int_noprefix(table_data, instruction         , 1);
+    /* Flags */
+    build_append_int_noprefix(table_data, flags               , 1);
+    /* Reserved */
+    build_append_int_noprefix(table_data, 0                   , 1);
+    /* Register Region */
+    gas.space_id = AML_SYSTEM_MEMORY;
+    gas.bit_width = register_bit_width;
+    gas.bit_offset = 0;
+    switch (register_bit_width) {
+    case 8:
+        gas.access_width = 1;
+        break;
+    case 16:
+        gas.access_width = 2;
+        break;
+    case 32:
+        gas.access_width = 3;
+        break;
+    case 64:
+        gas.access_width = 4;
+        break;
+    default:
+        gas.access_width = 0;
+        break;
+    }
+    gas.address = register_address;
+    build_append_gas_from_struct(table_data, &gas);
+    /* Value */
+    build_append_int_noprefix(table_data, value  , 8);
+    /* Mask */
+    build_append_int_noprefix(table_data, mask   , 8);
+}
+
+/* ACPI 4.0: 17.4.1 Serialization Action Table */
+void build_erst(GArray *table_data, BIOSLinker *linker, Object *erst_dev,
+    const char *oem_id, const char *oem_table_id)
+{
+    ERSTDeviceState *s = ACPIERST(erst_dev);
+    unsigned action;
+    unsigned erst_start = table_data->len;
+
+    s->bar0 = (hwaddr)pci_get_bar_addr(PCI_DEVICE(erst_dev), 0);
+    trace_acpi_erst_pci_bar_0(s->bar0);
+    s->bar1 = (hwaddr)pci_get_bar_addr(PCI_DEVICE(erst_dev), 1);
+    trace_acpi_erst_pci_bar_1(s->bar1);
+
+    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+    /* serialization_header_length */
+    build_append_int_noprefix(table_data, 48, 4);
+    /* reserved */
+    build_append_int_noprefix(table_data,  0, 4);
+    /*
+     * instruction_entry_count - changes to the number of serialization
+     * instructions in the ACTIONs below must be reflected in this
+     * pre-computed value.
+     */
+    build_append_int_noprefix(table_data, 29, 4);
+
+#define MASK8  0x00000000000000FFUL
+#define MASK16 0x000000000000FFFFUL
+#define MASK32 0x00000000FFFFFFFFUL
+#define MASK64 0xFFFFFFFFFFFFFFFFUL
+
+    for (action = 0; action < ACPI_ERST_MAX_ACTIONS; ++action) {
+        switch (action) {
+        case ACPI_ERST_ACTION_BEGIN_WRITE_OPERATION:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_BEGIN_READ_OPERATION:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_BEGIN_CLEAR_OPERATION:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_END_OPERATION:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_SET_RECORD_OFFSET:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER      , 0, 32,
+                s->bar0 + ERST_CSR_VALUE , 0, MASK32);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_EXECUTE_OPERATION:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_VALUE , ERST_EXECUTE_OPERATION_MAGIC, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_CHECK_BUSY_STATUS:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER_VALUE , 0, 32,
+                s->bar0 + ERST_CSR_VALUE, 0x01, MASK8);
+            break;
+        case ACPI_ERST_ACTION_GET_COMMAND_STATUS:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 32,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK8);
+            break;
+        case ACPI_ERST_ACTION_GET_RECORD_IDENTIFIER:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 64,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK64);
+            break;
+        case ACPI_ERST_ACTION_SET_RECORD_IDENTIFIER:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER      , 0, 64,
+                s->bar0 + ERST_CSR_VALUE , 0, MASK64);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_GET_RECORD_COUNT:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 32,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK32);
+            break;
+        case ACPI_ERST_ACTION_BEGIN_DUMMY_WRITE_OPERATION:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_RESERVED:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            break;
+        case ACPI_ERST_ACTION_GET_ERROR_LOG_ADDRESS_RANGE:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 64,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK64);
+            break;
+        case ACPI_ERST_ACTION_GET_ERROR_LOG_ADDRESS_LENGTH:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 64,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK32);
+            break;
+        case ACPI_ERST_ACTION_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 32,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK32);
+            break;
+        case ACPI_ERST_ACTION_GET_EXECUTE_OPERATION_TIMINGS:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_WRITE_REGISTER_VALUE, 0, 32,
+                s->bar0 + ERST_CSR_ACTION, action, MASK8);
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_READ_REGISTER       , 0, 64,
+                s->bar0 + ERST_CSR_VALUE, 0, MASK64);
+        default:
+            build_serialization_instruction_entry(table_data, action,
+                ACPI_ERST_INST_NOOP, 0, 0, 0, action, 0);
+            break;
+        }
+    }
+    build_header(linker, table_data,
+                 (void *)(table_data->data + erst_start),
+                 "ERST", table_data->len - erst_start,
+                 1, oem_id, oem_table_id);
+}
+
+/*******************************************************************/
+/*******************************************************************/
+
 static const VMStateDescription erst_vmstate  = {
     .name = "acpi-erst",
     .version_id = 1,
