This code is called from the machine code (if ACPI supported) to generate the ACPI ERST table.
Signed-off-by: Eric DeVolder <eric.devol...@oracle.com> --- hw/acpi/erst.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) 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, -- 1.8.3.1